[tracing] perfetto::Flow
Add perfetto::Flow and perfetto::TerminatingFlow helpers which can be
passed directly to TRACE_EVENT macros to populate the corresponding
proto fields.
R=eseckler@google.com
Change-Id: I7eaac2fdb0fe01872670f7b6754191adfe0fbd14
diff --git a/BUILD b/BUILD
index 264030b..57cbfbd 100644
--- a/BUILD
+++ b/BUILD
@@ -583,6 +583,7 @@
"include/perfetto/tracing/tracing_policy.h",
"include/perfetto/tracing/track.h",
"include/perfetto/tracing/track_event.h",
+ "include/perfetto/tracing/track_event_args.h",
"include/perfetto/tracing/track_event_category_registry.h",
"include/perfetto/tracing/track_event_interned_data_index.h",
"include/perfetto/tracing/track_event_legacy.h",
diff --git a/include/perfetto/tracing/BUILD.gn b/include/perfetto/tracing/BUILD.gn
index b7a91d0..f73dafd 100644
--- a/include/perfetto/tracing/BUILD.gn
+++ b/include/perfetto/tracing/BUILD.gn
@@ -61,6 +61,7 @@
"tracing_policy.h",
"track.h",
"track_event.h",
+ "track_event_args.h",
"track_event_category_registry.h",
"track_event_interned_data_index.h",
"track_event_legacy.h",
diff --git a/include/perfetto/tracing/internal/write_track_event_args.h b/include/perfetto/tracing/internal/write_track_event_args.h
index f34dc3a..f6e3b7f 100644
--- a/include/perfetto/tracing/internal/write_track_event_args.h
+++ b/include/perfetto/tracing/internal/write_track_event_args.h
@@ -20,6 +20,7 @@
#include "perfetto/base/compiler.h"
#include "perfetto/tracing/event_context.h"
#include "perfetto/tracing/traced_proto.h"
+#include "perfetto/tracing/track_event_args.h"
namespace perfetto {
namespace internal {
diff --git a/include/perfetto/tracing/track_event_args.h b/include/perfetto/tracing/track_event_args.h
new file mode 100644
index 0000000..8e9ec49
--- /dev/null
+++ b/include/perfetto/tracing/track_event_args.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_ARGS_H_
+#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_ARGS_H_
+
+#include "perfetto/tracing/event_context.h"
+
+#include <functional>
+
+namespace perfetto {
+
+// A helper to add |flow_id| as a non-terminating flow id to TRACE_EVENT
+// inline: TRACE_EVENT(..., perfetto::Flow(42));
+PERFETTO_ALWAYS_INLINE inline std::function<void(EventContext&)> Flow(
+ uint64_t flow_id) {
+ return [flow_id](perfetto::EventContext& ctx) {
+ ctx.event()->add_flow_ids(flow_id);
+ };
+}
+
+PERFETTO_ALWAYS_INLINE inline std::function<void(EventContext&)>
+TerminatingFlow(uint64_t flow_id) {
+ return [flow_id](perfetto::EventContext& ctx) {
+ ctx.event()->add_terminating_flow_ids(flow_id);
+ };
+}
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_ARGS_H_
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 68c5e6e..a55e5d5 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -661,6 +661,34 @@
slice += ")";
}
+ if (track_event.flow_ids_size()) {
+ slice += "(flow_ids=";
+ std::stringstream value;
+ bool first_annotation = true;
+ for (uint64_t id : track_event.flow_ids()) {
+ if (!first_annotation) {
+ value << ",";
+ }
+ first_annotation = false;
+ value << id;
+ }
+ slice += value.str() + ")";
+ }
+
+ if (track_event.terminating_flow_ids_size()) {
+ slice += "(terminating_flow_ids=";
+ std::stringstream value;
+ bool first_annotation = true;
+ for (uint64_t id : track_event.terminating_flow_ids()) {
+ if (!first_annotation) {
+ value << ",";
+ }
+ value << id;
+ first_annotation = false;
+ }
+ slice += value.str() + ")";
+ }
+
slices.push_back(slice);
}
EXPECT_TRUE(incremental_state_was_cleared);
@@ -1860,11 +1888,13 @@
};
};
-void CheckLogMessagePresent(const std::vector<char>& raw_trace) {
+void CheckTypedArguments(
+ const std::vector<char>& raw_trace,
+ std::function<void(const perfetto::protos::gen::TrackEvent&)> checker) {
perfetto::protos::gen::Trace parsed_trace;
ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
- bool found_args = false;
+ bool found_begin_slice = false;
for (const auto& packet : parsed_trace.packet()) {
if (!packet.has_track_event())
continue;
@@ -1874,13 +1904,20 @@
continue;
}
- EXPECT_TRUE(track_event.has_log_message());
- const auto& log = track_event.log_message();
- EXPECT_EQ(1u, log.source_location_iid());
- EXPECT_EQ(2u, log.body_iid());
- found_args = true;
+ checker(track_event);
+ found_begin_slice = true;
}
- EXPECT_TRUE(found_args);
+ EXPECT_TRUE(found_begin_slice);
+}
+
+void CheckLogMessagePresent(const std::vector<char>& raw_trace) {
+ CheckTypedArguments(raw_trace,
+ [](const perfetto::protos::gen::TrackEvent& track_event) {
+ EXPECT_TRUE(track_event.has_log_message());
+ const auto& log = track_event.log_message();
+ EXPECT_EQ(1u, log.source_location_iid());
+ EXPECT_EQ(2u, log.body_iid());
+ });
}
} // namespace
@@ -2100,6 +2137,66 @@
ElementsAre("B:foo.E(arg=(string)value)"));
}
+TEST_P(PerfettoApiTest, TrackEventArgs_Flow) {
+ // Create a new trace session.
+ auto* tracing_session = NewTraceWithCategories({"foo"});
+ tracing_session->get()->StartBlocking();
+
+ TRACE_EVENT_BEGIN("foo", "E", perfetto::Flow(42));
+ TRACE_EVENT_END("foo");
+
+ tracing_session->get()->StopBlocking();
+
+ std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+
+ // Find typed argument.
+ CheckTypedArguments(
+ raw_trace, [](const perfetto::protos::gen::TrackEvent& track_event) {
+ EXPECT_THAT(track_event.flow_ids(), testing::ElementsAre(42));
+ });
+}
+
+TEST_P(PerfettoApiTest, TrackEventArgs_TerminatingFlow) {
+ // Create a new trace session.
+ auto* tracing_session = NewTraceWithCategories({"foo"});
+ tracing_session->get()->StartBlocking();
+
+ TRACE_EVENT_BEGIN("foo", "E", perfetto::TerminatingFlow(42));
+ TRACE_EVENT_END("foo");
+
+ tracing_session->get()->StopBlocking();
+
+ std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+
+ // Find typed argument.
+ CheckTypedArguments(raw_trace,
+ [](const perfetto::protos::gen::TrackEvent& track_event) {
+ EXPECT_THAT(track_event.terminating_flow_ids(),
+ testing::ElementsAre(42));
+ });
+}
+
+TEST_P(PerfettoApiTest, TrackEventArgs_MultipleFlows) {
+ // Create a new trace session.
+ auto* tracing_session = NewTraceWithCategories({"foo"});
+ tracing_session->get()->StartBlocking();
+
+ {
+ TRACE_EVENT("foo", "E1", perfetto::Flow(1), perfetto::Flow(2),
+ perfetto::Flow(3));
+ }
+ { TRACE_EVENT("foo", "E2", perfetto::Flow(1), perfetto::TerminatingFlow(2)); }
+ { TRACE_EVENT("foo", "E3", perfetto::TerminatingFlow(3)); }
+
+ tracing_session->get()->StopBlocking();
+
+ std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
+ ElementsAre("B:foo.E1(flow_ids=1,2,3)", "E",
+ "B:foo.E2(flow_ids=1)(terminating_flow_ids=2)", "E",
+ "B:foo.E3(terminating_flow_ids=3)"));
+}
+
struct InternedLogMessageBody
: public perfetto::TrackEventInternedDataIndex<
InternedLogMessageBody,