Skip to content

Commit

Permalink
Merge "Add 'clone_snapshot_trigger' packet to the trace if it was clo…
Browse files Browse the repository at this point in the history
…ned by the trigger." into main
  • Loading branch information
Kirill Timofeev authored and Gerrit Code Review committed Nov 23, 2024
2 parents dc890fc + af72efb commit 80533e6
Show file tree
Hide file tree
Showing 13 changed files with 430 additions and 37 deletions.
13 changes: 13 additions & 0 deletions include/perfetto/ext/tracing/core/tracing_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,19 @@ class PERFETTO_EXPORT_COMPONENT ConsumerEndpoint {
// If set, affects the generation of the FlushFlags::CloneTarget to be set
// to kBugreport when requesting the flush to the producers.
bool for_bugreport = false;

// If not empty, this is stored in the trace as name of the trigger that
// caused the clone.
std::string clone_trigger_name;
// If not empty, this is stored in the trace as name of the producer that
// triggered the clone.
std::string clone_trigger_producer_name;
// If not zero, this is stored in the trace as uid of the producer that
// triggered the clone.
uid_t clone_trigger_trusted_producer_uid = 0;
// If not zero, this is stored in the trace as timestamp of the trigger that
// caused the clone.
uint64_t clone_trigger_boot_time_ns = 0;
};
virtual void CloneSession(CloneSessionArgs) = 0;

Expand Down
8 changes: 7 additions & 1 deletion protos/perfetto/common/observable_events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,14 @@ message ObservableEvents {
// there is no other good way to plumb it.
optional int64 tracing_session_id = 1;

// The trigger name of the CLONE_SNAPSHOT trigger which was hit.
// The name of the CLONE_SNAPSHOT trigger which was hit.
optional string trigger_name = 2;
// The name of the producer that sent the CLONE_SNAPSHOT trigger.
optional string producer_name = 3;
// The uid of the producer that sent the CLONE_SNAPSHOT trigger.
optional uint32 producer_uid = 4;
// The timestamp of the CLONE_SNAPSHOT trigger which was hit.
optional uint64 boot_time_ns = 5;
}

repeated DataSourceInstanceStateChange instance_state_changes = 1;
Expand Down
13 changes: 13 additions & 0 deletions protos/perfetto/ipc/consumer_port.proto
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,19 @@ message CloneSessionRequest {
// If set, affects the generation of the FlushFlags::CloneTarget to be set
// to kBugreport when requesting the flush to the producers.
optional bool for_bugreport = 3;

// If set, this is stored in the trace as name of the trigger that caused the
// clone.
optional string clone_trigger_name = 5;
// If set, this is stored in the trace as name of the producer that triggered
// the clone.
optional string clone_trigger_producer_name = 6;
// If set, this is stored in the trace as uid of the producer that triggered
// the clone.
optional int32 clone_trigger_trusted_producer_uid = 7;
// If set, this is stored in the trace as timestamp of the trigger that caused
// the clone.
optional uint64 clone_trigger_boot_time_ns = 8;
}

