xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/common/track_tracker.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2019 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/common/track_tracker.h"
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <optional>
22 #include <utility>
23 
24 #include "perfetto/base/compiler.h"
25 #include "perfetto/base/logging.h"
26 #include "perfetto/ext/base/string_view.h"
27 #include "src/trace_processor/importers/common/args_tracker.h"
28 #include "src/trace_processor/importers/common/cpu_tracker.h"
29 #include "src/trace_processor/importers/common/process_track_translation_table.h"
30 #include "src/trace_processor/importers/common/tracks_internal.h"
31 #include "src/trace_processor/storage/trace_storage.h"
32 #include "src/trace_processor/tables/track_tables_py.h"
33 #include "src/trace_processor/types/trace_processor_context.h"
34 #include "src/trace_processor/types/variadic.h"
35 
36 namespace perfetto::trace_processor {
37 namespace {
38 
IsLegacyStringIdNameAllowed(tracks::TrackClassification classification)39 bool IsLegacyStringIdNameAllowed(tracks::TrackClassification classification) {
40   // **DO NOT** add new values here. Use TrackTracker::AutoName instead.
41   return classification == tracks::unknown;
42 }
43 
IsLegacyCharArrayNameAllowed(tracks::TrackClassification classification)44 bool IsLegacyCharArrayNameAllowed(tracks::TrackClassification classification) {
45   // **DO NOT** add new values here. Use TrackTracker::AutoName instead.
46   return classification == tracks::cpu_funcgraph ||
47          classification == tracks::cpu_irq ||
48          classification == tracks::cpu_mali_irq ||
49          classification == tracks::cpu_napi_gro ||
50          classification == tracks::cpu_softirq ||
51          classification == tracks::pkvm_hypervisor;
52 }
53 
54 }  // namespace
55 
TrackTracker(TraceProcessorContext * context)56 TrackTracker::TrackTracker(TraceProcessorContext* context)
57     : source_key_(context->storage->InternString("source")),
58       trace_id_key_(context->storage->InternString("trace_id")),
59       trace_id_is_process_scoped_key_(
60           context->storage->InternString("trace_id_is_process_scoped")),
61       source_scope_key_(context->storage->InternString("source_scope")),
62       category_key_(context->storage->InternString("category")),
63       scope_id_(context->storage->InternString("scope")),
64       cookie_id_(context->storage->InternString("cookie")),
65       fuchsia_source_(context->storage->InternString("fuchsia")),
66       chrome_source_(context->storage->InternString("chrome")),
67       utid_id_(context->storage->InternString("utid")),
68       upid_id_(context->storage->InternString("upid")),
69       cpu_id_(context->storage->InternString("cpu")),
70       uid_id_(context->storage->InternString("uid")),
71       gpu_id_(context->storage->InternString("gpu")),
72       name_id_(context->storage->InternString("name")),
73       context_(context),
74       args_tracker_(context) {}
75 
CreateTrack(tracks::TrackClassification classification,std::optional<Dimensions> dimensions,const TrackName & name)76 TrackId TrackTracker::CreateTrack(tracks::TrackClassification classification,
77                                   std::optional<Dimensions> dimensions,
78                                   const TrackName& name) {
79   tables::TrackTable::Row row(StringIdFromTrackName(classification, name));
80   row.classification =
81       context_->storage->InternString(tracks::ToString(classification));
82   if (dimensions) {
83     row.dimension_arg_set_id = dimensions->arg_set_id;
84   }
85   row.machine_id = context_->machine_id();
86 
87   return context_->storage->mutable_track_table()->Insert(row).id;
88 }
89 
CreateProcessTrack(tracks::TrackClassification classification,UniquePid upid,std::optional<Dimensions> dims,const TrackName & name)90 TrackId TrackTracker::CreateProcessTrack(
91     tracks::TrackClassification classification,
92     UniquePid upid,
93     std::optional<Dimensions> dims,
94     const TrackName& name) {
95   Dimensions dims_id =
96       dims ? *dims : SingleDimension(upid_id_, Variadic::Integer(upid));
97 
98   tables::ProcessTrackTable::Row row(
99       StringIdFromTrackName(classification, name));
100   row.upid = upid;
101   row.dimension_arg_set_id = dims_id.arg_set_id;
102   row.classification =
103       context_->storage->InternString(tracks::ToString(classification));
104   row.machine_id = context_->machine_id();
105 
106   return context_->storage->mutable_process_track_table()->Insert(row).id;
107 }
108 
CreateThreadTrack(tracks::TrackClassification classification,UniqueTid utid,const TrackName & name)109 TrackId TrackTracker::CreateThreadTrack(
110     tracks::TrackClassification classification,
111     UniqueTid utid,
112     const TrackName& name) {
113   Dimensions dims_id = SingleDimension(utid_id_, Variadic::Integer(utid));
114 
115   tables::ThreadTrackTable::Row row(
116       StringIdFromTrackName(classification, name));
117   row.utid = utid;
118   row.classification =
119       context_->storage->InternString(tracks::ToString(classification));
120   row.dimension_arg_set_id = dims_id.arg_set_id;
121   row.machine_id = context_->machine_id();
122 
123   return context_->storage->mutable_thread_track_table()->Insert(row).id;
124 }
125 
InternProcessTrack(tracks::TrackClassification classification,UniquePid upid,const TrackName & name)126 TrackId TrackTracker::InternProcessTrack(
127     tracks::TrackClassification classification,
128     UniquePid upid,
129     const TrackName& name) {
130   Dimensions dims_id = SingleDimension(upid_id_, Variadic::Integer(upid));
131 
132   auto* it = tracks_.Find({classification, dims_id});
133   if (it)
134     return *it;
135 
136   TrackId track_id =
137       CreateProcessTrack(classification, upid, std::nullopt, name);
138   tracks_[{classification, dims_id}] = track_id;
139   return track_id;
140 }
141 
InternThreadTrack(UniqueTid utid,const TrackName & name)142 TrackId TrackTracker::InternThreadTrack(UniqueTid utid, const TrackName& name) {
143   Dimensions dims = SingleDimension(utid_id_, Variadic::Integer(utid));
144 
145   auto* it = tracks_.Find({tracks::thread, dims});
146   if (it)
147     return *it;
148   TrackId track_id = CreateThreadTrack(tracks::thread, utid, name);
149   tracks_[{tracks::thread, dims}] = track_id;
150   return track_id;
151 }
152 
InternCpuTrack(tracks::TrackClassification classification,uint32_t cpu,const TrackName & name)153 TrackId TrackTracker::InternCpuTrack(tracks::TrackClassification classification,
154                                      uint32_t cpu,
155                                      const TrackName& name) {
156   MarkCpuValid(cpu);
157 
158   Dimensions dims_id = SingleDimension(cpu_id_, Variadic::Integer(cpu));
159   auto* it = tracks_.Find({classification, dims_id});
160   if (it) {
161     return *it;
162   }
163 
164   tables::CpuTrackTable::Row row(StringIdFromTrackName(classification, name));
165   row.cpu = cpu;
166   row.machine_id = context_->machine_id();
167   row.classification =
168       context_->storage->InternString(tracks::ToString(classification));
169   row.dimension_arg_set_id = dims_id.arg_set_id;
170 
171   TrackId track_id =
172       context_->storage->mutable_cpu_track_table()->Insert(row).id;
173   tracks_[{classification, dims_id}] = track_id;
174   return track_id;
175 }
176 
LegacyInternGpuTrack(const tables::GpuTrackTable::Row & row)177 TrackId TrackTracker::LegacyInternGpuTrack(
178     const tables::GpuTrackTable::Row& row) {
179   DimensionsBuilder dims_builder = CreateDimensionsBuilder();
180   dims_builder.AppendGpu(row.context_id.value_or(0));
181   if (row.scope != kNullStringId) {
182     dims_builder.AppendDimension(scope_id_, Variadic::String(row.scope));
183   }
184   dims_builder.AppendName(row.name);
185   Dimensions dims_id = std::move(dims_builder).Build();
186 
187   TrackMapKey key;
188   key.classification = tracks::unknown;
189   key.dimensions = dims_id;
190 
191   auto* it = tracks_.Find(key);
192   if (it)
193     return *it;
194 
195   auto row_copy = row;
196   row_copy.classification =
197       context_->storage->InternString(tracks::ToString(tracks::unknown));
198   row_copy.dimension_arg_set_id = dims_id.arg_set_id;
199   row_copy.machine_id = context_->machine_id();
200 
201   TrackId track_id =
202       context_->storage->mutable_gpu_track_table()->Insert(row_copy).id;
203   tracks_[key] = track_id;
204   return track_id;
205 }
206 
LegacyInternLegacyChromeAsyncTrack(StringId raw_name,uint32_t upid,int64_t trace_id,bool trace_id_is_process_scoped,StringId source_scope)207 TrackId TrackTracker::LegacyInternLegacyChromeAsyncTrack(
208     StringId raw_name,
209     uint32_t upid,
210     int64_t trace_id,
211     bool trace_id_is_process_scoped,
212     StringId source_scope) {
213   DimensionsBuilder dims_builder = CreateDimensionsBuilder();
214   dims_builder.AppendDimension(scope_id_, Variadic::String(source_scope));
215   if (trace_id_is_process_scoped) {
216     dims_builder.AppendUpid(upid);
217   }
218   dims_builder.AppendDimension(cookie_id_, Variadic::Integer(trace_id));
219 
220   const StringId name =
221       context_->process_track_translation_table->TranslateName(raw_name);
222 
223   TrackMapKey key;
224   key.classification = tracks::unknown;
225   key.dimensions = std::move(dims_builder).Build();
226 
227   auto* it = tracks_.Find(key);
228   if (it) {
229     if (name != kNullStringId) {
230       // The track may have been created for an end event without name. In
231       // that case, update it with this event's name.
232       auto& tracks = *context_->storage->mutable_track_table();
233       auto rr = *tracks.FindById(*it);
234       if (rr.name() == kNullStringId) {
235         rr.set_name(name);
236       }
237     }
238     return *it;
239   }
240 
241   // Legacy async tracks are always drawn in the context of a process, even if
242   // the ID's scope is global.
243   tables::ProcessTrackTable::Row track(name);
244   track.upid = upid;
245   track.classification =
246       context_->storage->InternString(tracks::ToString(tracks::unknown));
247   track.dimension_arg_set_id = key.dimensions->arg_set_id;
248   track.machine_id = context_->machine_id();
249 
250   TrackId id =
251       context_->storage->mutable_process_track_table()->Insert(track).id;
252   tracks_[key] = id;
253 
254   args_tracker_.AddArgsTo(id)
255       .AddArg(source_key_, Variadic::String(chrome_source_))
256       .AddArg(trace_id_key_, Variadic::Integer(trace_id))
257       .AddArg(trace_id_is_process_scoped_key_,
258               Variadic::Boolean(trace_id_is_process_scoped))
259       .AddArg(source_scope_key_, Variadic::String(source_scope));
260   args_tracker_.Flush();
261 
262   return id;
263 }
264 
StringIdFromTrackName(tracks::TrackClassification classification,const TrackTracker::TrackName & name)265 StringId TrackTracker::StringIdFromTrackName(
266     tracks::TrackClassification classification,
267     const TrackTracker::TrackName& name) {
268   switch (name.index()) {
269     case base::variant_index<TrackName, AutoName>():
270       return kNullStringId;
271     case base::variant_index<TrackName, LegacyStringIdName>():
272       PERFETTO_DCHECK(IsLegacyStringIdNameAllowed(classification));
273       return std::get<LegacyStringIdName>(name).id;
274     case base::variant_index<TrackName, LegacyCharArrayName>():
275       PERFETTO_DCHECK(IsLegacyCharArrayNameAllowed(classification));
276       return context_->storage->InternString(
277           std::get<LegacyCharArrayName>(name).name);
278   }
279   PERFETTO_FATAL("For GCC");
280 }
281 
AddTrack(const tracks::BlueprintBase & blueprint,StringId name,StringId counter_unit,GlobalArgsTracker::CompactArg * d_args,uint32_t d_size,const SetArgsCallback & args)282 TrackId TrackTracker::AddTrack(const tracks::BlueprintBase& blueprint,
283                                StringId name,
284                                StringId counter_unit,
285                                GlobalArgsTracker::CompactArg* d_args,
286                                uint32_t d_size,
287                                const SetArgsCallback& args) {
288   const auto* dims = blueprint.dimension_blueprints.data();
289   for (uint32_t i = 0; i < d_size; ++i) {
290     StringId key = context_->storage->InternString(
291         base::StringView(dims[i].name.data(), dims[i].name.size()));
292     d_args[i].key = key;
293     d_args[i].flat_key = key;
294   }
295 
296   tables::TrackTable::Row row(name);
297   row.machine_id = context_->machine_id();
298   row.classification = context_->storage->InternString(base::StringView(
299       blueprint.classification.data(), blueprint.classification.size()));
300   if (d_size > 0) {
301     row.dimension_arg_set_id =
302         context_->global_args_tracker->AddArgSet(d_args, 0, d_size);
303   }
304   row.event_type = context_->storage->InternString(blueprint.event_type);
305   row.counter_unit = counter_unit;
306   TrackId id = context_->storage->mutable_track_table()->Insert(row).id;
307   if (args) {
308     auto inserter = args_tracker_.AddArgsTo(id);
309     args(inserter);
310     args_tracker_.Flush();
311   }
312   return id;
313 }
314 
MarkCpuValid(uint32_t cpu)315 void TrackTracker::MarkCpuValid(uint32_t cpu) {
316   context_->cpu_tracker->MarkCpuValid(cpu);
317 }
318 
319 }  // namespace perfetto::trace_processor
320