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 <tuple>
23
24 #include "perfetto/ext/base/string_view.h"
25 #include "src/trace_processor/importers/common/args_tracker.h"
26 #include "src/trace_processor/importers/common/cpu_tracker.h"
27 #include "src/trace_processor/importers/common/process_track_translation_table.h"
28 #include "src/trace_processor/importers/common/tracks.h"
29 #include "src/trace_processor/importers/common/tracks_common.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
TrackTracker(TraceProcessorContext * context)38 TrackTracker::TrackTracker(TraceProcessorContext* context)
39 : source_key_(context->storage->InternString("source")),
40 trace_id_key_(context->storage->InternString("trace_id")),
41 trace_id_is_process_scoped_key_(
42 context->storage->InternString("trace_id_is_process_scoped")),
43 upid_(context->storage->InternString("upid")),
44 source_scope_key_(context->storage->InternString("source_scope")),
45 chrome_source_(context->storage->InternString("chrome")),
46 context_(context),
47 args_tracker_(context) {}
48
InternLegacyAsyncTrack(StringId raw_name,uint32_t upid,int64_t trace_id,bool trace_id_is_process_scoped,StringId source_scope)49 TrackId TrackTracker::InternLegacyAsyncTrack(StringId raw_name,
50 uint32_t upid,
51 int64_t trace_id,
52 bool trace_id_is_process_scoped,
53 StringId source_scope) {
54 const StringId name =
55 context_->process_track_translation_table->TranslateName(raw_name);
56
57 auto args_fn = [&](ArgsTracker::BoundInserter& inserter) {
58 inserter.AddArg(source_key_, Variadic::String(chrome_source_))
59 .AddArg(trace_id_key_, Variadic::Integer(trace_id))
60 .AddArg(trace_id_is_process_scoped_key_,
61 Variadic::Boolean(trace_id_is_process_scoped))
62 .AddArg(upid_, Variadic::UnsignedInteger(upid))
63 .AddArg(source_scope_key_, Variadic::String(source_scope));
64 };
65 TrackId track_id;
66 bool inserted;
67 if (trace_id_is_process_scoped) {
68 static constexpr auto kBlueprint = tracks::SliceBlueprint(
69 "legacy_async_process_slice",
70 tracks::DimensionBlueprints(tracks::kProcessDimensionBlueprint,
71 tracks::StringDimensionBlueprint("scope"),
72 tracks::LongDimensionBlueprint("cookie")),
73 tracks::DynamicNameBlueprint());
74 std::tie(track_id, inserted) = InternTrackInner(
75 kBlueprint,
76 tracks::Dimensions(upid, context_->storage->GetString(source_scope),
77 trace_id),
78 tracks::DynamicName(name), args_fn);
79 } else {
80 static constexpr auto kBlueprint = tracks::SliceBlueprint(
81 "legacy_async_global_slice",
82 tracks::DimensionBlueprints(tracks::StringDimensionBlueprint("scope"),
83 tracks::LongDimensionBlueprint("cookie")),
84 tracks::DynamicNameBlueprint());
85 std::tie(track_id, inserted) = InternTrackInner(
86 kBlueprint,
87 tracks::Dimensions(context_->storage->GetString(source_scope),
88 trace_id),
89 tracks::DynamicName(name), args_fn);
90 }
91 // The track may have been created for an end event without name. In
92 // that case, update it with this event's name.
93 if (inserted && name != kNullStringId) {
94 auto& tracks = *context_->storage->mutable_track_table();
95 auto rr = *tracks.FindById(track_id);
96 if (rr.name() == kNullStringId) {
97 rr.set_name(name);
98 }
99 }
100 return track_id;
101 }
102
AddTrack(const tracks::BlueprintBase & blueprint,StringId name,StringId counter_unit,GlobalArgsTracker::CompactArg * d_args,uint32_t d_size,const SetArgsCallback & args)103 TrackId TrackTracker::AddTrack(const tracks::BlueprintBase& blueprint,
104 StringId name,
105 StringId counter_unit,
106 GlobalArgsTracker::CompactArg* d_args,
107 uint32_t d_size,
108 const SetArgsCallback& args) {
109 tables::TrackTable::Row row(name);
110 const auto* dims = blueprint.dimension_blueprints.data();
111 for (uint32_t i = 0; i < d_size; ++i) {
112 base::StringView str(dims[i].name.data(), dims[i].name.size());
113 if (str == "cpu" && d_args[i].value.type == Variadic::kInt) {
114 context_->cpu_tracker->MarkCpuValid(
115 static_cast<uint32_t>(d_args[i].value.int_value));
116 } else if (str == "utid" && d_args[i].value.type == Variadic::kInt) {
117 row.utid = static_cast<uint32_t>(d_args[i].value.int_value);
118 } else if (str == "upid" && d_args[i].value.type == Variadic::kInt) {
119 row.upid = static_cast<uint32_t>(d_args[i].value.int_value);
120 }
121 StringId key = context_->storage->InternString(str);
122 d_args[i].key = key;
123 d_args[i].flat_key = key;
124 }
125
126 row.machine_id = context_->machine_id();
127 row.type = context_->storage->InternString(
128 base::StringView(blueprint.type.data(), blueprint.type.size()));
129 if (d_size > 0) {
130 row.dimension_arg_set_id =
131 context_->global_args_tracker->AddArgSet(d_args, 0, d_size);
132 }
133 row.event_type = context_->storage->InternString(blueprint.event_type);
134 row.counter_unit = counter_unit;
135 TrackId id = context_->storage->mutable_track_table()->Insert(row).id;
136 if (args) {
137 auto inserter = args_tracker_.AddArgsTo(id);
138 args(inserter);
139 args_tracker_.Flush();
140 }
141 return id;
142 }
143
144 } // namespace perfetto::trace_processor
145