• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/trace_processor/importers/proto/metadata_module.h"
18 
19 #include "perfetto/ext/base/string_utils.h"
20 #include "src/trace_processor/importers/common/slice_tracker.h"
21 #include "src/trace_processor/importers/common/track_tracker.h"
22 #include "src/trace_processor/importers/proto/metadata_tracker.h"
23 
24 #include "protos/perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.h"
25 #include "protos/perfetto/trace/chrome/chrome_metadata.pbzero.h"
26 #include "protos/perfetto/trace/trigger.pbzero.h"
27 
28 namespace perfetto {
29 namespace trace_processor {
30 
31 using perfetto::protos::pbzero::TracePacket;
32 
MetadataModule(TraceProcessorContext * context)33 MetadataModule::MetadataModule(TraceProcessorContext* context)
34     : context_(context) {
35   RegisterForField(TracePacket::kUiStateFieldNumber, context);
36   RegisterForField(TracePacket::kChromeMetadataFieldNumber, context);
37   RegisterForField(TracePacket::kChromeBenchmarkMetadataFieldNumber, context);
38   RegisterForField(TracePacket::kTriggerFieldNumber, context);
39 }
40 
TokenizePacket(const protos::pbzero::TracePacket::Decoder & decoder,TraceBlobView *,int64_t,PacketSequenceState *,uint32_t field_id)41 ModuleResult MetadataModule::TokenizePacket(
42     const protos::pbzero::TracePacket::Decoder& decoder,
43     TraceBlobView*,
44     int64_t,
45     PacketSequenceState*,
46     uint32_t field_id) {
47   switch (field_id) {
48     case TracePacket::kUiStateFieldNumber: {
49       auto ui_state = decoder.ui_state();
50       std::string base64 = base::Base64Encode(ui_state.data, ui_state.size);
51       StringId id = context_->storage->InternString(base::StringView(base64));
52       context_->metadata_tracker->SetMetadata(metadata::ui_state,
53                                               Variadic::String(id));
54       return ModuleResult::Handled();
55     }
56     case TracePacket::kChromeMetadataFieldNumber: {
57       ParseChromeMetadataPacket(decoder.chrome_metadata());
58       // Metadata packets may also contain untyped metadata due to a bug in
59       // Chrome <M92.
60       // TODO(crbug.com/1194914): Replace this with Handled() once the
61       // Chrome-side fix has propagated into all release channels.
62       return ModuleResult::Ignored();
63     }
64     case TracePacket::kChromeBenchmarkMetadataFieldNumber: {
65       ParseChromeBenchmarkMetadata(decoder.chrome_benchmark_metadata());
66       return ModuleResult::Handled();
67     }
68   }
69   return ModuleResult::Ignored();
70 }
71 
ParsePacket(const protos::pbzero::TracePacket::Decoder & decoder,const TimestampedTracePiece & ttp,uint32_t field_id)72 void MetadataModule::ParsePacket(
73     const protos::pbzero::TracePacket::Decoder& decoder,
74     const TimestampedTracePiece& ttp,
75     uint32_t field_id) {
76   switch (field_id) {
77     case TracePacket::kTriggerFieldNumber:
78       // We handle triggers at parse time rather at tokenization because
79       // we add slices to tables which need to happen post-sorting.
80       ParseTrigger(ttp.timestamp, decoder.trigger());
81       break;
82   }
83 }
84 
ParseChromeBenchmarkMetadata(ConstBytes blob)85 void MetadataModule::ParseChromeBenchmarkMetadata(ConstBytes blob) {
86   TraceStorage* storage = context_->storage.get();
87   MetadataTracker* metadata = context_->metadata_tracker.get();
88 
89   protos::pbzero::ChromeBenchmarkMetadata::Decoder packet(blob.data, blob.size);
90   if (packet.has_benchmark_name()) {
91     auto benchmark_name_id = storage->InternString(packet.benchmark_name());
92     metadata->SetMetadata(metadata::benchmark_name,
93                           Variadic::String(benchmark_name_id));
94   }
95   if (packet.has_benchmark_description()) {
96     auto benchmark_description_id =
97         storage->InternString(packet.benchmark_description());
98     metadata->SetMetadata(metadata::benchmark_description,
99                           Variadic::String(benchmark_description_id));
100   }
101   if (packet.has_label()) {
102     auto label_id = storage->InternString(packet.label());
103     metadata->SetMetadata(metadata::benchmark_label,
104                           Variadic::String(label_id));
105   }
106   if (packet.has_story_name()) {
107     auto story_name_id = storage->InternString(packet.story_name());
108     metadata->SetMetadata(metadata::benchmark_story_name,
109                           Variadic::String(story_name_id));
110   }
111   for (auto it = packet.story_tags(); it; ++it) {
112     auto story_tag_id = storage->InternString(*it);
113     metadata->AppendMetadata(metadata::benchmark_story_tags,
114                              Variadic::String(story_tag_id));
115   }
116   if (packet.has_benchmark_start_time_us()) {
117     metadata->SetMetadata(metadata::benchmark_start_time_us,
118                           Variadic::Integer(packet.benchmark_start_time_us()));
119   }
120   if (packet.has_story_run_time_us()) {
121     metadata->SetMetadata(metadata::benchmark_story_run_time_us,
122                           Variadic::Integer(packet.story_run_time_us()));
123   }
124   if (packet.has_story_run_index()) {
125     metadata->SetMetadata(metadata::benchmark_story_run_index,
126                           Variadic::Integer(packet.story_run_index()));
127   }
128   if (packet.has_had_failures()) {
129     metadata->SetMetadata(metadata::benchmark_had_failures,
130                           Variadic::Integer(packet.had_failures()));
131   }
132 }
133 
ParseChromeMetadataPacket(ConstBytes blob)134 void MetadataModule::ParseChromeMetadataPacket(ConstBytes blob) {
135   TraceStorage* storage = context_->storage.get();
136   MetadataTracker* metadata = context_->metadata_tracker.get();
137 
138   // Typed chrome metadata proto. The untyped metadata is parsed below in
139   // ParseChromeEvents().
140   protos::pbzero::ChromeMetadataPacket::Decoder packet(blob.data, blob.size);
141 
142   if (packet.has_chrome_version_code()) {
143     metadata->SetDynamicMetadata(
144         storage->InternString("cr-playstore_version_code"),
145         Variadic::Integer(packet.chrome_version_code()));
146   }
147   if (packet.has_enabled_categories()) {
148     auto categories_id = storage->InternString(packet.enabled_categories());
149     metadata->SetDynamicMetadata(storage->InternString("cr-enabled_categories"),
150                                  Variadic::String(categories_id));
151   }
152 }
153 
ParseTrigger(int64_t ts,ConstBytes blob)154 void MetadataModule::ParseTrigger(int64_t ts, ConstBytes blob) {
155   protos::pbzero::Trigger::Decoder trigger(blob.data, blob.size);
156   StringId cat_id = kNullStringId;
157   TrackId track_id = context_->track_tracker->GetOrCreateTriggerTrack();
158   StringId name_id = context_->storage->InternString(trigger.trigger_name());
159   context_->slice_tracker->Scoped(
160       ts, track_id, cat_id, name_id,
161       /* duration = */ 0,
162       [&trigger, this](ArgsTracker::BoundInserter* args_table) {
163         StringId producer_name_key =
164             context_->storage->InternString("producer_name");
165         args_table->AddArg(producer_name_key,
166                            Variadic::String(context_->storage->InternString(
167                                trigger.producer_name())));
168         StringId trusted_producer_uid_key =
169             context_->storage->InternString("trusted_producer_uid");
170         args_table->AddArg(trusted_producer_uid_key,
171                            Variadic::Integer(trigger.trusted_producer_uid()));
172       });
173 }
174 
175 }  // namespace trace_processor
176 }  // namespace perfetto
177