xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/proto/metadata_minimal_module.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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_minimal_module.h"
18 
19 #include "perfetto/ext/base/base64.h"
20 #include "perfetto/ext/base/string_utils.h"
21 #include "src/trace_processor/importers/common/metadata_tracker.h"
22 #include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
23 #include "src/trace_processor/types/trace_processor_context.h"
24 
25 #include "protos/perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.h"
26 #include "protos/perfetto/trace/chrome/chrome_metadata.pbzero.h"
27 
28 namespace perfetto {
29 namespace trace_processor {
30 
31 using perfetto::protos::pbzero::TracePacket;
32 
MetadataMinimalModule(TraceProcessorContext * context)33 MetadataMinimalModule::MetadataMinimalModule(TraceProcessorContext* context)
34     : context_(context) {
35   RegisterForField(TracePacket::kChromeMetadataFieldNumber, context);
36   RegisterForField(TracePacket::kChromeBenchmarkMetadataFieldNumber, context);
37 }
38 
TokenizePacket(const protos::pbzero::TracePacket::Decoder & decoder,TraceBlobView *,int64_t,RefPtr<PacketSequenceStateGeneration>,uint32_t field_id)39 ModuleResult MetadataMinimalModule::TokenizePacket(
40     const protos::pbzero::TracePacket::Decoder& decoder,
41     TraceBlobView*,
42     int64_t,
43     RefPtr<PacketSequenceStateGeneration>,
44     uint32_t field_id) {
45   switch (field_id) {
46     case TracePacket::kChromeMetadataFieldNumber: {
47       ParseChromeMetadataPacket(decoder.chrome_metadata());
48       return ModuleResult::Handled();
49     }
50     case TracePacket::kChromeBenchmarkMetadataFieldNumber: {
51       ParseChromeBenchmarkMetadata(decoder.chrome_benchmark_metadata());
52       return ModuleResult::Handled();
53     }
54   }
55   return ModuleResult::Ignored();
56 }
57 
ParseChromeBenchmarkMetadata(ConstBytes blob)58 void MetadataMinimalModule::ParseChromeBenchmarkMetadata(ConstBytes blob) {
59   TraceStorage* storage = context_->storage.get();
60   MetadataTracker* metadata = context_->metadata_tracker.get();
61 
62   protos::pbzero::ChromeBenchmarkMetadata::Decoder packet(blob.data, blob.size);
63   if (packet.has_benchmark_name()) {
64     auto benchmark_name_id = storage->InternString(packet.benchmark_name());
65     metadata->SetMetadata(metadata::benchmark_name,
66                           Variadic::String(benchmark_name_id));
67   }
68   if (packet.has_benchmark_description()) {
69     auto benchmark_description_id =
70         storage->InternString(packet.benchmark_description());
71     metadata->SetMetadata(metadata::benchmark_description,
72                           Variadic::String(benchmark_description_id));
73   }
74   if (packet.has_label()) {
75     auto label_id = storage->InternString(packet.label());
76     metadata->SetMetadata(metadata::benchmark_label,
77                           Variadic::String(label_id));
78   }
79   if (packet.has_story_name()) {
80     auto story_name_id = storage->InternString(packet.story_name());
81     metadata->SetMetadata(metadata::benchmark_story_name,
82                           Variadic::String(story_name_id));
83   }
84   for (auto it = packet.story_tags(); it; ++it) {
85     auto story_tag_id = storage->InternString(*it);
86     metadata->AppendMetadata(metadata::benchmark_story_tags,
87                              Variadic::String(story_tag_id));
88   }
89   if (packet.has_benchmark_start_time_us()) {
90     metadata->SetMetadata(metadata::benchmark_start_time_us,
91                           Variadic::Integer(packet.benchmark_start_time_us()));
92   }
93   if (packet.has_story_run_time_us()) {
94     metadata->SetMetadata(metadata::benchmark_story_run_time_us,
95                           Variadic::Integer(packet.story_run_time_us()));
96   }
97   if (packet.has_story_run_index()) {
98     metadata->SetMetadata(metadata::benchmark_story_run_index,
99                           Variadic::Integer(packet.story_run_index()));
100   }
101   if (packet.has_had_failures()) {
102     metadata->SetMetadata(metadata::benchmark_had_failures,
103                           Variadic::Integer(packet.had_failures()));
104   }
105 }
106 
ParseChromeMetadataPacket(ConstBytes blob)107 void MetadataMinimalModule::ParseChromeMetadataPacket(ConstBytes blob) {
108   TraceStorage* storage = context_->storage.get();
109   MetadataTracker* metadata = context_->metadata_tracker.get();
110 
111   // TODO(b/322298334): There is no easy way to associate ChromeMetadataPacket
112   // with ChromeMetadata for the same instance, so we have opted for letters to
113   // differentiate Chrome instances for ChromeMetadataPacket. When a unifying
114   // Chrome instance ID is in place, update this code to use the same counter
115   // as ChromeMetadata values.
116   base::StackString<6> metadata_prefix(
117       "cr-%c-", static_cast<char>('a' + (chrome_metadata_count_ % 26)));
118   chrome_metadata_count_++;
119 
120   // Typed chrome metadata proto. The untyped metadata is parsed below in
121   // ParseChromeEvents().
122   protos::pbzero::ChromeMetadataPacket::Decoder packet_decoder(blob.data,
123                                                                blob.size);
124 
125   if (packet_decoder.has_chrome_version_code()) {
126     metadata->SetDynamicMetadata(
127         storage->InternString(base::StringView(metadata_prefix.ToStdString() +
128                                                "playstore_version_code")),
129         Variadic::Integer(packet_decoder.chrome_version_code()));
130   }
131   if (packet_decoder.has_enabled_categories()) {
132     auto categories_id =
133         storage->InternString(packet_decoder.enabled_categories());
134     metadata->SetDynamicMetadata(
135         storage->InternString(base::StringView(metadata_prefix.ToStdString() +
136                                                "enabled_categories")),
137         Variadic::String(categories_id));
138   }
139 
140   if (packet_decoder.has_field_trial_hashes()) {
141     std::string field_trials;
142 
143     // Add  a line break after every 2 field trial hashes to better utilize the
144     // UI space.
145     int line_size = 0;
146     for (auto it = packet_decoder.field_trial_hashes(); it; ++it) {
147       if (line_size == 2) {
148         field_trials.append("\n");
149         line_size = 1;
150       } else {
151         line_size++;
152       }
153 
154       perfetto::protos::pbzero::ChromeMetadataPacket::FinchHash::Decoder
155           field_trial(*it);
156 
157       base::StackString<45> field_trial_string(
158           "{ name: %u, group: %u } ", field_trial.name(), field_trial.group());
159 
160       field_trials.append(field_trial_string.ToStdString());
161     }
162 
163     StringId field_trials_string =
164         context_->storage->InternString(base::StringView(field_trials));
165     metadata->SetDynamicMetadata(
166         storage->InternString(base::StringView(metadata_prefix.ToStdString() +
167                                                "field_trial_hashes")),
168         Variadic::String(field_trials_string));
169   }
170 
171   if (packet_decoder.has_background_tracing_metadata()) {
172     auto background_tracing_metadata =
173         packet_decoder.background_tracing_metadata();
174 
175     std::string base64 = base::Base64Encode(background_tracing_metadata.data,
176                                             background_tracing_metadata.size);
177     metadata->SetDynamicMetadata(
178         storage->InternString("cr-background_tracing_metadata"),
179         Variadic::String(storage->InternString(base::StringView(base64))));
180 
181     protos::pbzero::BackgroundTracingMetadata::Decoder metadata_decoder(
182         background_tracing_metadata.data, background_tracing_metadata.size);
183     if (metadata_decoder.has_scenario_name_hash()) {
184       metadata->SetDynamicMetadata(
185           storage->InternString("cr-scenario_name_hash"),
186           Variadic::Integer(metadata_decoder.scenario_name_hash()));
187     }
188     auto triggered_rule = metadata_decoder.triggered_rule();
189     if (!metadata_decoder.has_triggered_rule())
190       return;
191     protos::pbzero::BackgroundTracingMetadata::TriggerRule::Decoder
192         triggered_rule_decoder(triggered_rule.data, triggered_rule.size);
193   }
194 }
195 
196 }  // namespace trace_processor
197 }  // namespace perfetto
198