message CloneSessionResponse {
Expand Down
4 changes: 3 additions & 1 deletion protos/perfetto/trace/perfetto_trace.proto
Original file line number Diff line number Diff line change
Expand Up @@ -15672,7 +15672,7 @@ message UiState {
// See the [Buffers and Dataflow](/docs/concepts/buffers.md) doc for details.
//
// Next reserved id: 14 (up to 15).
// Next id: 113.
// Next id: 114.
message TracePacket {
// The timestamp of the TracePacket.
// By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
Expand Down Expand Up @@ -15812,6 +15812,8 @@ message TracePacket {
PixelModemEvents pixel_modem_events = 110;
PixelModemTokenDatabase pixel_modem_token_database = 111;

Trigger clone_snapshot_trigger = 113;

// This field is only used for testing.
// In previous versions of this proto this field had the id 268435455
// This caused many problems:
Expand Down
4 changes: 3 additions & 1 deletion protos/perfetto/trace/trace_packet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ package perfetto.protos;
// See the [Buffers and Dataflow](/docs/concepts/buffers.md) doc for details.
//
// Next reserved id: 14 (up to 15).
// Next id: 113.
// Next id: 114.
message TracePacket {
// The timestamp of the TracePacket.
// By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
Expand Down Expand Up @@ -244,6 +244,8 @@ message TracePacket {
PixelModemEvents pixel_modem_events = 110;
PixelModemTokenDatabase pixel_modem_token_database = 111;

Trigger clone_snapshot_trigger = 113;

// This field is only used for testing.
// In previous versions of this proto this field had the id 268435455
// This caused many problems:
Expand Down
41 changes: 26 additions & 15 deletions src/perfetto_cmd/perfetto_cmd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -989,11 +989,11 @@ int PerfettoCmd::ConnectToServiceAndRun() {
}

if (is_clone()) {
if (snapshot_trigger_name_.empty()) {
if (!snapshot_trigger_info_.has_value()) {
LogUploadEvent(PerfettoStatsdAtom::kCmdCloneTraceBegin);
} else {
LogUploadEvent(PerfettoStatsdAtom::kCmdCloneTriggerTraceBegin,
snapshot_trigger_name_);
snapshot_trigger_info_->trigger_name);
}
} else if (trace_config_->trigger_config().trigger_timeout_ms() == 0) {
LogUploadEvent(PerfettoStatsdAtom::kTraceBegin);
Expand Down Expand Up @@ -1076,6 +1076,13 @@ void PerfettoCmd::OnConnect() {
} else if (!clone_name_.empty()) {
args.unique_session_name = clone_name_;
}
if (snapshot_trigger_info_.has_value()) {
args.clone_trigger_name = snapshot_trigger_info_->trigger_name;
args.clone_trigger_producer_name = snapshot_trigger_info_->producer_name;
args.clone_trigger_trusted_producer_uid =
snapshot_trigger_info_->producer_uid;
args.clone_trigger_boot_time_ns = snapshot_trigger_info_->boot_time_ns;
}
consumer_endpoint_->CloneSession(std::move(args));
return;
}
Expand Down Expand Up @@ -1384,11 +1391,11 @@ void PerfettoCmd::OnSessionCloned(const OnSessionClonedArgs& args) {
uuid_ = args.uuid.ToString();

// Log the new UUID with the clone tag.
if (snapshot_trigger_name_.empty()) {
if (!snapshot_trigger_info_.has_value()) {
LogUploadEvent(PerfettoStatsdAtom::kCmdOnSessionClone);
} else {
LogUploadEvent(PerfettoStatsdAtom::kCmdOnTriggerSessionClone,
snapshot_trigger_name_);
snapshot_trigger_info_->trigger_name);
}
ReadbackTraceDataAndQuit(full_error);
}
Expand Down Expand Up @@ -1520,15 +1527,19 @@ void PerfettoCmd::OnObservableEvents(
}
if (observable_events.has_clone_trigger_hit()) {
int64_t tsid = observable_events.clone_trigger_hit().tracing_session_id();
std::string trigger_name =
observable_events.clone_trigger_hit().trigger_name();
SnapshotTriggerInfo trigger = {
observable_events.clone_trigger_hit().boot_time_ns(),
observable_events.clone_trigger_hit().trigger_name(),
observable_events.clone_trigger_hit().producer_name(),
observable_events.clone_trigger_hit().producer_uid()};
OnCloneSnapshotTriggerReceived(static_cast<TracingSessionID>(tsid),
std::move(trigger_name));
trigger);
}
}

void PerfettoCmd::OnCloneSnapshotTriggerReceived(TracingSessionID tsid,
std::string trigger_name) {
void PerfettoCmd::OnCloneSnapshotTriggerReceived(
TracingSessionID tsid,
const SnapshotTriggerInfo& trigger) {
std::string cmdline;
cmdline.reserve(128);
ArgsAppend(&cmdline, "perfetto");
Expand All @@ -1546,15 +1557,14 @@ void PerfettoCmd::OnCloneSnapshotTriggerReceived(TracingSessionID tsid,
} else {
PERFETTO_FATAL("Cannot use CLONE_SNAPSHOT with the current cmdline args");
}
CloneSessionOnThread(tsid, cmdline, kSingleExtraThread,
std::move(trigger_name), nullptr);
CloneSessionOnThread(tsid, cmdline, kSingleExtraThread, trigger, nullptr);
}

void PerfettoCmd::CloneSessionOnThread(
TracingSessionID tsid,
const std::string& cmdline,
CloneThreadMode thread_mode,
std::string trigger_name,
const std::optional<SnapshotTriggerInfo>& trigger,
std::function<void()> on_clone_callback) {
PERFETTO_DLOG("Creating snapshot for tracing session %" PRIu64, tsid);

Expand All @@ -1576,7 +1586,7 @@ void PerfettoCmd::CloneSessionOnThread(
std::string trace_config_copy = trace_config_->SerializeAsString();

snapshot_threads_.back().PostTask(
[tsid, cmdline, trace_config_copy, trigger_name, on_clone_callback] {
[tsid, cmdline, trace_config_copy, trigger, on_clone_callback] {
int argc = 0;
char* argv[32];
// `splitter` needs to live on the stack for the whole scope as it owns
Expand All @@ -1588,7 +1598,7 @@ void PerfettoCmd::CloneSessionOnThread(
}
perfetto::PerfettoCmd cmd;
cmd.snapshot_config_ = std::move(trace_config_copy);
cmd.snapshot_trigger_name_ = std::move(trigger_name);
cmd.snapshot_trigger_info_ = trigger;
cmd.on_session_cloned_ = on_clone_callback;
auto cmdline_res = cmd.ParseCmdlineAndMaybeDaemonize(argc, argv);
PERFETTO_CHECK(!cmdline_res.has_value()); // No daemonization expected.
Expand Down Expand Up @@ -1680,7 +1690,8 @@ void PerfettoCmd::CloneAllBugreportTraces(
ArgsAppend(&cmdline, "--clone-for-bugreport");
ArgsAppend(&cmdline, "--out");
ArgsAppend(&cmdline, out_path);
CloneSessionOnThread(it->tsid, cmdline, kNewThreadPerRequest, "", sync_fn);
CloneSessionOnThread(it->tsid, cmdline, kNewThreadPerRequest, std::nullopt,
sync_fn);
} // for(sessions)

PERFETTO_DLOG("Issuing %zu CloneSession requests", num_sessions);
Expand Down
20 changes: 17 additions & 3 deletions src/perfetto_cmd/perfetto_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class PerfettoCmd : public Consumer {
void SignalCtrlC() { ctrl_c_evt_.Notify(); }

private:
struct SnapshotTriggerInfo;

enum CloneThreadMode { kSingleExtraThread, kNewThreadPerRequest };

bool OpenOutputFile();
Expand All @@ -83,10 +85,11 @@ class PerfettoCmd : public Consumer {
void PrintUsage(const char* argv0);
void PrintServiceState(bool success, const TracingServiceState&);
void CloneAllBugreportTraces(bool success, const TracingServiceState&);

void CloneSessionOnThread(TracingSessionID,
const std::string& cmdline, // \0 separated.
CloneThreadMode,
std::string clone_trigger_name,
const std::optional<SnapshotTriggerInfo>& trigger,
std::function<void()> on_clone_callback);
void OnTimeout();
bool is_detach() const { return !detach_key_.empty(); }
Expand Down Expand Up @@ -131,7 +134,7 @@ class PerfettoCmd : public Consumer {
void NotifyBgProcessPipe(BgProcessStatus status);

void OnCloneSnapshotTriggerReceived(TracingSessionID,
std::string trigger_name);
const SnapshotTriggerInfo& trigger);

#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
static base::ScopedFile CreateUnlinkedTmpFile();
Expand Down Expand Up @@ -191,7 +194,18 @@ class PerfettoCmd : public Consumer {
std::list<base::ThreadTaskRunner> snapshot_threads_;
int snapshot_count_ = 0;
std::string snapshot_config_;
std::string snapshot_trigger_name_;
// If the trigger caused the clone operation, we want to save the information
// about that trigger to the trace We may get multiple triggers with the same
// name, so we pass the entire structure to uniquely identify the trigger
// later. This structure is identical to the
// `TracingServiceImpl::TriggerInfo`.
struct SnapshotTriggerInfo {
uint64_t boot_time_ns = 0;
std::string trigger_name;
std::string producer_name;
uid_t producer_uid = 0;
};
std::optional<SnapshotTriggerInfo> snapshot_trigger_info_;

base::WeakPtrFactory<PerfettoCmd> weak_factory_{this};
};
Expand Down
13 changes: 13 additions & 0 deletions src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,19 @@ void ConsumerIPCClientImpl::CloneSession(CloneSessionArgs args) {
}
req.set_skip_trace_filter(args.skip_trace_filter);
req.set_for_bugreport(args.for_bugreport);
if (!args.clone_trigger_name.empty()) {
req.set_clone_trigger_name(args.clone_trigger_name);
}
if (!args.clone_trigger_producer_name.empty()) {
req.set_clone_trigger_producer_name(args.clone_trigger_producer_name);
}
if (args.clone_trigger_trusted_producer_uid != 0) {
req.set_clone_trigger_trusted_producer_uid(
static_cast<int32_t>(args.clone_trigger_trusted_producer_uid));
}
if (args.clone_trigger_boot_time_ns != 0) {
req.set_clone_trigger_boot_time_ns(args.clone_trigger_boot_time_ns);
}
ipc::Deferred<protos::gen::CloneSessionResponse> async_response;
auto weak_this = weak_ptr_factory_.GetWeakPtr();

Expand Down
13 changes: 13 additions & 0 deletions src/tracing/ipc/service/consumer_ipc_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,19 @@ void ConsumerIPCService::CloneSession(
if (req.has_unique_session_name()) {
args.unique_session_name = req.unique_session_name();
}
if (req.has_clone_trigger_name()) {
args.clone_trigger_name = req.clone_trigger_name();
}
if (req.has_clone_trigger_producer_name()) {
args.clone_trigger_producer_name = req.clone_trigger_producer_name();
}
if (req.has_clone_trigger_trusted_producer_uid()) {
args.clone_trigger_trusted_producer_uid =
static_cast<uid_t>(req.clone_trigger_trusted_producer_uid());
}
if (req.has_clone_trigger_boot_time_ns()) {
args.clone_trigger_boot_time_ns = req.clone_trigger_boot_time_ns();
}
remote_consumer->service_endpoint->CloneSession(std::move(args));
}

Expand Down
Loading

0 comments on commit 80533e6

Please sign in to comment.