• 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/base64.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       producer_name_key_id_(context_->storage->InternString("producer_name")),
36       trusted_producer_uid_key_id_(
37           context_->storage->InternString("trusted_producer_uid")) {
38   RegisterForField(TracePacket::kUiStateFieldNumber, context);
39   RegisterForField(TracePacket::kChromeMetadataFieldNumber, context);
40   RegisterForField(TracePacket::kChromeBenchmarkMetadataFieldNumber, context);
41   RegisterForField(TracePacket::kTriggerFieldNumber, context);
42 }
43 
TokenizePacket(const protos::pbzero::TracePacket::Decoder & decoder,TraceBlobView *,int64_t,PacketSequenceState *,uint32_t field_id)44 ModuleResult MetadataModule::TokenizePacket(
45     const protos::pbzero::TracePacket::Decoder& decoder,
46     TraceBlobView*,
47     int64_t,
48     PacketSequenceState*,
49     uint32_t field_id) {
50   switch (field_id) {
51     case TracePacket::kUiStateFieldNumber: {
52       auto ui_state = decoder.ui_state();
53       std::string base64 = base::Base64Encode(ui_state.data, ui_state.size);
54       StringId id = context_->storage->InternString(base::StringView(base64));
55       context_->metadata_tracker->SetMetadata(metadata::ui_state,
56                                               Variadic::String(id));
57       return ModuleResult::Handled();
58     }
59     case TracePacket::kChromeMetadataFieldNumber: {
60       ParseChromeMetadataPacket(decoder.chrome_metadata());
61       // Metadata packets may also contain untyped metadata due to a bug in
62       // Chrome <M92.
63       // TODO(crbug.com/1194914): Replace this with Handled() once the
64       // Chrome-side fix has propagated into all release channels.
65       return ModuleResult::Ignored();
66     }
67     case TracePacket::kChromeBenchmarkMetadataFieldNumber: {
68       ParseChromeBenchmarkMetadata(decoder.chrome_benchmark_metadata());
69       return ModuleResult::Handled();
70     }
71   }
72   return ModuleResult::Ignored();
73 }
74 
ParsePacket(const protos::pbzero::TracePacket::Decoder & decoder,const TimestampedTracePiece & ttp,uint32_t field_id)75 void MetadataModule::ParsePacket(
76     const protos::pbzero::TracePacket::Decoder& decoder,
77     const TimestampedTracePiece& ttp,
78     uint32_t field_id) {
79   switch (field_id) {
80     case TracePacket::kTriggerFieldNumber:
81       // We handle triggers at parse time rather at tokenization because
82       // we add slices to tables which need to happen post-sorting.
83       ParseTrigger(ttp.timestamp, decoder.trigger());
84       break;
85   }
86 }
87 
ParseChromeBenchmarkMetadata(ConstBytes blob)88 void MetadataModule::ParseChromeBenchmarkMetadata(ConstBytes blob) {
89   TraceStorage* storage = context_->storage.get();
90   MetadataTracker* metadata = context_->metadata_tracker.get();
91 
92   protos::pbzero::ChromeBenchmarkMetadata::Decoder packet(blob.data, blob.size);
93   if (packet.has_benchmark_name()) {
94     auto benchmark_name_id = storage->InternString(packet.benchmark_name());
95     metadata->SetMetadata(metadata::benchmark_name,
96                           Variadic::String(benchmark_name_id));
97   }
98   if (packet.has_benchmark_description()) {
99     auto benchmark_description_id =
100         storage->InternString(packet.benchmark_description());
101     metadata->SetMetadata(metadata::benchmark_description,
102                           Variadic::String(benchmark_description_id));
103   }
104   if (packet.has_label()) {
105     auto label_id = storage->InternString(packet.label());
106     metadata->SetMetadata(metadata::benchmark_label,
107                           Variadic::String(label_id));
108   }
109   if (packet.has_story_name()) {
110     auto story_name_id = storage->InternString(packet.story_name());
111     metadata->SetMetadata(metadata::benchmark_story_name,
112                           Variadic::String(story_name_id));
113   }
114   for (auto it = packet.story_tags(); it; ++it) {
115     auto story_tag_id = storage->InternString(*it);
116     metadata->AppendMetadata(metadata::benchmark_story_tags,
117                              Variadic::String(story_tag_id));
118   }
119   if (packet.has_benchmark_start_time_us()) {
120     metadata->SetMetadata(metadata::benchmark_start_time_us,
121                           Variadic::Integer(packet.benchmark_start_time_us()));
122   }
123   if (packet.has_story_run_time_us()) {
124     metadata->SetMetadata(metadata::benchmark_story_run_time_us,
125                           Variadic::Integer(packet.story_run_time_us()));
126   }
127   if (packet.has_story_run_index()) {
128     metadata->SetMetadata(metadata::benchmark_story_run_index,
129                           Variadic::Integer(packet.story_run_index()));
130   }
131   if (packet.has_had_failures()) {
132     metadata->SetMetadata(metadata::benchmark_had_failures,
133                           Variadic::Integer(packet.had_failures()));
134   }
135 }
136 
ParseChromeMetadataPacket(ConstBytes blob)137 void MetadataModule::ParseChromeMetadataPacket(ConstBytes blob) {
138   TraceStorage* storage = context_->storage.get();
139   MetadataTracker* metadata = context_->metadata_tracker.get();
140 
141   // Typed chrome metadata proto. The untyped metadata is parsed below in
142   // ParseChromeEvents().
143   protos::pbzero::ChromeMetadataPacket::Decoder packet(blob.data, blob.size);
144 
145   if (packet.has_chrome_version_code()) {
146     metadata->SetDynamicMetadata(
147         storage->InternString("cr-playstore_version_code"),
148         Variadic::Integer(packet.chrome_version_code()));
149   }
150   if (packet.has_enabled_categories()) {
151     auto categories_id = storage->InternString(packet.enabled_categories());
152     metadata->SetDynamicMetadata(storage->InternString("cr-enabled_categories"),
153                                  Variadic::String(categories_id));
154   }
155 }
156 
ParseTrigger(int64_t ts,ConstBytes blob)157 void MetadataModule::ParseTrigger(int64_t ts, ConstBytes blob) {
158   protos::pbzero::Trigger::Decoder trigger(blob.data, blob.size);
159   StringId cat_id = kNullStringId;
160   TrackId track_id = context_->track_tracker->GetOrCreateTriggerTrack();
161   StringId name_id = context_->storage->InternString(trigger.trigger_name());
162   context_->slice_tracker->Scoped(
163       ts, track_id, cat_id, name_id,
164       /* duration = */ 0,
165       [&trigger, this](ArgsTracker::BoundInserter* args_table) {
166         StringId producer_name =
167             context_->storage->InternString(trigger.producer_name());
168         if (!producer_name.is_null()) {
169           args_table->AddArg(producer_name_key_id_,
170                              Variadic::String(producer_name));
171         }
172         if (trigger.has_trusted_producer_uid()) {
173           args_table->AddArg(trusted_producer_uid_key_id_,
174                              Variadic::Integer(trigger.trusted_producer_uid()));
175         }
176       });
177 }
178 
179 }  // namespace trace_processor
180 }  // namespace perfetto
181