Skip to content

Commit 0ea4ed1

Browse files
committed
tp: Make metadata per trace- per machine
CHROME_STDLIB_MANUAL_ROLL=Breaking change covering entire tp
1 parent 12dcdeb commit 0ea4ed1

35 files changed

+644
-290
lines changed

Android.bp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14513,6 +14513,7 @@ filegroup {
1451314513
"src/trace_processor/importers/common/event_tracker.cc",
1451414514
"src/trace_processor/importers/common/flow_tracker.cc",
1451514515
"src/trace_processor/importers/common/global_args_tracker.cc",
14516+
"src/trace_processor/importers/common/global_metadata_tracker.cc",
1451614517
"src/trace_processor/importers/common/import_logs_tracker.cc",
1451714518
"src/trace_processor/importers/common/jit_cache.cc",
1451814519
"src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.cc",

BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,6 +2201,8 @@ perfetto_filegroup(
22012201
"src/trace_processor/importers/common/flow_tracker.h",
22022202
"src/trace_processor/importers/common/global_args_tracker.cc",
22032203
"src/trace_processor/importers/common/global_args_tracker.h",
2204+
"src/trace_processor/importers/common/global_metadata_tracker.cc",
2205+
"src/trace_processor/importers/common/global_metadata_tracker.h",
22042206
"src/trace_processor/importers/common/import_logs_tracker.cc",
22052207
"src/trace_processor/importers/common/import_logs_tracker.h",
22062208
"src/trace_processor/importers/common/jit_cache.cc",

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ Unreleased:
4242
* Breaking change: `machine_id` is now a non-nullable column in all Trace
4343
Processor tables. The host machine is now consistently represented by 0
4444
instead of NULL.
45+
* Breaking change: Refactored the `metadata` table to support multi-trace
46+
and multi-machine traces. Added `trace_id` and `machine_id` columns to
47+
associate entries with their specific context.
4548
* Added support for R8 retracing during deobfuscation. Improves
4649
deobfuscation quality for some supported profiling types.
4750
UI:

src/trace_processor/export_json_unittest.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "src/trace_processor/importers/common/args_tracker.h"
3939
#include "src/trace_processor/importers/common/cpu_tracker.h"
4040
#include "src/trace_processor/importers/common/event_tracker.h"
41+
#include "src/trace_processor/importers/common/global_metadata_tracker.h"
4142
#include "src/trace_processor/importers/common/machine_tracker.h"
4243
#include "src/trace_processor/importers/common/metadata_tracker.h"
4344
#include "src/trace_processor/importers/common/process_track_translation_table.h"
@@ -94,8 +95,12 @@ class ExportJsonTest : public ::testing::Test {
9495
context_.event_tracker.reset(new EventTracker(&context_));
9596
context_.track_tracker.reset(new TrackTracker(&context_));
9697
context_.cpu_tracker.reset(new CpuTracker(&context_));
97-
context_.metadata_tracker.reset(
98-
new MetadataTracker(context_.storage.get()));
98+
context_.global_metadata_tracker.reset(
99+
new GlobalMetadataTracker(context_.storage.get()));
100+
context_.trace_state =
101+
TraceProcessorContextPtr<TraceProcessorContext::TraceState>::MakeRoot(
102+
TraceProcessorContext::TraceState{TraceId(0)});
103+
context_.metadata_tracker.reset(new MetadataTracker(&context_));
99104
context_.process_tracker.reset(new ProcessTracker(&context_));
100105
context_.process_track_translation_table.reset(
101106
new ProcessTrackTranslationTable(context_.storage.get()));

src/trace_processor/forwarding_trace_parser.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ base::Status ForwardingTraceParser::Init(const TraceBlobView& blob) {
128128
// TODO(b/334978369) Make sure kProtoTraceType and kSystraceTraceType are
129129
// parsed first so that we do not get issues with
130130
// SetPidZeroIsUpidZeroIdleProcess()
131-
trace_context_ = input_context_->ForkContextForTrace(file_id_.value, 0);
131+
trace_context_ = input_context_->ForkContextForTrace(file_id_, 0);
132132
if (trace_type_ == kProtoTraceType || trace_type_ == kSystraceTraceType) {
133133
trace_context_->process_tracker->SetPidZeroIsUpidZeroIdleProcess();
134134
}

src/trace_processor/importers/android_bugreport/android_log_unittest.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "src/trace_processor/importers/android_bugreport/android_log_event.h"
3131
#include "src/trace_processor/importers/android_bugreport/android_log_event_parser.h"
3232
#include "src/trace_processor/importers/common/clock_tracker.h"
33+
#include "src/trace_processor/importers/common/global_metadata_tracker.h"
3334
#include "src/trace_processor/importers/common/machine_tracker.h"
3435
#include "src/trace_processor/importers/common/metadata_tracker.h"
3536
#include "src/trace_processor/sorter/trace_sorter.h"
@@ -70,8 +71,12 @@ class AndroidLogReaderTest : public ::testing::Test {
7071
std::make_unique<ClockSynchronizerListenerImpl>(&context_);
7172
context_.clock_tracker =
7273
std::make_unique<ClockTracker>(std::move(clock_tracker_listener));
73-
context_.metadata_tracker =
74-
std::make_unique<MetadataTracker>(context_.storage.get());
74+
context_.global_metadata_tracker =
75+
std::make_unique<GlobalMetadataTracker>(context_.storage.get());
76+
context_.trace_state =
77+
TraceProcessorContextPtr<TraceProcessorContext::TraceState>::MakeRoot(
78+
TraceProcessorContext::TraceState{TraceId(0)});
79+
context_.metadata_tracker = std::make_unique<MetadataTracker>(&context_);
7580
context_.clock_tracker->SetTraceTimeClock(
7681
protos::pbzero::ClockSnapshot::Clock::REALTIME);
7782
context_.sorter = std::make_unique<TraceSorter>(

src/trace_processor/importers/common/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ source_set("common") {
3737
"flow_tracker.h",
3838
"global_args_tracker.cc",
3939
"global_args_tracker.h",
40+
"global_metadata_tracker.cc",
41+
"global_metadata_tracker.h",
4042
"import_logs_tracker.cc",
4143
"import_logs_tracker.h",
4244
"jit_cache.cc",

src/trace_processor/importers/common/clock_tracker_unittest.cc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "perfetto/base/logging.h"
2626
#include "perfetto/ext/base/utils.h"
27+
#include "src/trace_processor/importers/common/global_metadata_tracker.h"
2728
#include "src/trace_processor/importers/common/import_logs_tracker.h"
2829
#include "src/trace_processor/importers/common/machine_tracker.h"
2930
#include "src/trace_processor/importers/common/metadata_tracker.h"
@@ -42,9 +43,14 @@ class ClockTrackerTest : public ::testing::Test {
4243
context_.storage.reset(new TraceStorage());
4344
context_.global_args_tracker.reset(
4445
new GlobalArgsTracker(context_.storage.get()));
45-
context_.metadata_tracker.reset(
46-
new MetadataTracker(context_.storage.get()));
47-
context_.import_logs_tracker.reset(new ImportLogsTracker(&context_, 1));
46+
context_.global_metadata_tracker.reset(
47+
new GlobalMetadataTracker(context_.storage.get()));
48+
context_.trace_state =
49+
TraceProcessorContextPtr<TraceProcessorContext::TraceState>::MakeRoot(
50+
TraceProcessorContext::TraceState{TraceId(0)});
51+
context_.metadata_tracker.reset(new MetadataTracker(&context_));
52+
context_.import_logs_tracker.reset(
53+
new ImportLogsTracker(&context_, TraceId(1)));
4854
context_.machine_tracker =
4955
std::make_unique<MachineTracker>(&context_, kDefaultMachineId);
5056
ct_ = std::make_unique<ClockTracker>(
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/*
2+
* Copyright (C) 2025 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/global_metadata_tracker.h"
18+
19+
#include <cstddef>
20+
#include <optional>
21+
22+
#include "perfetto/base/logging.h"
23+
#include "perfetto/ext/base/crash_keys.h"
24+
#include "perfetto/trace_processor/basic_types.h"
25+
#include "src/trace_processor/storage/metadata.h"
26+
#include "src/trace_processor/storage/trace_storage.h"
27+
#include "src/trace_processor/tables/metadata_tables_py.h"
28+
#include "src/trace_processor/types/variadic.h"
29+
30+
namespace perfetto::trace_processor {
31+
32+
namespace {
33+
base::CrashKey g_crash_key_uuid("trace_uuid");
34+
}
35+
36+
GlobalMetadataTracker::GlobalMetadataTracker(TraceStorage* storage)
37+
: storage_(storage) {
38+
for (size_t i = 0; i < kNumKeys; ++i) {
39+
key_ids_[i] = storage->InternString(metadata::kNames[i]);
40+
}
41+
for (size_t i = 0; i < kNumKeyTypes; ++i) {
42+
key_type_ids_[i] = storage->InternString(metadata::kKeyTypeNames[i]);
43+
}
44+
}
45+
46+
MetadataId GlobalMetadataTracker::SetMetadata(
47+
std::optional<MachineId> machine_id,
48+
std::optional<TraceId> trace_id,
49+
metadata::KeyId key,
50+
Variadic value) {
51+
PERFETTO_CHECK(metadata::kKeyTypes[key] == metadata::KeyType::kSingle);
52+
PERFETTO_CHECK(value.type == metadata::kValueTypes[key]);
53+
54+
// When the trace_uuid is set, store a copy in a crash key, so in case of
55+
// a crash in the pipelines we can tell which trace caused the crash.
56+
if (key == metadata::trace_uuid && value.type == Variadic::kString) {
57+
g_crash_key_uuid.Set(storage_->GetString(value.string_value));
58+
}
59+
60+
auto ctx_ids = GetContextIds(key, machine_id, trace_id);
61+
auto& metadata_table = *storage_->mutable_metadata_table();
62+
StringId name_id = key_ids_[static_cast<size_t>(key)];
63+
64+
for (auto it = metadata_table.IterateRows(); it; ++it) {
65+
if (it.name() == name_id && it.machine_id() == ctx_ids.machine_id &&
66+
it.trace_id() == ctx_ids.trace_id) {
67+
WriteValue(it.ToRowReference(), value);
68+
return it.id();
69+
}
70+
}
71+
72+
// Special case for trace_uuid: it's possible that trace_uuid was set
73+
// globally (with trace_id=null) before the actual trace_id was known (e.g. by
74+
// TraceProcessorStorageImpl). In this case, we "upgrade" the existing global
75+
// entry by associating it with the current trace context instead of
76+
// inserting a new row.
77+
if (key == metadata::trace_uuid) {
78+
for (auto it = metadata_table.IterateRows(); it; ++it) {
79+
if (it.name() == name_id && !it.trace_id().has_value()) {
80+
auto rr = it.ToRowReference();
81+
rr.set_trace_id(ctx_ids.trace_id);
82+
WriteValue(rr, value);
83+
return rr.id();
84+
}
85+
}
86+
}
87+
88+
tables::MetadataTable::Row row;
89+
row.name = name_id;
90+
row.key_type = key_type_ids_[static_cast<size_t>(metadata::KeyType::kSingle)];
91+
row.machine_id = ctx_ids.machine_id;
92+
row.trace_id = ctx_ids.trace_id;
93+
94+
auto id_and_row = metadata_table.Insert(row);
95+
WriteValue(metadata_table[id_and_row.row], value);
96+
return id_and_row.id;
97+
}
98+
99+
std::optional<SqlValue> GlobalMetadataTracker::GetMetadata(
100+
std::optional<MachineId> machine_id,
101+
std::optional<TraceId> trace_id,
102+
metadata::KeyId key) const {
103+
// KeyType::kMulti not yet supported by this method.
104+
PERFETTO_CHECK(metadata::kKeyTypes[key] == metadata::KeyType::kSingle);
105+
106+
auto ctx_ids = GetContextIds(key, machine_id, trace_id);
107+
const auto& metadata_table = storage_->metadata_table();
108+
StringId name_id = key_ids_[static_cast<size_t>(key)];
109+
110+
for (auto it = metadata_table.IterateRows(); it; ++it) {
111+
if (it.name() == name_id && it.machine_id() == ctx_ids.machine_id &&
112+
it.trace_id() == ctx_ids.trace_id) {
113+
auto value_type = metadata::kValueTypes[key];
114+
switch (value_type) {
115+
case Variadic::kInt:
116+
return SqlValue::Long(*it.int_value());
117+
case Variadic::kString:
118+
return SqlValue::String(storage_->GetString(*it.str_value()).c_str());
119+
case Variadic::kNull:
120+
return SqlValue();
121+
case Variadic::kUint:
122+
case Variadic::kReal:
123+
case Variadic::kPointer:
124+
case Variadic::kBool:
125+
case Variadic::kJson:
126+
PERFETTO_FATAL("Invalid metadata value type %s",
127+
Variadic::kTypeNames[value_type]);
128+
}
129+
}
130+
}
131+
return std::nullopt;
132+
}
133+
134+
MetadataId GlobalMetadataTracker::AppendMetadata(
135+
std::optional<MachineId> machine_id,
136+
std::optional<TraceId> trace_id,
137+
metadata::KeyId key,
138+
Variadic value) {
139+
PERFETTO_CHECK(key < metadata::kNumKeys);
140+
PERFETTO_CHECK(metadata::kKeyTypes[key] == metadata::KeyType::kMulti);
141+
PERFETTO_CHECK(value.type == metadata::kValueTypes[key]);
142+
143+
auto ctx_ids = GetContextIds(key, machine_id, trace_id);
144+
auto& metadata_table = *storage_->mutable_metadata_table();
145+
146+
tables::MetadataTable::Row row;
147+
row.name = key_ids_[static_cast<size_t>(key)];
148+
row.key_type = key_type_ids_[static_cast<size_t>(metadata::KeyType::kMulti)];
149+
row.machine_id = ctx_ids.machine_id;
150+
row.trace_id = ctx_ids.trace_id;
151+
152+
auto id_and_row = metadata_table.Insert(row);
153+
WriteValue(metadata_table[id_and_row.row], value);
154+
return id_and_row.id;
155+
}
156+
157+
MetadataId GlobalMetadataTracker::SetDynamicMetadata(
158+
std::optional<MachineId> machine_id,
159+
std::optional<TraceId> trace_id,
160+
StringId key,
161+
Variadic value) {
162+
auto& metadata_table = *storage_->mutable_metadata_table();
163+
tables::MetadataTable::Row row;
164+
row.name = key;
165+
row.key_type = key_type_ids_[static_cast<size_t>(metadata::KeyType::kSingle)];
166+
row.machine_id = machine_id;
167+
row.trace_id = trace_id;
168+
169+
auto id_and_row = metadata_table.Insert(row);
170+
WriteValue(metadata_table[id_and_row.row], value);
171+
return id_and_row.id;
172+
}
173+
174+
void GlobalMetadataTracker::WriteValue(tables::MetadataTable::RowReference rr,
175+
Variadic value) {
176+
switch (value.type) {
177+
case Variadic::Type::kInt:
178+
rr.set_int_value(value.int_value);
179+
break;
180+
case Variadic::Type::kString:
181+
rr.set_str_value(value.string_value);
182+
break;
183+
case Variadic::Type::kJson:
184+
rr.set_str_value(value.json_value);
185+
break;
186+
case Variadic::Type::kBool:
187+
case Variadic::Type::kPointer:
188+
case Variadic::Type::kUint:
189+
case Variadic::Type::kReal:
190+
case Variadic::Type::kNull:
191+
PERFETTO_FATAL("Unsupported value type %s",
192+
Variadic::kTypeNames[value.type]);
193+
}
194+
}
195+
196+
GlobalMetadataTracker::ContextIds GlobalMetadataTracker::GetContextIds(
197+
metadata::KeyId key,
198+
std::optional<MachineId> machine_id,
199+
std::optional<TraceId> trace_id) const {
200+
// Exception for trace_uuid: it can be called with null trace_id initially
201+
// from TraceProcessorStorageImpl when parsing hasn just started.
202+
if (key == metadata::trace_uuid) {
203+
return {std::nullopt, trace_id};
204+
}
205+
206+
switch (metadata::kScopes[key]) {
207+
case metadata::Scope::kGlobal:
208+
return {std::nullopt, std::nullopt};
209+
case metadata::Scope::kMachine:
210+
PERFETTO_CHECK(machine_id.has_value());
211+
return {machine_id, std::nullopt};
212+
case metadata::Scope::kTrace:
213+
PERFETTO_CHECK(trace_id.has_value());
214+
return {std::nullopt, trace_id};
215+
case metadata::Scope::kMachineAndTrace:
216+
PERFETTO_CHECK(machine_id.has_value());
217+
PERFETTO_CHECK(trace_id.has_value());
218+
return {machine_id, trace_id};
219+
case metadata::Scope::kNumScopes:
220+
PERFETTO_FATAL("Invalid scope");
221+
}
222+
}
223+
224+
} // namespace perfetto::trace_processor

0 commit comments

Comments
 (0)