Merge "Hash scope into id for legacy trace events"
diff --git a/Android.bp b/Android.bp
index b54baa5..5bf2da2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3743,6 +3743,7 @@
"protos/perfetto/metrics/chrome/scroll_jank.proto",
"protos/perfetto/metrics/chrome/test_chrome_metric.proto",
"protos/perfetto/metrics/chrome/touch_jank.proto",
+ "protos/perfetto/metrics/chrome/user_event_hashes.proto",
"protos/perfetto/metrics/custom_options.proto",
"protos/perfetto/metrics/metrics.proto",
],
@@ -8392,6 +8393,7 @@
"src/trace_processor/metrics/sql/chrome/chrome_histogram_hashes.sql",
"src/trace_processor/metrics/sql/chrome/chrome_processes.sql",
"src/trace_processor/metrics/sql/chrome/chrome_thread_slice.sql",
+ "src/trace_processor/metrics/sql/chrome/chrome_user_event_hashes.sql",
"src/trace_processor/metrics/sql/chrome/cpu_time_by_category.sql",
"src/trace_processor/metrics/sql/chrome/cpu_time_by_rail_mode.sql",
"src/trace_processor/metrics/sql/chrome/estimated_power_by_category.sql",
diff --git a/BUILD b/BUILD
index eba87b7..8870bbd 100644
--- a/BUILD
+++ b/BUILD
@@ -1117,6 +1117,7 @@
"src/trace_processor/metrics/sql/chrome/chrome_histogram_hashes.sql",
"src/trace_processor/metrics/sql/chrome/chrome_processes.sql",
"src/trace_processor/metrics/sql/chrome/chrome_thread_slice.sql",
+ "src/trace_processor/metrics/sql/chrome/chrome_user_event_hashes.sql",
"src/trace_processor/metrics/sql/chrome/cpu_time_by_category.sql",
"src/trace_processor/metrics/sql/chrome/cpu_time_by_rail_mode.sql",
"src/trace_processor/metrics/sql/chrome/estimated_power_by_category.sql",
@@ -2751,6 +2752,7 @@
"protos/perfetto/metrics/chrome/scroll_jank.proto",
"protos/perfetto/metrics/chrome/test_chrome_metric.proto",
"protos/perfetto/metrics/chrome/touch_jank.proto",
+ "protos/perfetto/metrics/chrome/user_event_hashes.proto",
],
visibility = [
PERFETTO_CONFIG.proto_library_visibility,
diff --git a/buildtools/BUILD.gn b/buildtools/BUILD.gn
index a508a74..6c8106c 100644
--- a/buildtools/BUILD.gn
+++ b/buildtools/BUILD.gn
@@ -1162,7 +1162,7 @@
# writing, the only c++14 specific code is behind an #ifndef NDEBUG, so we
# could keep building as c++11 in non-debug builds, but we always use c++14 for
# consistency.
-static_library("llvm_demangle") {
+source_set("llvm_demangle") {
visibility = _buildtools_visibility
configs -= [
"//gn/standalone:extra_warnings",
diff --git a/protos/perfetto/metrics/chrome/BUILD.gn b/protos/perfetto/metrics/chrome/BUILD.gn
index a170ace..ad53980 100644
--- a/protos/perfetto/metrics/chrome/BUILD.gn
+++ b/protos/perfetto/metrics/chrome/BUILD.gn
@@ -32,6 +32,7 @@
"scroll_jank.proto",
"test_chrome_metric.proto",
"touch_jank.proto",
+ "user_event_hashes.proto",
]
}
diff --git a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto b/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
index 03c2bb2..5513b52 100644
--- a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
+++ b/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
@@ -29,6 +29,7 @@
import "protos/perfetto/metrics/chrome/scroll_jank.proto";
import "protos/perfetto/metrics/chrome/test_chrome_metric.proto";
import "protos/perfetto/metrics/chrome/touch_jank.proto";
+import "protos/perfetto/metrics/chrome/user_event_hashes.proto";
// TODO(lalitm): rename metrics below to include a "chrome_" prefix.
extend TraceMetrics {
@@ -42,4 +43,5 @@
optional ChromeDroppedFrames chrome_dropped_frames = 1008;
optional ChromeLongLatency chrome_long_latency = 1009;
optional ChromeHistogramHashes chrome_histogram_hashes = 1010;
+ optional ChromeUserEventHashes chrome_user_event_hashes = 1011;
}
diff --git a/protos/perfetto/metrics/chrome/user_event_hashes.proto b/protos/perfetto/metrics/chrome/user_event_hashes.proto
new file mode 100644
index 0000000..e50e6bd
--- /dev/null
+++ b/protos/perfetto/metrics/chrome/user_event_hashes.proto
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+// The list of Chrome user event hashes in trace track events.
+// Use cases include translating user event hashes to action
+// names by getting this list, and prepending a translation table to the trace.
+message ChromeUserEventHashes {
+ repeated int64 action_hash = 1;
+}
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 0961c10..ec49f71 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -54,7 +54,18 @@
]
}
-static_library("demangle") {
+# In Bazel builds the ":demangle" target (below) should be a static_library so
+# it gets mapped to an actual target (rather than being squashed as a filegroup)
+# and can be replaced in Google internal builds via perfetto_cfg.bzl.
+# Unfortunately, however, static_library targets seem to break Wasm builds on
+# Mac. For this reason we just make it a source_set for all other build types.
+if (is_perfetto_build_generator) {
+ _demangle_target_type = "static_library"
+} else {
+ _demangle_target_type = "source_set"
+}
+
+target(_demangle_target_type, "demangle") {
sources = [ "demangle.cc" ]
deps = [
"../../gn:default_deps",
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index 3bfc0fb..e05680e 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -709,7 +709,7 @@
const auto& thread_table = storage_->thread_table();
for (UniqueTid utid = 0; utid < thread_table.row_count(); ++utid) {
auto opt_name = thread_table.name()[utid];
- if (!opt_name.is_null()) {
+ if (opt_name.has_value()) {
const char* thread_name = GetNonNullString(storage_, opt_name);
auto pid_and_tid = UtidToPidAndTid(utid);
writer_.WriteMetadataEvent("thread_name", "name", thread_name,
@@ -723,7 +723,7 @@
const auto& process_table = storage_->process_table();
for (UniquePid upid = 0; upid < process_table.row_count(); ++upid) {
auto opt_name = process_table.name()[upid];
- if (!opt_name.is_null()) {
+ if (opt_name.has_value()) {
const char* process_name = GetNonNullString(storage_, opt_name);
writer_.WriteMetadataEvent("process_name", "name", process_name,
UpidToPid(upid), /*tid=*/0);
diff --git a/src/trace_processor/importers/common/args_translation_table.cc b/src/trace_processor/importers/common/args_translation_table.cc
index 216305d..72ced8b 100644
--- a/src/trace_processor/importers/common/args_translation_table.cc
+++ b/src/trace_processor/importers/common/args_translation_table.cc
@@ -22,16 +22,27 @@
constexpr char ArgsTranslationTable::kChromeHistogramHashKey[];
constexpr char ArgsTranslationTable::kChromeHistogramNameKey[];
+constexpr char ArgsTranslationTable::kChromeUserEventHashKey[];
+constexpr char ArgsTranslationTable::kChromeUserEventActionKey[];
+
ArgsTranslationTable::ArgsTranslationTable(TraceStorage* storage)
: storage_(storage),
+ interned_chrome_histogram_hash_key_(
+ storage->InternString(kChromeHistogramHashKey)),
interned_chrome_histogram_name_key_(
- storage->InternString(kChromeHistogramNameKey)) {}
+ storage->InternString(kChromeHistogramNameKey)),
+ interned_chrome_user_event_hash_key_(
+ storage->InternString(kChromeUserEventHashKey)),
+ interned_chrome_user_event_action_key_(
+ storage->InternString(kChromeUserEventActionKey)) {}
bool ArgsTranslationTable::TranslateUnsignedIntegerArg(
const Key& key,
uint64_t value,
ArgsTracker::BoundInserter& inserter) {
if (key.key == kChromeHistogramHashKey) {
+ inserter.AddArg(interned_chrome_histogram_hash_key_,
+ Variadic::UnsignedInteger(value));
const base::Optional<base::StringView> translated_value =
TranslateChromeHistogramHash(value);
if (translated_value) {
@@ -39,17 +50,24 @@
interned_chrome_histogram_name_key_,
Variadic::String(storage_->InternString(*translated_value)));
}
+ return true;
+ }
+ if (key.key == kChromeUserEventHashKey) {
+ inserter.AddArg(interned_chrome_user_event_hash_key_,
+ Variadic::UnsignedInteger(value));
+ const base::Optional<base::StringView> translated_value =
+ TranslateChromeUserEventHash(value);
+ if (translated_value) {
+ inserter.AddArg(
+ interned_chrome_user_event_action_key_,
+ Variadic::String(storage_->InternString(*translated_value)));
+ }
+ return true;
}
return false;
}
base::Optional<base::StringView>
-ArgsTranslationTable::TranslateChromeHistogramHashForTesting(
- uint64_t hash) const {
- return TranslateChromeHistogramHash(hash);
-}
-
-base::Optional<base::StringView>
ArgsTranslationTable::TranslateChromeHistogramHash(uint64_t hash) const {
auto* value = chrome_histogram_hash_to_name_.Find(hash);
if (!value) {
@@ -58,10 +76,13 @@
return base::StringView(*value);
}
-void ArgsTranslationTable::AddChromeHistogramTranslationRule(
- uint64_t hash,
- base::StringView name) {
- chrome_histogram_hash_to_name_.Insert(hash, name.ToStdString());
+base::Optional<base::StringView>
+ArgsTranslationTable::TranslateChromeUserEventHash(uint64_t hash) const {
+ auto* value = chrome_user_event_hash_to_action_.Find(hash);
+ if (!value) {
+ return base::nullopt;
+ }
+ return base::StringView(*value);
}
} // namespace trace_processor
diff --git a/src/trace_processor/importers/common/args_translation_table.h b/src/trace_processor/importers/common/args_translation_table.h
index aac2bb6..a27656f 100644
--- a/src/trace_processor/importers/common/args_translation_table.h
+++ b/src/trace_processor/importers/common/args_translation_table.h
@@ -44,10 +44,22 @@
uint64_t value,
ArgsTracker::BoundInserter& inserter);
- void AddChromeHistogramTranslationRule(uint64_t hash, base::StringView name);
+ void AddChromeHistogramTranslationRule(uint64_t hash, base::StringView name) {
+ chrome_histogram_hash_to_name_.Insert(hash, name.ToStdString());
+ }
+ void AddChromeUserEventTranslationRule(uint64_t hash,
+ base::StringView action) {
+ chrome_user_event_hash_to_action_.Insert(hash, action.ToStdString());
+ }
base::Optional<base::StringView> TranslateChromeHistogramHashForTesting(
- uint64_t hash) const;
+ uint64_t hash) const {
+ return TranslateChromeHistogramHash(hash);
+ }
+ base::Optional<base::StringView> TranslateChromeUserEventHashForTesting(
+ uint64_t hash) const {
+ return TranslateChromeUserEventHash(hash);
+ }
private:
static constexpr char kChromeHistogramHashKey[] =
@@ -55,12 +67,23 @@
static constexpr char kChromeHistogramNameKey[] =
"chrome_histogram_sample.name";
+ static constexpr char kChromeUserEventHashKey[] =
+ "chrome_user_event.action_hash";
+ static constexpr char kChromeUserEventActionKey[] =
+ "chrome_user_event.action";
+
TraceStorage* storage_;
+ StringId interned_chrome_histogram_hash_key_;
StringId interned_chrome_histogram_name_key_;
+ StringId interned_chrome_user_event_hash_key_;
+ StringId interned_chrome_user_event_action_key_;
base::FlatHashMap<uint64_t, std::string> chrome_histogram_hash_to_name_;
+ base::FlatHashMap<uint64_t, std::string> chrome_user_event_hash_to_action_;
base::Optional<base::StringView> TranslateChromeHistogramHash(
uint64_t hash) const;
+ base::Optional<base::StringView> TranslateChromeUserEventHash(
+ uint64_t hash) const;
};
} // namespace trace_processor
diff --git a/src/trace_processor/importers/common/args_translation_table_unittest.cc b/src/trace_processor/importers/common/args_translation_table_unittest.cc
index 08bc458..5e5ab4b 100644
--- a/src/trace_processor/importers/common/args_translation_table_unittest.cc
+++ b/src/trace_processor/importers/common/args_translation_table_unittest.cc
@@ -25,9 +25,10 @@
TraceStorage storage;
ArgsTranslationTable table(&storage);
EXPECT_EQ(table.TranslateChromeHistogramHashForTesting(1), base::nullopt);
+ EXPECT_EQ(table.TranslateChromeUserEventHashForTesting(1), base::nullopt);
}
-TEST(ArgsTranslationTable, TranslatesHashes) {
+TEST(ArgsTranslationTable, TranslatesHistogramHashes) {
TraceStorage storage;
ArgsTranslationTable table(&storage);
table.AddChromeHistogramTranslationRule(1, "hash1");
@@ -39,6 +40,18 @@
EXPECT_EQ(table.TranslateChromeHistogramHashForTesting(2), base::nullopt);
}
+TEST(ArgsTranslationTable, TranslatesUserEventHashes) {
+ TraceStorage storage;
+ ArgsTranslationTable table(&storage);
+ table.AddChromeUserEventTranslationRule(1, "action1");
+ table.AddChromeUserEventTranslationRule(10, "action2");
+ EXPECT_EQ(table.TranslateChromeUserEventHashForTesting(1),
+ base::Optional<base::StringView>("action1"));
+ EXPECT_EQ(table.TranslateChromeUserEventHashForTesting(10),
+ base::Optional<base::StringView>("action2"));
+ EXPECT_EQ(table.TranslateChromeUserEventHashForTesting(2), base::nullopt);
+}
+
} // namespace
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/common/process_tracker.cc b/src/trace_processor/importers/common/process_tracker.cc
index 93a5890..2ef798d 100644
--- a/src/trace_processor/importers/common/process_tracker.cc
+++ b/src/trace_processor/importers/common/process_tracker.cc
@@ -285,7 +285,7 @@
auto* process_table = context_->storage->mutable_process_table();
auto* thread_table = context_->storage->mutable_thread_table();
- PERFETTO_DCHECK(process_table->name()[upid].is_null());
+ PERFETTO_DCHECK(!process_table->name()[upid].has_value());
PERFETTO_DCHECK(!process_table->start_ts()[upid].has_value());
if (timestamp) {
@@ -339,7 +339,7 @@
void ProcessTracker::SetProcessNameIfUnset(UniquePid upid,
StringId process_name_id) {
auto* process_table = context_->storage->mutable_process_table();
- if (process_table->name()[upid].is_null())
+ if (!process_table->name()[upid].has_value())
process_table->mutable_name()->Set(upid, process_name_id);
}
diff --git a/src/trace_processor/importers/common/process_tracker_unittest.cc b/src/trace_processor/importers/common/process_tracker_unittest.cc
index 7fc9055..d037136 100644
--- a/src/trace_processor/importers/common/process_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/process_tracker_unittest.cc
@@ -86,8 +86,8 @@
TEST_F(ProcessTrackerTest, AddProcessEntry_CorrectName) {
context.process_tracker->SetProcessMetadata(1, base::nullopt, "test",
base::StringView());
- auto name =
- context.storage->GetString(context.storage->process_table().name()[1]);
+ auto name = context.storage->process_table().name().GetString(1);
+
ASSERT_EQ(name, "test");
}
diff --git a/src/trace_processor/importers/ftrace/binder_tracker.cc b/src/trace_processor/importers/ftrace/binder_tracker.cc
index fd229f1..5e95579 100644
--- a/src/trace_processor/importers/ftrace/binder_tracker.cc
+++ b/src/trace_processor/importers/ftrace/binder_tracker.cc
@@ -113,12 +113,13 @@
if (is_reply) {
UniqueTid utid = context_->process_tracker->GetOrCreateThread(
static_cast<uint32_t>(dest_tid));
- StringId dest_thread_name =
- context_->storage->thread_table().name()[utid];
+ auto dest_thread_name = context_->storage->thread_table().name()[utid];
auto dest_args_inserter = [this, dest_tid, &dest_thread_name](
ArgsTracker::BoundInserter* inserter) {
inserter->AddArg(dest_thread_, Variadic::Integer(dest_tid));
- inserter->AddArg(dest_name_, Variadic::String(dest_thread_name));
+ if (dest_thread_name.has_value()) {
+ inserter->AddArg(dest_name_, Variadic::String(*dest_thread_name));
+ }
};
context_->slice_tracker->AddArgs(track_id, binder_category_id_, reply_id_,
dest_args_inserter);
@@ -179,9 +180,10 @@
auto args_inserter = [this, utid,
pid](ArgsTracker::BoundInserter* inserter) {
inserter->AddArg(dest_thread_, Variadic::UnsignedInteger(pid));
- inserter->AddArg(
- dest_name_,
- Variadic::String(context_->storage->thread_table().name()[utid]));
+ auto dest_thread_name = context_->storage->thread_table().name()[utid];
+ if (dest_thread_name.has_value()) {
+ inserter->AddArg(dest_name_, Variadic::String(*dest_thread_name));
+ }
};
context_->slice_tracker->AddArgs(*transaction.send_track_id,
binder_category_id_,
diff --git a/src/trace_processor/importers/ftrace/sched_event_tracker.cc b/src/trace_processor/importers/ftrace/sched_event_tracker.cc
index 00fc93f..66a78b3 100644
--- a/src/trace_processor/importers/ftrace/sched_event_tracker.cc
+++ b/src/trace_processor/importers/ftrace/sched_event_tracker.cc
@@ -175,7 +175,9 @@
// Do a fresh task name lookup in case it was updated by a task_rename while
// scheduled.
- StringId prev_comm_id = context_->storage->thread_table().name()[prev_utid];
+ StringId prev_comm_id =
+ context_->storage->thread_table().name()[prev_utid].value_or(
+ kNullStringId);
auto new_slice_idx = AddRawEventAndStartSlice(
cpu, ts, prev_utid, prev_pid, prev_comm_id, prev_prio, prev_state,
diff --git a/src/trace_processor/importers/ftrace/sched_event_tracker_unittest.cc b/src/trace_processor/importers/ftrace/sched_event_tracker_unittest.cc
index 15f6eca..802990f 100644
--- a/src/trace_processor/importers/ftrace/sched_event_tracker_unittest.cc
+++ b/src/trace_processor/importers/ftrace/sched_event_tracker_unittest.cc
@@ -69,8 +69,7 @@
ASSERT_EQ(timestamps[0], timestamp);
ASSERT_EQ(context.storage->thread_table().start_ts()[1], base::nullopt);
- auto name =
- context.storage->GetString(context.storage->thread_table().name()[1]);
+ auto name = context.storage->thread_table().name().GetString(1);
ASSERT_STREQ(name.c_str(), kCommProc1);
ASSERT_EQ(context.storage->sched_slice_table().utid()[0], 1u);
ASSERT_EQ(context.storage->sched_slice_table().dur()[0], 1);
diff --git a/src/trace_processor/importers/proto/translation_table_module.cc b/src/trace_processor/importers/proto/translation_table_module.cc
index cf523d9..24d4ebe 100644
--- a/src/trace_processor/importers/proto/translation_table_module.cc
+++ b/src/trace_processor/importers/proto/translation_table_module.cc
@@ -42,6 +42,8 @@
protos::pbzero::TranslationTable::Decoder(decoder.translation_table());
if (translation_table.has_chrome_histogram()) {
ParseChromeHistogramRules(translation_table.chrome_histogram());
+ } else if (translation_table.has_chrome_user_event()) {
+ ParseChromeUserEventRules(translation_table.chrome_user_event());
}
}
@@ -57,5 +59,17 @@
}
}
+void TranslationTableModule::ParseChromeUserEventRules(
+ protozero::ConstBytes bytes) {
+ const auto chrome_user_event =
+ protos::pbzero::ChromeUserEventTranslationTable::Decoder(bytes);
+ for (auto it = chrome_user_event.action_hash_to_name(); it; ++it) {
+ protos::pbzero::ChromeUserEventTranslationTable::ActionHashToNameEntry::
+ Decoder entry(*it);
+ context_->args_translation_table->AddChromeUserEventTranslationRule(
+ entry.key(), entry.value());
+ }
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/translation_table_module.h b/src/trace_processor/importers/proto/translation_table_module.h
index c6c61a6..bc96f00 100644
--- a/src/trace_processor/importers/proto/translation_table_module.h
+++ b/src/trace_processor/importers/proto/translation_table_module.h
@@ -39,6 +39,7 @@
private:
void ParseChromeHistogramRules(protozero::ConstBytes bytes);
+ void ParseChromeUserEventRules(protozero::ConstBytes bytes);
TraceProcessorContext* context_;
};
diff --git a/src/trace_processor/metrics/sql/BUILD.gn b/src/trace_processor/metrics/sql/BUILD.gn
index 27facfb..5c07ca1 100644
--- a/src/trace_processor/metrics/sql/BUILD.gn
+++ b/src/trace_processor/metrics/sql/BUILD.gn
@@ -87,6 +87,7 @@
"chrome/chrome_histogram_hashes.sql",
"chrome/chrome_processes.sql",
"chrome/chrome_thread_slice.sql",
+ "chrome/chrome_user_event_hashes.sql",
"chrome/cpu_time_by_category.sql",
"chrome/cpu_time_by_rail_mode.sql",
"chrome/estimated_power_by_category.sql",
diff --git a/src/trace_processor/metrics/sql/chrome/chrome_histogram_hashes.sql b/src/trace_processor/metrics/sql/chrome/chrome_histogram_hashes.sql
index ba48b5d..ef5d918 100644
--- a/src/trace_processor/metrics/sql/chrome/chrome_histogram_hashes.sql
+++ b/src/trace_processor/metrics/sql/chrome/chrome_histogram_hashes.sql
@@ -21,6 +21,6 @@
SELECT RepeatedField(int_value)
FROM args
WHERE key = 'chrome_histogram_sample.name_hash'
- ORDER BY arg_set_id
+ ORDER BY int_value
)
);
diff --git a/src/trace_processor/metrics/sql/chrome/chrome_user_event_hashes.sql b/src/trace_processor/metrics/sql/chrome/chrome_user_event_hashes.sql
new file mode 100644
index 0000000..005e2ad
--- /dev/null
+++ b/src/trace_processor/metrics/sql/chrome/chrome_user_event_hashes.sql
@@ -0,0 +1,26 @@
+--
+-- Copyright 2022 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+DROP VIEW IF EXISTS chrome_user_event_hashes_output;
+
+CREATE VIEW chrome_user_event_hashes_output AS
+SELECT ChromeUserEventHashes(
+ 'action_hash', (
+ SELECT RepeatedField(int_value)
+ FROM args
+ WHERE key = 'chrome_user_event.action_hash'
+ ORDER BY int_value
+ )
+);
diff --git a/src/trace_processor/sqlite/sqlite_raw_table.cc b/src/trace_processor/sqlite/sqlite_raw_table.cc
index e579fda..a42d83b 100644
--- a/src/trace_processor/sqlite/sqlite_raw_table.cc
+++ b/src/trace_processor/sqlite/sqlite_raw_table.cc
@@ -619,7 +619,7 @@
if (opt_upid.has_value()) {
tgid = storage_->process_table().pid()[*opt_upid];
}
- auto name = storage_->GetString(storage_->thread_table().name()[utid]);
+ auto name = storage_->thread_table().name().GetString(utid);
FtraceTime ftrace_time(ts);
if (tid == 0) {
diff --git a/src/trace_processor/tables/metadata_tables.h b/src/trace_processor/tables/metadata_tables.h
index 2fad555..22431b9 100644
--- a/src/trace_processor/tables/metadata_tables.h
+++ b/src/trace_processor/tables/metadata_tables.h
@@ -88,7 +88,7 @@
NAME(ThreadTable, "internal_thread") \
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
C(uint32_t, tid) \
- C(StringPool::Id, name) \
+ C(base::Optional<StringPool::Id>, name) \
C(base::Optional<int64_t>, start_ts) \
C(base::Optional<int64_t>, end_ts) \
C(base::Optional<uint32_t>, upid) \
@@ -129,7 +129,7 @@
NAME(ProcessTable, "internal_process") \
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
C(uint32_t, pid) \
- C(StringPool::Id, name) \
+ C(base::Optional<StringPool::Id>, name) \
C(base::Optional<int64_t>, start_ts) \
C(base::Optional<int64_t>, end_ts) \
C(base::Optional<uint32_t>, parent_upid) \
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index e0e8707..dda24f1 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -128,6 +128,22 @@
}
};
+static void WriteFile(const std::string& file_name,
+ const char* content,
+ size_t len) {
+ std::ofstream output;
+ output.open(file_name.c_str(), std::ios::out | std::ios::binary);
+ output.write(content, static_cast<std::streamsize>(len));
+ output.close();
+}
+
+// Unused in merged code, but very handy for debugging when trace generated in
+// a test needs to be exported, to understand it further with other tools.
+__attribute__((unused)) static void WriteFile(const std::string& file_name,
+ const std::vector<char>& data) {
+ return WriteFile(file_name, data.data(), data.size());
+}
+
// Represents an opaque (from Perfetto's point of view) thread identifier (e.g.,
// base::PlatformThreadId in Chromium).
struct MyThreadId {
diff --git a/test/trace_processor/chrome/chrome_user_event_hashes.out b/test/trace_processor/chrome/chrome_user_event_hashes.out
new file mode 100644
index 0000000..69ca70f
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_user_event_hashes.out
@@ -0,0 +1,5 @@
+[perfetto.protos.chrome_user_event_hashes]: {
+ action_hash: 10
+ action_hash: 20
+}
+
diff --git a/test/trace_processor/chrome/chrome_user_event_hashes.textproto b/test/trace_processor/chrome/chrome_user_event_hashes.textproto
new file mode 100644
index 0000000..41b21b9
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_user_event_hashes.textproto
@@ -0,0 +1,27 @@
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat1"
+ type: 3
+ name_iid: 1
+ chrome_user_event {
+ action_hash: 10
+ }
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat2"
+ type: 3
+ name_iid: 2
+ chrome_user_event {
+ action_hash: 20
+ }
+ }
+}
+
diff --git a/test/trace_processor/chrome/index b/test/trace_processor/chrome/index
index 1f727f4..9bdeb89 100644
--- a/test/trace_processor/chrome/index
+++ b/test/trace_processor/chrome/index
@@ -57,3 +57,6 @@
# Chrome histogram hashes
chrome_histogram_hashes.textproto chrome_histogram_hashes chrome_histogram_hashes.out
+
+# Chrome user events
+chrome_user_event_hashes.textproto chrome_user_event_hashes chrome_user_event_hashes.out
diff --git a/test/trace_processor/translation/chrome_histogram.sql b/test/trace_processor/translation/chrome_args.sql
similarity index 100%
rename from test/trace_processor/translation/chrome_histogram.sql
rename to test/trace_processor/translation/chrome_args.sql
diff --git a/test/trace_processor/translation/chrome_user_event.out b/test/trace_processor/translation/chrome_user_event.out
new file mode 100644
index 0000000..b092f7a
--- /dev/null
+++ b/test/trace_processor/translation/chrome_user_event.out
@@ -0,0 +1,9 @@
+"flat_key","key","int_value","string_value"
+"is_root_in_scope","is_root_in_scope",1,"[NULL]"
+"source","source","[NULL]","descriptor"
+"source_id","source_id",0,"[NULL]"
+"chrome_user_event.action","chrome_user_event.action","[NULL]","action1"
+"chrome_user_event.action_hash","chrome_user_event.action_hash",10,"[NULL]"
+"chrome_user_event.action","chrome_user_event.action","[NULL]","action2"
+"chrome_user_event.action_hash","chrome_user_event.action_hash",20,"[NULL]"
+"chrome_user_event.action_hash","chrome_user_event.action_hash",30,"[NULL]"
diff --git a/test/trace_processor/translation/chrome_user_event.textproto b/test/trace_processor/translation/chrome_user_event.textproto
new file mode 100644
index 0000000..9dd30c1
--- /dev/null
+++ b/test/trace_processor/translation/chrome_user_event.textproto
@@ -0,0 +1,52 @@
+# Chrome histogram hashes translation rules
+packet {
+ translation_table {
+ chrome_user_event {
+ action_hash_to_name { key: 10 value: "action1" }
+ action_hash_to_name { key: 20 value: "action2" }
+ }
+ }
+}
+# Known action hash, should be translated to a name
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat1"
+ type: 3
+ name_iid: 1
+ chrome_user_event {
+ action_hash: 10
+ }
+ }
+}
+# Another known hash, should be translated to a name
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat2"
+ type: 3
+ name_iid: 2
+ chrome_user_event {
+ action_hash: 20
+ }
+ }
+}
+# Unknown hash, should not be translated to any name
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat3"
+ type: 3
+ name_iid: 3
+ chrome_user_event {
+ action_hash: 30
+ }
+ }
+}
+
diff --git a/test/trace_processor/translation/index b/test/trace_processor/translation/index
index 77fd3d4..fc07479 100644
--- a/test/trace_processor/translation/index
+++ b/test/trace_processor/translation/index
@@ -1 +1,2 @@
-chrome_histogram.textproto chrome_histogram.sql chrome_histogram.out
+chrome_histogram.textproto chrome_args.sql chrome_histogram.out
+chrome_user_event.textproto chrome_args.sql chrome_user_event.out
diff --git a/ui/src/base/generic_set.ts b/ui/src/base/generic_set.ts
new file mode 100644
index 0000000..d2b73cf
--- /dev/null
+++ b/ui/src/base/generic_set.ts
@@ -0,0 +1,30 @@
+// ES6 Set does not allow to reasonably store compound objects; this class
+// rectifies the problem by implementing generic set on top of Map and an
+// injective function from objects of generic type to strings.
+export class GenericSet<T> {
+ interner: (t: T) => string;
+
+ // Passed function should be injective (as in never having the same output for
+ // two different inputs).
+ constructor(interner: (t: T) => string) {
+ this.interner = interner;
+ }
+
+ backingMap = new Map<string, T>();
+
+ has(column: T): boolean {
+ return this.backingMap.has(this.interner(column));
+ }
+
+ add(column: T) {
+ this.backingMap.set(this.interner(column), column);
+ }
+
+ delete(column: T) {
+ this.backingMap.delete(this.interner(column));
+ }
+
+ values(): Iterable<T> {
+ return this.backingMap.values();
+ }
+}
diff --git a/ui/src/frontend/pivot_table_redux.ts b/ui/src/frontend/pivot_table_redux.ts
index ea2b7d3..a8f3e8b 100644
--- a/ui/src/frontend/pivot_table_redux.ts
+++ b/ui/src/frontend/pivot_table_redux.ts
@@ -1,5 +1,6 @@
import * as m from 'mithril';
+import {GenericSet} from '../base/generic_set';
import {sqliteString} from '../base/string_utils';
import {Actions} from '../common/actions';
import {ColumnType} from '../common/query_result';
@@ -15,7 +16,7 @@
import {
aggregationIndex,
areaFilter,
- ColumnSet,
+ createColumnSet,
generateQuery,
QueryGeneratorError,
sliceAggregationColumns,
@@ -26,7 +27,7 @@
} from './pivot_table_redux_query_generator';
interface ColumnSetCheckboxAttrs {
- set: ColumnSet;
+ set: GenericSet<TableColumn>;
setKey: TableColumn;
}
@@ -74,8 +75,8 @@
}
export class PivotTableRedux extends Panel<PivotTableReduxAttrs> {
- selectedPivotsMap = new ColumnSet();
- selectedAggregations = new ColumnSet();
+ selectedPivotsMap = createColumnSet();
+ selectedAggregations = createColumnSet();
constrainToArea = true;
editMode = true;
diff --git a/ui/src/frontend/pivot_table_redux_query_generator.ts b/ui/src/frontend/pivot_table_redux_query_generator.ts
index 8e9586b..8c201fc 100644
--- a/ui/src/frontend/pivot_table_redux_query_generator.ts
+++ b/ui/src/frontend/pivot_table_redux_query_generator.ts
@@ -1,3 +1,4 @@
+import {GenericSet} from '../base/generic_set';
import {Area, PivotTableReduxQuery} from '../common/state';
import {toNs} from '../common/time';
import {
@@ -48,35 +49,8 @@
// Pair of table name and column name.
export type TableColumn = [string, string];
-// ES6 Set does not allow to reasonably store compound objects; this class
-// rectifies the problem by providing a domain-specific set of pairs of strings.
-export class ColumnSet {
- // Should've been Set<TableColumn>, but JavaScript Set does not support custom
- // hashing/equality predicates, so TableColumn is keyed by a string generated
- // by columnKey method.
- backingMap = new Map<string, TableColumn>();
-
- private static columnKey(column: TableColumn): string {
- // None of table and column names used in Perfetto tables contain periods,
- // so this function should not lead to collisions.
- return `${column[0]}.${column[1]}`;
- }
-
- has(column: TableColumn): boolean {
- return this.backingMap.has(ColumnSet.columnKey(column));
- }
-
- add(column: TableColumn) {
- this.backingMap.set(ColumnSet.columnKey(column), column);
- }
-
- delete(column: TableColumn) {
- this.backingMap.delete(ColumnSet.columnKey(column));
- }
-
- values(): Iterable<[string, string]> {
- return this.backingMap.values();
- }
+export function createColumnSet(): GenericSet<TableColumn> {
+ return new GenericSet((column: TableColumn) => `${column[0]}.${column[1]}`);
}
// Exception thrown by query generator in case incoming parameters are not
@@ -124,7 +98,8 @@
`;
}
-function computeSliceTableAggregations(selectedAggregations: ColumnSet):
+function computeSliceTableAggregations(
+ selectedAggregations: GenericSet<TableColumn>):
{tableName: string, flatAggregations: string[]} {
let hasThreadSliceColumn = false;
const allColumns = [];
@@ -154,8 +129,8 @@
}
export function generateQuery(
- selectedPivots: ColumnSet,
- selectedAggregations: ColumnSet,
+ selectedPivots: GenericSet<TableColumn>,
+ selectedAggregations: GenericSet<TableColumn>,
area: Area,
constrainToArea: boolean): PivotTableReduxQuery {
const sliceTableAggregations =