Merge "docs: Add doc for release process"
diff --git a/CHANGELOG b/CHANGELOG
index 79050a5..c01f292 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,9 +4,9 @@
Trace Processor:
*
UI:
- *
+ * Fixed ADB connection issues ("unable to reset device") on Windows and Mac.
SDK:
- *
+ * Added support for writing track events using custom clock timestamps.
v16.0 - 2021-06-01:
diff --git a/docs/reference/checkpoint-atoms.md b/docs/design-docs/checkpoint-atoms.md
similarity index 100%
rename from docs/reference/checkpoint-atoms.md
rename to docs/design-docs/checkpoint-atoms.md
diff --git a/docs/toc.md b/docs/toc.md
index 6f09a13..b9f8b9c 100644
--- a/docs/toc.md
+++ b/docs/toc.md
@@ -74,3 +74,4 @@
* [Perfetto CI](design-docs/continuous-integration.md)
* [ProtoZero](design-docs/protozero.md)
* [Security model](design-docs/security-model.md)
+ * [Statsd Checkpoint Atoms](design-docs/checkpoint-atoms.md)
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index 12a5a85..9229153 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -35,11 +35,6 @@
namespace perfetto {
-struct TraceTimestamp {
- protos::pbzero::BuiltinClock clock_id;
- uint64_t nanoseconds;
-};
-
// This template provides a way to convert an abstract timestamp into the trace
// clock timebase in nanoseconds. By specialising this template and defining
// static ConvertTimestampToTraceTimeNs function in it the user can register
@@ -60,6 +55,15 @@
}
};
+// A pass-through implementation for the trace timestamp structure.
+template <>
+struct TraceTimestampTraits<TraceTimestamp> {
+ static inline TraceTimestamp ConvertTimestampToTraceTimeNs(
+ const TraceTimestamp& timestamp) {
+ return timestamp;
+ }
+};
+
namespace internal {
namespace {
@@ -440,19 +444,16 @@
return;
}
- // TODO(skyostil): Support additional clock ids.
TraceTimestamp trace_timestamp = ::perfetto::TraceTimestampTraits<
TimestampType>::ConvertTimestampToTraceTimeNs(timestamp);
- PERFETTO_DCHECK(trace_timestamp.clock_id ==
- TrackEventInternal::GetClockId());
// Make sure incremental state is valid.
TraceWriterBase* trace_writer = ctx.tls_inst_->trace_writer.get();
TrackEventIncrementalState* incr_state = ctx.GetIncrementalState();
if (incr_state->was_cleared) {
incr_state->was_cleared = false;
- TrackEventInternal::ResetIncrementalState(
- trace_writer, trace_timestamp.nanoseconds);
+ TrackEventInternal::ResetIncrementalState(trace_writer,
+ trace_timestamp);
}
// Write the track descriptor before any event on the track.
@@ -465,7 +466,7 @@
{
auto event_ctx = TrackEventInternal::WriteEvent(
trace_writer, incr_state, static_category, event_name, type,
- trace_timestamp.nanoseconds);
+ trace_timestamp);
// Write dynamic categories (except for events that don't require
// categories). For counter events, the counter name (and optional
// category) is stored as part of the track descriptor instead being
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index d293039..afd874c 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -32,6 +32,13 @@
#include <unordered_map>
namespace perfetto {
+
+// Represents a point in time for the clock specified by |clock_id|.
+struct TraceTimestamp {
+ protos::pbzero::BuiltinClock clock_id;
+ uint64_t nanoseconds;
+};
+
class EventContext;
class TrackEventSessionObserver;
struct Category;
@@ -139,9 +146,9 @@
const Category* category,
const char* name,
perfetto::protos::pbzero::TrackEvent::Type,
- uint64_t timestamp = GetTimeNs());
+ TraceTimestamp timestamp = {GetClockId(), GetTimeNs()});
- static void ResetIncrementalState(TraceWriterBase*, uint64_t timestamp);
+ static void ResetIncrementalState(TraceWriterBase*, TraceTimestamp);
template <typename T>
static void AddDebugAnnotation(perfetto::EventContext* event_ctx,
@@ -171,7 +178,7 @@
static void WriteTrackDescriptor(const TrackType& track,
TraceWriterBase* trace_writer) {
TrackRegistry::Get()->SerializeTrack(
- track, NewTracePacket(trace_writer, GetTimeNs()));
+ track, NewTracePacket(trace_writer, {GetClockId(), GetTimeNs()}));
}
// Get the current time in nanoseconds in the trace clock timebase.
@@ -195,7 +202,7 @@
private:
static protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket(
TraceWriterBase*,
- uint64_t timestamp,
+ TraceTimestamp,
uint32_t seq_flags =
protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
static protos::pbzero::DebugAnnotation* AddDebugAnnotation(
diff --git a/include/perfetto/tracing/traced_proto.h b/include/perfetto/tracing/traced_proto.h
index 4298bcc..a887d96 100644
--- a/include/perfetto/tracing/traced_proto.h
+++ b/include/perfetto/tracing/traced_proto.h
@@ -130,6 +130,67 @@
namespace internal {
+template <typename FieldMetadata,
+ bool is_message,
+ protozero::proto_utils::RepetitionType repetition_type>
+struct TypedProtoWriterImpl;
+
+// Simple non-repeated field.
+template <typename FieldMetadata>
+struct TypedProtoWriterImpl<
+ FieldMetadata,
+ /*is_message=*/false,
+ protozero::proto_utils::RepetitionType::kNotRepeated> {
+ template <typename Proto, typename ValueType>
+ static void Write(TracedProto<Proto> context, ValueType&& value) {
+ protozero::internal::FieldWriter<FieldMetadata::kProtoFieldType>::Append(
+ *context.message(), FieldMetadata::kFieldId, value);
+ }
+};
+
+// Simple repeated non-packed field.
+template <typename FieldMetadata>
+struct TypedProtoWriterImpl<
+ FieldMetadata,
+ /*is_message=*/false,
+ protozero::proto_utils::RepetitionType::kRepeatedNotPacked> {
+ template <typename Proto, typename ValueType>
+ static void Write(TracedProto<Proto> context, ValueType&& value) {
+ for (auto&& item : value) {
+ protozero::internal::FieldWriter<FieldMetadata::kProtoFieldType>::Append(
+ *context.message(), FieldMetadata::kFieldId, item);
+ }
+ }
+};
+
+// Nested repeated non-packed field.
+template <typename FieldMetadata>
+struct TypedProtoWriterImpl<
+ FieldMetadata,
+ /*is_message=*/true,
+ protozero::proto_utils::RepetitionType::kNotRepeated> {
+ template <typename Proto, typename ValueType>
+ static void Write(TracedProto<Proto> context, ValueType&& value) {
+ // TODO(altimin): support TraceFormatTraits here.
+ value.WriteIntoTrace(context.template WriteNestedMessage<FieldMetadata>());
+ }
+};
+
+// Nested repeated non-packed field.
+template <typename FieldMetadata>
+struct TypedProtoWriterImpl<
+ FieldMetadata,
+ /*is_message=*/true,
+ protozero::proto_utils::RepetitionType::kRepeatedNotPacked> {
+ template <typename Proto, typename ValueType>
+ static void Write(TracedProto<Proto> context, ValueType&& value) {
+ // TODO(altimin): support TraceFormatTraits here.
+ for (auto&& item : value) {
+ item.WriteIntoTrace(context.template WriteNestedMessage<FieldMetadata>());
+ }
+ }
+};
+
// TypedProtoWriter takes the protozero message (TracedProto<MessageType>),
// field description (FieldMetadata) and value and writes the given value
// into the given field of the given protozero message.
@@ -150,58 +211,17 @@
RepetitionType::kRepeatedPacked,
"writing packed fields isn't supported yet");
+ template <bool is_message, RepetitionType repetition_type>
+ struct Writer;
+
public:
- // Implementation note: typename Check=void is used to ensure that SFINAE
- // kicks in and the methods which do not match FieldMetadata do not fail
- // to compile. std::is_same<Check,void> prevents early evaluation of the
- // first enable_if_t argument.
-
- // Simple non-repeated field.
- template <typename Proto, typename ValueType, typename Check = void>
- static typename base::enable_if_t<
- FieldMetadata::kProtoFieldType != ProtoSchemaType::kMessage &&
- FieldMetadata::kRepetitionType == RepetitionType::kNotRepeated &&
- std::is_same<Check, void>::value>
- Write(TracedProto<Proto> context, ValueType&& value) {
- protozero::internal::FieldWriter<FieldMetadata::kProtoFieldType>::Append(
- *context.message(), FieldMetadata::kFieldId, value);
- }
-
- // Simple repeated non-packed field.
- template <typename Proto, typename ValueType, typename Check = void>
- static typename base::enable_if_t<
- FieldMetadata::kProtoFieldType != ProtoSchemaType::kMessage &&
- FieldMetadata::kRepetitionType == RepetitionType::kRepeatedNotPacked &&
- std::is_same<Check, void>::value>
- Write(TracedProto<Proto> context, ValueType&& value) {
- for (auto&& item : value) {
- protozero::internal::FieldWriter<FieldMetadata::kProtoFieldType>::Append(
- *context.message(), FieldMetadata::kFieldId, item);
- }
- }
-
- // Nested non-repeated field.
- template <typename Proto, typename ValueType, typename Check = void>
- static typename base::enable_if_t<
- FieldMetadata::kProtoFieldType == ProtoSchemaType::kMessage &&
- FieldMetadata::kRepetitionType == RepetitionType::kNotRepeated &&
- std::is_same<Check, void>::value>
- Write(TracedProto<Proto> context, ValueType&& value) {
- // TODO(altimin): support TraceFormatTraits here.
- value.WriteIntoTrace(context.template WriteNestedMessage<FieldMetadata>());
- }
-
- // Nested repeated non-packed field.
- template <typename Proto, typename ValueType, typename Check = void>
- static typename base::enable_if_t<
- FieldMetadata::kProtoFieldType == ProtoSchemaType::kMessage &&
- FieldMetadata::kRepetitionType == RepetitionType::kRepeatedNotPacked &&
- std::is_same<Check, void>::value>
- Write(TracedProto<Proto> context, ValueType&& value) {
- // TODO(altimin): support TraceFormatTraits here.
- for (auto&& item : value) {
- item.WriteIntoTrace(context.template WriteNestedMessage<FieldMetadata>());
- }
+ template <typename Proto, typename ValueType>
+ static void Write(TracedProto<Proto> context, ValueType&& value) {
+ TypedProtoWriterImpl<
+ FieldMetadata,
+ FieldMetadata::kProtoFieldType == ProtoSchemaType::kMessage,
+ FieldMetadata::kRepetitionType>::Write(std::move(context),
+ std::forward<ValueType>(value));
}
};
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index b2eb293..ebf198c 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -160,14 +160,10 @@
":platform_impl",
]
- # TODO(primiano/altimin): these sources build with clang-cl but fail to
- # build with MSVC 2019. Investigate.
- if (!is_win || is_clang) {
- sources += [
- "traced_proto_unittest.cc",
- "traced_value_unittest.cc",
- ]
- }
+ sources += [
+ "traced_proto_unittest.cc",
+ "traced_value_unittest.cc",
+ ]
}
}
diff --git a/src/tracing/internal/track_event_internal.cc b/src/tracing/internal/track_event_internal.cc
index 736c312..5e4a154 100644
--- a/src/tracing/internal/track_event_internal.cc
+++ b/src/tracing/internal/track_event_internal.cc
@@ -309,7 +309,7 @@
// static
void TrackEventInternal::ResetIncrementalState(TraceWriterBase* trace_writer,
- uint64_t timestamp) {
+ TraceTimestamp timestamp) {
auto default_track = ThreadTrack::Current();
{
// Mark any incremental state before this point invalid. Also set up
@@ -337,14 +337,18 @@
// static
protozero::MessageHandle<protos::pbzero::TracePacket>
TrackEventInternal::NewTracePacket(TraceWriterBase* trace_writer,
- uint64_t timestamp,
+ TraceTimestamp timestamp,
uint32_t seq_flags) {
auto packet = trace_writer->NewTracePacket();
- packet->set_timestamp(timestamp);
- // TODO(skyostil): Stop emitting this for every event once the trace
- // processor understands trace packet defaults.
- if (GetClockId() != protos::pbzero::BUILTIN_CLOCK_BOOTTIME)
+ packet->set_timestamp(timestamp.nanoseconds);
+ if (timestamp.clock_id != GetClockId()) {
+ packet->set_timestamp_clock_id(static_cast<uint32_t>(timestamp.clock_id));
+ } else if (GetClockId() != protos::pbzero::BUILTIN_CLOCK_BOOTTIME) {
+ // TODO(skyostil): Stop emitting the clock id for the default trace clock
+ // for every event once the trace processor understands trace packet
+ // defaults.
packet->set_timestamp_clock_id(GetClockId());
+ }
packet->set_sequence_flags(seq_flags);
return packet;
}
@@ -356,7 +360,7 @@
const Category* category,
const char* name,
perfetto::protos::pbzero::TrackEvent::Type type,
- uint64_t timestamp) {
+ TraceTimestamp timestamp) {
PERFETTO_DCHECK(g_main_thread);
PERFETTO_DCHECK(!incr_state->was_cleared);
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 061e2fe..ed08a17 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -1473,6 +1473,65 @@
perfetto::TrackEvent::EraseTrackDescriptor(track);
}
+TEST_P(PerfettoApiTest, TrackEventCustomTimestampClock) {
+ // Create a new trace session.
+ auto* tracing_session = NewTraceWithCategories({"foo"});
+ tracing_session->get()->StartBlocking();
+
+ const perfetto::protos::pbzero::BuiltinClock kMyClockId =
+ static_cast<perfetto::protos::pbzero::BuiltinClock>(700);
+ const uint64_t kTimestamp = 12345678;
+
+ // First emit a clock snapshot that maps our custom clock to regular trace
+ // time. Note that the clock snapshot should come before any events
+ // referencing that clock.
+ perfetto::TrackEvent::Trace([](perfetto::TrackEvent::TraceContext ctx) {
+ auto packet = ctx.NewTracePacket();
+ packet->set_timestamp_clock_id(perfetto::TrackEvent::GetTraceClockId());
+ packet->set_timestamp(perfetto::TrackEvent::GetTraceTimeNs());
+ auto* clock_snapshot = packet->set_clock_snapshot();
+ // First set the reference clock, i.e., the default trace clock in this
+ // case.
+ auto* clock = clock_snapshot->add_clocks();
+ clock->set_clock_id(perfetto::TrackEvent::GetTraceClockId());
+ clock->set_timestamp(perfetto::TrackEvent::GetTraceTimeNs());
+ // Then set the value of our reference clock at the same point in time. We
+ // pretend our clock is one second behind trace time.
+ clock = clock_snapshot->add_clocks();
+ clock->set_clock_id(kMyClockId);
+ clock->set_timestamp(kTimestamp + 1000000000ull);
+ });
+
+ // Next emit a trace event with a custom timestamp and a custom clock.
+ TRACE_EVENT_INSTANT("foo", "EventWithCustomTime",
+ perfetto::TraceTimestamp{kMyClockId, kTimestamp});
+ TRACE_EVENT_INSTANT("foo", "EventWithNormalTime");
+
+ perfetto::TrackEvent::Flush();
+ tracing_session->get()->StopBlocking();
+
+ std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ perfetto::protos::gen::Trace trace;
+ ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+
+ // Check that both the clock id and the timestamp got written together with
+ // the packet. Note that we don't check the actual clock sync behavior here
+ // since that happens in the Trace Processor instead.
+ bool found_clock_snapshot = false;
+ bool found_event = false;
+ for (const auto& packet : trace.packet()) {
+ if (packet.has_clock_snapshot())
+ found_clock_snapshot = true;
+ if (!packet.has_track_event() || packet.timestamp() != kTimestamp)
+ continue;
+ found_event = true;
+ EXPECT_EQ(static_cast<uint32_t>(kMyClockId), packet.timestamp_clock_id());
+ EXPECT_EQ(kTimestamp, packet.timestamp());
+ }
+ EXPECT_TRUE(found_clock_snapshot);
+ EXPECT_TRUE(found_event);
+}
+
TEST_P(PerfettoApiTest, LegacyEventWithThreadOverride) {
// Create a new trace session.
auto* tracing_session = NewTraceWithCategories({"cat"});
diff --git a/ui/release/channels.json b/ui/release/channels.json
index 526675f..04e189d 100644
--- a/ui/release/channels.json
+++ b/ui/release/channels.json
@@ -2,11 +2,11 @@
"channels": [
{
"name": "stable",
- "rev": "85ad7248ca898e29e71a6e76ea85f070c4c3e3a9"
+ "rev": "6dd6756ffbdff4f845c4db28e1fd5aed9ba77b56"
},
{
"name": "canary",
- "rev": "bae8193de6c017394901163b7817157342914679"
+ "rev": "3e21f613f20779c04b0bcc937f2605b9b05556ad"
},
{
"name": "autopush",
diff --git a/ui/src/controller/adb.ts b/ui/src/controller/adb.ts
index 5ed6152..47783a6 100644
--- a/ui/src/controller/adb.ts
+++ b/ui/src/controller/adb.ts
@@ -114,8 +114,6 @@
this.key = await AdbOverWebUsb.initKey();
await this.dev.open();
- await this.dev.reset(); // The reset is done so that we can claim the
- // device before adb server can.
const {configValue, usbInterfaceNumber, endpoints} =
this.findInterfaceAndEndpoint();