Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions protos/perfetto/common/builtin_clock.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,55 @@ syntax = "proto2";

package perfetto.protos;

// Builtin clock domains used in Perfetto traces.
//
// The default trace time clock is BUILTIN_CLOCK_TRACE_FILE: a synthetic clock
// representing the trace file's own timeline. Each trace file gets its own
// instance (scoped by trace file index).
//
// For backwards compatibility, Perfetto proto traces register BOOTTIME as a
// fallback: if the first timestamp conversion uses a clock other than the
// trace file clock and no explicit clock snapshot data exists, the trace time
// is switched to BOOTTIME. This fallback does not fire for modern traces that
// include ClockSnapshots or that only use the trace file clock directly.
//
// The `primary_trace_clock` field in ClockSnapshot can definitively override
// the trace time clock regardless of the above.
enum BuiltinClock {
BUILTIN_CLOCK_UNKNOWN = 0;

// Corresponds to CLOCK_REALTIME. See clock_gettime(2).
BUILTIN_CLOCK_REALTIME = 1;

// Corresponds to CLOCK_REALTIME_COARSE. See clock_gettime(2).
BUILTIN_CLOCK_REALTIME_COARSE = 2;

// Corresponds to CLOCK_MONOTONIC. See clock_gettime(2).
BUILTIN_CLOCK_MONOTONIC = 3;

// Corresponds to CLOCK_MONOTONIC_COARSE. See clock_gettime(2).
BUILTIN_CLOCK_MONOTONIC_COARSE = 4;

// Corresponds to CLOCK_MONOTONIC_RAW. See clock_gettime(2).
BUILTIN_CLOCK_MONOTONIC_RAW = 5;

// Corresponds to CLOCK_BOOTTIME. See clock_gettime(2).
// For proto traces, this is used as a backwards-compatible fallback trace
// time clock when no explicit clock snapshots are present.
BUILTIN_CLOCK_BOOTTIME = 6;

// TSC (Time Stamp Counter). Architecture-specific high-resolution counter.
BUILTIN_CLOCK_TSC = 9;

// Corresponds to the perf event clock (PERF_CLOCK).
BUILTIN_CLOCK_PERF = 10;

// A synthetic clock representing the trace file's own timeline. Each trace
// file gets its own instance (scoped by trace file index). This is the
// default trace time clock before any clock snapshot or format-specific
// override takes effect.
BUILTIN_CLOCK_TRACE_FILE = 11;

BUILTIN_CLOCK_MAX_ID = 63;

reserved 7, 8;
Expand Down
39 changes: 39 additions & 0 deletions protos/perfetto/config/perfetto_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -456,16 +456,55 @@ message TracingServiceState {

// Begin of protos/perfetto/common/builtin_clock.proto

// Builtin clock domains used in Perfetto traces.
//
// The default trace time clock is BUILTIN_CLOCK_TRACE_FILE: a synthetic clock
// representing the trace file's own timeline. Each trace file gets its own
// instance (scoped by trace file index).
//
// For backwards compatibility, Perfetto proto traces register BOOTTIME as a
// fallback: if the first timestamp conversion uses a clock other than the
// trace file clock and no explicit clock snapshot data exists, the trace time
// is switched to BOOTTIME. This fallback does not fire for modern traces that
// include ClockSnapshots or that only use the trace file clock directly.
//
// The `primary_trace_clock` field in ClockSnapshot can definitively override
// the trace time clock regardless of the above.
enum BuiltinClock {
BUILTIN_CLOCK_UNKNOWN = 0;

// Corresponds to CLOCK_REALTIME. See clock_gettime(2).
BUILTIN_CLOCK_REALTIME = 1;

// Corresponds to CLOCK_REALTIME_COARSE. See clock_gettime(2).
BUILTIN_CLOCK_REALTIME_COARSE = 2;

// Corresponds to CLOCK_MONOTONIC. See clock_gettime(2).
BUILTIN_CLOCK_MONOTONIC = 3;

// Corresponds to CLOCK_MONOTONIC_COARSE. See clock_gettime(2).
BUILTIN_CLOCK_MONOTONIC_COARSE = 4;

// Corresponds to CLOCK_MONOTONIC_RAW. See clock_gettime(2).
BUILTIN_CLOCK_MONOTONIC_RAW = 5;

// Corresponds to CLOCK_BOOTTIME. See clock_gettime(2).
// For proto traces, this is used as a backwards-compatible fallback trace
// time clock when no explicit clock snapshots are present.
BUILTIN_CLOCK_BOOTTIME = 6;

// TSC (Time Stamp Counter). Architecture-specific high-resolution counter.
BUILTIN_CLOCK_TSC = 9;

// Corresponds to the perf event clock (PERF_CLOCK).
BUILTIN_CLOCK_PERF = 10;

// A synthetic clock representing the trace file's own timeline. Each trace
// file gets its own instance (scoped by trace file index). This is the
// default trace time clock before any clock snapshot or format-specific
// override takes effect.
BUILTIN_CLOCK_TRACE_FILE = 11;

BUILTIN_CLOCK_MAX_ID = 63;

reserved 7, 8;
Expand Down
11 changes: 7 additions & 4 deletions protos/perfetto/trace/clock_snapshot.proto
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,12 @@ message ClockSnapshot {
}
repeated Clock clocks = 1;

// The authoritative clock domain for the trace. Defaults to BOOTTIME, but can
// be overridden in TraceConfig's builtin_data_sources. Trace processor will
// attempt to translate packet/event timestamps from various data sources (and
// their chosen clock domains) to this domain during import.
// The authoritative clock domain for the trace. When set, this definitively
// overrides the trace time clock. If not set, the trace time clock remains
// at its default (BUILTIN_CLOCK_TRACE_FILE), unless a format-specific
// fallback applies (e.g. BOOTTIME for legacy proto traces without clock
// snapshots). Trace processor will attempt to translate packet/event
// timestamps from various data sources (and their chosen clock domains) to
// this domain during import.
optional BuiltinClock primary_trace_clock = 2;
}
50 changes: 46 additions & 4 deletions protos/perfetto/trace/perfetto_trace.proto
Original file line number Diff line number Diff line change
Expand Up @@ -456,16 +456,55 @@ message TracingServiceState {

// Begin of protos/perfetto/common/builtin_clock.proto

// Builtin clock domains used in Perfetto traces.
//
// The default trace time clock is BUILTIN_CLOCK_TRACE_FILE: a synthetic clock
// representing the trace file's own timeline. Each trace file gets its own
// instance (scoped by trace file index).
//
// For backwards compatibility, Perfetto proto traces register BOOTTIME as a
// fallback: if the first timestamp conversion uses a clock other than the
// trace file clock and no explicit clock snapshot data exists, the trace time
// is switched to BOOTTIME. This fallback does not fire for modern traces that
// include ClockSnapshots or that only use the trace file clock directly.
//
// The `primary_trace_clock` field in ClockSnapshot can definitively override
// the trace time clock regardless of the above.
enum BuiltinClock {
BUILTIN_CLOCK_UNKNOWN = 0;

// Corresponds to CLOCK_REALTIME. See clock_gettime(2).
BUILTIN_CLOCK_REALTIME = 1;

// Corresponds to CLOCK_REALTIME_COARSE. See clock_gettime(2).
BUILTIN_CLOCK_REALTIME_COARSE = 2;

// Corresponds to CLOCK_MONOTONIC. See clock_gettime(2).
BUILTIN_CLOCK_MONOTONIC = 3;

// Corresponds to CLOCK_MONOTONIC_COARSE. See clock_gettime(2).
BUILTIN_CLOCK_MONOTONIC_COARSE = 4;

// Corresponds to CLOCK_MONOTONIC_RAW. See clock_gettime(2).
BUILTIN_CLOCK_MONOTONIC_RAW = 5;

// Corresponds to CLOCK_BOOTTIME. See clock_gettime(2).
// For proto traces, this is used as a backwards-compatible fallback trace
// time clock when no explicit clock snapshots are present.
BUILTIN_CLOCK_BOOTTIME = 6;

// TSC (Time Stamp Counter). Architecture-specific high-resolution counter.
BUILTIN_CLOCK_TSC = 9;

// Corresponds to the perf event clock (PERF_CLOCK).
BUILTIN_CLOCK_PERF = 10;

// A synthetic clock representing the trace file's own timeline. Each trace
// file gets its own instance (scoped by trace file index). This is the
// default trace time clock before any clock snapshot or format-specific
// override takes effect.
BUILTIN_CLOCK_TRACE_FILE = 11;

BUILTIN_CLOCK_MAX_ID = 63;

reserved 7, 8;
Expand Down Expand Up @@ -7971,10 +8010,13 @@ message ClockSnapshot {
}
repeated Clock clocks = 1;

// The authoritative clock domain for the trace. Defaults to BOOTTIME, but can
// be overridden in TraceConfig's builtin_data_sources. Trace processor will
// attempt to translate packet/event timestamps from various data sources (and
// their chosen clock domains) to this domain during import.
// The authoritative clock domain for the trace. When set, this definitively
// overrides the trace time clock. If not set, the trace time clock remains
// at its default (BUILTIN_CLOCK_TRACE_FILE), unless a format-specific
// fallback applies (e.g. BOOTTIME for legacy proto traces without clock
// snapshots). Trace processor will attempt to translate packet/event
// timestamps from various data sources (and their chosen clock domains) to
// this domain during import.
optional BuiltinClock primary_trace_clock = 2;
}

Expand Down
1 change: 1 addition & 0 deletions src/trace_processor/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ source_set("storage_minimal") {
"tables",
"types",
"util:blob",
"util:clock",
"util:descriptors",
"util:gzip",
"util:proto_to_args_parser",
Expand Down
31 changes: 31 additions & 0 deletions src/trace_processor/forwarding_trace_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "perfetto/ext/base/status_macros.h"
#include "perfetto/trace_processor/basic_types.h"
#include "src/trace_processor/importers/common/chunked_trace_reader.h"
#include "src/trace_processor/importers/common/clock_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/trace_file_tracker.h"
#include "src/trace_processor/importers/proto/proto_trace_reader.h"
Expand All @@ -33,8 +34,11 @@
#include "src/trace_processor/tables/metadata_tables_py.h"
#include "src/trace_processor/trace_reader_registry.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/util/clock_synchronizer.h"
#include "src/trace_processor/util/trace_type.h"

#include "protos/perfetto/common/builtin_clock.pbzero.h"

namespace perfetto::trace_processor {
namespace {

Expand Down Expand Up @@ -140,6 +144,33 @@ base::Status ForwardingTraceParser::Init(const TraceBlobView& blob) {
}
ASSIGN_OR_RETURN(reader_, input_context_->reader_registry->CreateTraceReader(
trace_type_, trace_context_));

// Centralize clock setup for all trace formats. Proto traces add an identity
// sync so BOOTTIME is reachable in the clock graph; the trace default clock
// is set later by ParseClockSnapshot. All other formats know their clock
// statically and set the global clock directly.
using ClockId = ClockTracker::ClockId;
if (trace_type_ == kProtoTraceType) {
trace_context_->clock_tracker->AddDeferredIdentitySync(
ClockId::Machine(protos::pbzero::BUILTIN_CLOCK_BOOTTIME));
} else if (trace_type_ == kSystraceTraceType ||
trace_type_ == kSimpleperfProtoTraceType ||
trace_type_ == kPerfTextTraceType ||
trace_type_ == kPerfDataTraceType ||
trace_type_ == kArtMethodTraceType) {
trace_context_->clock_tracker->SetGlobalClock(
ClockId::Machine(protos::pbzero::BUILTIN_CLOCK_MONOTONIC));
} else if (trace_type_ == kFuchsiaTraceType) {
trace_context_->clock_tracker->SetGlobalClock(
ClockId::Machine(protos::pbzero::BUILTIN_CLOCK_BOOTTIME));
} else if (trace_type_ == kGeckoTraceType || trace_type_ == kJsonTraceType ||
trace_type_ == kInstrumentsXmlTraceType) {
trace_context_->clock_tracker->SetGlobalClock(
ClockId::TraceFile(trace_context_->trace_id().value));
} else if (trace_type_ == kAndroidDumpstateTraceType) {
trace_context_->clock_tracker->SetGlobalClock(
ClockId::Machine(protos::pbzero::BUILTIN_CLOCK_REALTIME));
}
return base::OkStatus();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ base::Status AndroidBatteryStatsReader::SendToSorter(
std::chrono::nanoseconds event_ts,
AndroidDumpstateEvent event) {
std::optional<int64_t> trace_ts = context_->clock_tracker->ToTraceTime(
ClockTracker::ClockId(protos::pbzero::ClockSnapshot::Clock::REALTIME),
ClockId::Machine(protos::pbzero::ClockSnapshot::Clock::REALTIME),
event_ts.count());
if (trace_ts) {
stream_->Push(*trace_ts, std::move(event));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "src/trace_processor/importers/common/clock_tracker.h"
#include "src/trace_processor/importers/common/trace_file_tracker.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/util/clock_synchronizer.h"
#include "src/trace_processor/util/trace_type.h"
#include "src/trace_processor/util/zip_reader.h"

Expand Down Expand Up @@ -95,7 +96,14 @@ std::optional<FindBugReportFileResult> FindBugReportFile(

AndroidBugreportReader::AndroidBugreportReader(TraceProcessorContext* context)
: context_(context),
dumpstate_reader_(std::make_unique<AndroidDumpstateReader>(context_)) {}
dumpstate_reader_(std::make_unique<AndroidDumpstateReader>(context_)) {
// All logs in Android bugreports use wall time (which creates problems
// in case of early boot events before NTP kicks in, which get emitted as
// 1970), but that is the state of affairs.
using ClockId = ClockTracker::ClockId;
context_->clock_tracker->SetGlobalClock(
ClockId::Machine(protos::pbzero::BUILTIN_CLOCK_REALTIME));
}

AndroidBugreportReader::~AndroidBugreportReader() = default;

Expand Down Expand Up @@ -129,12 +137,6 @@ base::Status AndroidBugreportReader::Parse(std::vector<util::ZipFile> files) {
ordered_log_files.insert(LogFile{id, timestamp, std::move(files[i])});
}

// All logs in Android bugreports use wall time (which creates problems
// in case of early boot events before NTP kicks in, which get emitted as
// 1970), but that is the state of affairs.
context_->clock_tracker->SetTraceTimeClock(
ClockTracker::ClockId(protos::pbzero::BUILTIN_CLOCK_REALTIME));

ASSIGN_OR_RETURN(std::vector<TimestampedAndroidLogEvent> logcat_events,
ParseDumpstateTxt(bug_report));
return ParsePersistentLogcat(bug_report, ordered_log_files,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/string_view_splitter.h"
#include "protos/perfetto/common/builtin_clock.pbzero.h"
#include "src/trace_processor/importers/android_bugreport/android_battery_stats_reader.h"
#include "src/trace_processor/importers/android_bugreport/android_log_reader.h"
#include "src/trace_processor/importers/common/clock_tracker.h"
Expand All @@ -53,9 +52,6 @@ base::Status AndroidDumpstateReader::ParseLine(base::StringView line) {
base::Status AndroidDumpstateReader::ParseLine(
BufferingAndroidLogReader* const log_reader,
base::StringView line) {
context_->clock_tracker->SetTraceTimeClock(
ClockTracker::ClockId(protos::pbzero::BUILTIN_CLOCK_REALTIME));

// Dumpstate is organized in a two level hierarchy, beautifully flattened into
// one text file with load bearing ----- markers:
// 1. Various dumpstate sections, examples:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,7 @@ base::Status AndroidLogReader::SendToSorter(std::chrono::nanoseconds event_ts,
int64_t ts =
event_ts.count() - context_->clock_tracker->timezone_offset().value_or(0);
std::optional<int64_t> trace_ts = context_->clock_tracker->ToTraceTime(
ClockTracker::ClockId(protos::pbzero::ClockSnapshot::Clock::REALTIME),
ts);
ClockId::Machine(protos::pbzero::ClockSnapshot::Clock::REALTIME), ts);
if (trace_ts) {
stream_->Push(*trace_ts, event);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/types/trace_processor_context_ptr.h"
#include "src/trace_processor/util/clock_synchronizer.h"
#include "test/gtest_and_gmock.h"

#include "protos/perfetto/common/android_log_constants.pbzero.h"
Expand Down Expand Up @@ -74,12 +76,16 @@ class AndroidLogReaderTest : public ::testing::Test {
TraceProcessorContextPtr<TraceProcessorContext::TraceState>::MakeRoot(
TraceProcessorContext::TraceState{TraceId(0)});
context_.metadata_tracker = std::make_unique<MetadataTracker>(&context_);
context_.trace_time_state = std::make_unique<TraceTimeState>(TraceTimeState{
ClockTracker::ClockId(protos::pbzero::BUILTIN_CLOCK_BOOTTIME), false});
context_.trace_time_state = std::make_unique<TraceTimeState>(
ClockId::Machine(protos::pbzero::BUILTIN_CLOCK_BOOTTIME));
primary_sync_ = std::make_unique<ClockSynchronizer>(
context_.trace_time_state.get(),
std::make_unique<ClockSynchronizerListenerImpl>(&context_));
context_.clock_tracker = std::make_unique<ClockTracker>(
&context_, std::make_unique<ClockSynchronizerListenerImpl>(&context_));
context_.clock_tracker->SetTraceTimeClock(
ClockTracker::ClockId(protos::pbzero::ClockSnapshot::Clock::REALTIME));
&context_, std::make_unique<ClockSynchronizerListenerImpl>(&context_),
primary_sync_.get(), true);
context_.clock_tracker->SetGlobalClock(
ClockId::Machine(protos::pbzero::ClockSnapshot::Clock::REALTIME));
context_.sorter = std::make_unique<TraceSorter>(
&context_, TraceSorter::SortingMode::kDefault);
}
Expand All @@ -92,6 +98,7 @@ class AndroidLogReaderTest : public ::testing::Test {

private:
TraceProcessorContext context_;
std::unique_ptr<ClockSynchronizer> primary_sync_;
};

TEST_F(AndroidLogReaderTest, PersistentLogFormat) {
Expand Down
Loading
Loading