Tracing API: Add FlushFlags
Give a way to producer to tell what's the reason for the flush.
For future-proofing and ease of plumbing the flags are implemented
as a uint64 which overlays different sub-fields.
Test: updated perfetto_unittests & perfetto_integrationtests
Bug: 293429094
Change-Id: I6f8ff60832d8bec8b8b8aa8b7b019ac0b2081748
diff --git a/BUILD b/BUILD
index 078b4df..f47bcc3 100644
--- a/BUILD
+++ b/BUILD
@@ -849,6 +849,7 @@
"include/perfetto/tracing/core/chrome_config.h",
"include/perfetto/tracing/core/data_source_config.h",
"include/perfetto/tracing/core/data_source_descriptor.h",
+ "include/perfetto/tracing/core/flush_flags.h",
"include/perfetto/tracing/core/trace_config.h",
"include/perfetto/tracing/core/tracing_service_capabilities.h",
"include/perfetto/tracing/core/tracing_service_state.h",
diff --git a/include/perfetto/ext/tracing/core/producer.h b/include/perfetto/ext/tracing/core/producer.h
index d1ca85d..234c406 100644
--- a/include/perfetto/ext/tracing/core/producer.h
+++ b/include/perfetto/ext/tracing/core/producer.h
@@ -19,7 +19,9 @@
#include "perfetto/base/export.h"
#include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/flush_flags.h"
#include "perfetto/tracing/core/forward_decls.h"
+
namespace perfetto {
class SharedMemory;
@@ -106,7 +108,8 @@
// flushes < N have also been committed.
virtual void Flush(FlushRequestID,
const DataSourceInstanceID* data_source_ids,
- size_t num_data_sources) = 0;
+ size_t num_data_sources,
+ FlushFlags) = 0;
// Called by the service to instruct the given data sources to stop referring
// to any trace contents emitted so far. The intent is that after processing
diff --git a/include/perfetto/ext/tracing/core/tracing_service.h b/include/perfetto/ext/tracing/core/tracing_service.h
index b82a96a..690795f 100644
--- a/include/perfetto/ext/tracing/core/tracing_service.h
+++ b/include/perfetto/ext/tracing/core/tracing_service.h
@@ -30,6 +30,7 @@
#include "perfetto/ext/tracing/core/shared_memory.h"
#include "perfetto/ext/tracing/core/trace_packet.h"
#include "perfetto/tracing/buffer_exhausted_policy.h"
+#include "perfetto/tracing/core/flush_flags.h"
#include "perfetto/tracing/core/forward_decls.h"
namespace perfetto {
@@ -203,7 +204,15 @@
// if that one is not set (or is set to 0), kDefaultFlushTimeoutMs (5s) is
// used.
using FlushCallback = std::function<void(bool /*success*/)>;
- virtual void Flush(uint32_t timeout_ms, FlushCallback) = 0;
+ virtual void Flush(uint32_t timeout_ms, FlushCallback callback, FlushFlags);
+
+ // The only caller of this method is arctraceservice's PerfettoClient.
+ // Everything else in the codebase uses the 3-arg Flush() above.
+ // TODO(primiano): remove the overload without FlushFlags once
+ // arctraceservice moves away from this interface. arctraceservice lives in
+ // the internal repo and changes to this interface require multi-side patches.
+ // Inernally this calls Flush(timeout, callback, FlushFlags(0)).
+ virtual void Flush(uint32_t timeout_ms, FlushCallback callback);
// Tracing data will be delivered invoking Consumer::OnTraceData().
virtual void ReadBuffers() = 0;
diff --git a/include/perfetto/tracing/core/BUILD.gn b/include/perfetto/tracing/core/BUILD.gn
index c961c2d..9ea0e2c 100644
--- a/include/perfetto/tracing/core/BUILD.gn
+++ b/include/perfetto/tracing/core/BUILD.gn
@@ -22,6 +22,7 @@
"chrome_config.h",
"data_source_config.h",
"data_source_descriptor.h",
+ "flush_flags.h",
"trace_config.h",
"tracing_service_capabilities.h",
"tracing_service_state.h",
diff --git a/include/perfetto/tracing/core/flush_flags.h b/include/perfetto/tracing/core/flush_flags.h
new file mode 100644
index 0000000..12445b5
--- /dev/null
+++ b/include/perfetto/tracing/core/flush_flags.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2023 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_CORE_FLUSH_FLAGS_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_FLUSH_FLAGS_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace perfetto {
+
+// This class is a wrapper around the uint64_t flags that are sent across the
+// tracing protocol whenenver a flush occurs. It helps determining the reason
+// and initiator of the flush.
+// NOTE: the values here are part of the tracing protocol ABI. Do not renumber.
+class FlushFlags {
+ public:
+ enum class Initiator : uint64_t {
+ // DO NOT RENUMBER, ABI.
+ kUnknown = 0,
+ kTraced = 1,
+ kPerfettoCmd = 2,
+ kConsumerSdk = 3,
+ kMax,
+ };
+
+ enum class Reason : uint64_t {
+ // DO NOT RENUMBER, ABI.
+ kUnknown = 0,
+ kPeriodic = 1,
+ kTraceStop = 2,
+ kTraceClone = 3,
+ kExplicit = 4,
+ kMax,
+ };
+
+ enum class CloneTarget : uint64_t {
+ // DO NOT RENUMBER, ABI.
+ kUnknown = 0,
+ kBugreport = 1,
+ kMax,
+ };
+
+ explicit FlushFlags(uint64_t flags = 0) : flags_(flags) {}
+ FlushFlags(Initiator i, Reason r, CloneTarget c = CloneTarget::kUnknown)
+ : flags_((static_cast<uint64_t>(i) << kInitiatorShift) |
+ (static_cast<uint64_t>(r) << kReasonShift) |
+ (static_cast<uint64_t>(c) << kCloneTargetShift)) {}
+
+ bool operator==(const FlushFlags& o) const { return flags_ == o.flags_; }
+ bool operator!=(const FlushFlags& o) const { return !(*this == o); }
+
+ Initiator initiator() const {
+ // Due to version mismatch we might see a value from the future that we
+ // didn't know yet. If that happens, short ciruit to kUnknown.
+ static_assert(
+ uint64_t(Initiator::kMax) - 1 <= (kInitiatorMask >> kInitiatorShift),
+ "enum out of range");
+ const uint64_t value = (flags_ & kInitiatorMask) >> kInitiatorShift;
+ return value < uint64_t(Initiator::kMax) ? Initiator(value)
+ : Initiator::kUnknown;
+ }
+
+ Reason reason() const {
+ static_assert(uint64_t(Reason::kMax) - 1 <= (kReasonMask >> kReasonShift),
+ "enum out of range");
+ const uint64_t value = (flags_ & kReasonMask) >> kReasonShift;
+ return value < uint64_t(Reason::kMax) ? Reason(value) : Reason::kUnknown;
+ }
+
+ CloneTarget clone_target() const {
+ static_assert(uint64_t(CloneTarget::kMax) - 1 <=
+ (kCloneTargetMask >> kCloneTargetShift),
+ "enum out of range");
+ const uint64_t value = (flags_ & kCloneTargetMask) >> kCloneTargetShift;
+ return value < uint64_t(CloneTarget::kMax) ? CloneTarget(value)
+ : CloneTarget::kUnknown;
+ }
+
+ uint64_t flags() const { return flags_; }
+
+ private:
+ // DO NOT CHANGE, ABI.
+ static constexpr uint64_t kReasonMask = 0xF;
+ static constexpr uint64_t kReasonShift = 0;
+ static constexpr uint64_t kInitiatorMask = 0xF0;
+ static constexpr uint64_t kInitiatorShift = 4;
+ static constexpr uint64_t kCloneTargetMask = 0xF00;
+ static constexpr uint64_t kCloneTargetShift = 8;
+
+ uint64_t flags_ = 0;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_CORE_FLUSH_FLAGS_H_
diff --git a/include/perfetto/tracing/data_source.h b/include/perfetto/tracing/data_source.h
index 925e4dd..4bcd04e 100644
--- a/include/perfetto/tracing/data_source.h
+++ b/include/perfetto/tracing/data_source.h
@@ -33,6 +33,7 @@
#include "perfetto/protozero/message_handle.h"
#include "perfetto/tracing/buffer_exhausted_policy.h"
+#include "perfetto/tracing/core/flush_flags.h"
#include "perfetto/tracing/core/forward_decls.h"
#include "perfetto/tracing/internal/basic_types.h"
#include "perfetto/tracing/internal/data_source_internal.h"
@@ -160,6 +161,9 @@
// The index of this data source instance (0..kMaxDataSourceInstances - 1).
uint32_t internal_instance_index = 0;
+
+ // The reason and initiator of the flush. See flush_flags.h .
+ FlushFlags flush_flags;
};
// Called when the tracing service requests a Flush. Users can override this
// to tell other threads to flush their TraceContext for this data source
diff --git a/protos/perfetto/ipc/consumer_port.proto b/protos/perfetto/ipc/consumer_port.proto
index 2fdc919..b587846 100644
--- a/protos/perfetto/ipc/consumer_port.proto
+++ b/protos/perfetto/ipc/consumer_port.proto
@@ -205,6 +205,10 @@
// Arguments for rpc Flush().
message FlushRequest {
optional uint32 timeout_ms = 1;
+
+ // More details such as flush reason and originator. Introduced in v38 / V.
+ // See FlushFlags in include/perfetto/ext/tracing/core/flush_flags.h.
+ optional uint64 flags = 2;
}
message FlushResponse {}
diff --git a/protos/perfetto/ipc/producer_port.proto b/protos/perfetto/ipc/producer_port.proto
index 5c204cb..9e3d5d1 100644
--- a/protos/perfetto/ipc/producer_port.proto
+++ b/protos/perfetto/ipc/producer_port.proto
@@ -318,6 +318,10 @@
// expected to copy this value back into the CommitDataRequest, so the
// service can tell when the data for this flush has been committed.
optional uint64 request_id = 2;
+
+ // More details such as flush reason and originator. Introduced in v38 / V.
+ // See FlushFlags in include/perfetto/ext/tracing/core/flush_flags.h.
+ optional uint64 flags = 3;
}
// Instructs the given data sources to stop referring to any trace contents
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index 3052341..2ddbf04 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -1264,13 +1264,17 @@
return;
PERFETTO_LOG("SIGINT/SIGTERM received: disabling tracing.");
weak_this->ctrl_c_evt_.Clear();
- weak_this->consumer_endpoint_->Flush(0, [weak_this](bool flush_success) {
- if (!weak_this)
- return;
- if (!flush_success)
- PERFETTO_ELOG("Final flush unsuccessful.");
- weak_this->consumer_endpoint_->DisableTracing();
- });
+ weak_this->consumer_endpoint_->Flush(
+ 0,
+ [weak_this](bool flush_success) {
+ if (!weak_this)
+ return;
+ if (!flush_success)
+ PERFETTO_ELOG("Final flush unsuccessful.");
+ weak_this->consumer_endpoint_->DisableTracing();
+ },
+ FlushFlags(FlushFlags::Initiator::kPerfettoCmd,
+ FlushFlags::Reason::kTraceStop));
});
}
@@ -1305,13 +1309,17 @@
if (stop_trace_once_attached_) {
auto weak_this = weak_factory_.GetWeakPtr();
- consumer_endpoint_->Flush(0, [weak_this](bool flush_success) {
- if (!weak_this)
- return;
- if (!flush_success)
- PERFETTO_ELOG("Final flush unsuccessful.");
- weak_this->consumer_endpoint_->DisableTracing();
- });
+ consumer_endpoint_->Flush(
+ 0,
+ [weak_this](bool flush_success) {
+ if (!weak_this)
+ return;
+ if (!flush_success)
+ PERFETTO_ELOG("Final flush unsuccessful.");
+ weak_this->consumer_endpoint_->DisableTracing();
+ },
+ FlushFlags(FlushFlags::Initiator::kPerfettoCmd,
+ FlushFlags::Reason::kTraceStop));
}
}
diff --git a/src/perfetto_cmd/trigger_producer.cc b/src/perfetto_cmd/trigger_producer.cc
index 7aefabd..a3abf5a 100644
--- a/src/perfetto_cmd/trigger_producer.cc
+++ b/src/perfetto_cmd/trigger_producer.cc
@@ -81,7 +81,8 @@
}
void TriggerProducer::Flush(FlushRequestID,
const DataSourceInstanceID*,
- size_t) {
+ size_t,
+ FlushFlags) {
PERFETTO_DFATAL("Attempted to Flush() on commandline producer");
}
diff --git a/src/perfetto_cmd/trigger_producer.h b/src/perfetto_cmd/trigger_producer.h
index 0a31bd3..90cd489 100644
--- a/src/perfetto_cmd/trigger_producer.h
+++ b/src/perfetto_cmd/trigger_producer.h
@@ -47,7 +47,10 @@
void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
void StartDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
void StopDataSource(DataSourceInstanceID) override;
- void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override;
+ void Flush(FlushRequestID,
+ const DataSourceInstanceID*,
+ size_t,
+ FlushFlags) override;
void ClearIncrementalState(const DataSourceInstanceID* data_source_ids,
size_t num_data_sources) override;
diff --git a/src/profiling/memory/heapprofd_producer.cc b/src/profiling/memory/heapprofd_producer.cc
index d4b8ccc..7490115 100644
--- a/src/profiling/memory/heapprofd_producer.cc
+++ b/src/profiling/memory/heapprofd_producer.cc
@@ -765,7 +765,8 @@
void HeapprofdProducer::Flush(FlushRequestID flush_id,
const DataSourceInstanceID* ids,
- size_t num_ids) {
+ size_t num_ids,
+ FlushFlags) {
size_t& flush_in_progress = flushes_in_progress_[flush_id];
PERFETTO_DCHECK(flush_in_progress == 0);
flush_in_progress = num_ids;
diff --git a/src/profiling/memory/heapprofd_producer.h b/src/profiling/memory/heapprofd_producer.h
index fa1f058..f1473c8 100644
--- a/src/profiling/memory/heapprofd_producer.h
+++ b/src/profiling/memory/heapprofd_producer.h
@@ -119,7 +119,8 @@
void OnTracingSetup() override;
void Flush(FlushRequestID,
const DataSourceInstanceID* data_source_ids,
- size_t num_data_sources) override;
+ size_t num_data_sources,
+ FlushFlags) override;
void ClearIncrementalState(const DataSourceInstanceID* /*data_source_ids*/,
size_t /*num_data_sources*/) override {}
diff --git a/src/profiling/memory/java_hprof_producer.cc b/src/profiling/memory/java_hprof_producer.cc
index 01bd01c..9049bc3 100644
--- a/src/profiling/memory/java_hprof_producer.cc
+++ b/src/profiling/memory/java_hprof_producer.cc
@@ -163,7 +163,8 @@
void JavaHprofProducer::Flush(FlushRequestID flush_id,
const DataSourceInstanceID*,
- size_t) {
+ size_t,
+ FlushFlags) {
endpoint_->NotifyFlushComplete(flush_id);
}
diff --git a/src/profiling/memory/java_hprof_producer.h b/src/profiling/memory/java_hprof_producer.h
index 4355d96..8591718 100644
--- a/src/profiling/memory/java_hprof_producer.h
+++ b/src/profiling/memory/java_hprof_producer.h
@@ -52,7 +52,8 @@
void OnTracingSetup() override {}
void Flush(FlushRequestID,
const DataSourceInstanceID* data_source_ids,
- size_t num_data_sources) override;
+ size_t num_data_sources,
+ FlushFlags) override;
void ClearIncrementalState(const DataSourceInstanceID* /*data_source_ids*/,
size_t /*num_data_sources*/) override {}
// TODO(fmayer): Refactor once/if we have generic reconnect logic.
diff --git a/src/profiling/perf/perf_producer.cc b/src/profiling/perf/perf_producer.cc
index fec5b6d..109b580 100644
--- a/src/profiling/perf/perf_producer.cc
+++ b/src/profiling/perf/perf_producer.cc
@@ -561,7 +561,8 @@
// the SMB.
void PerfProducer::Flush(FlushRequestID flush_id,
const DataSourceInstanceID* data_source_ids,
- size_t num_data_sources) {
+ size_t num_data_sources,
+ FlushFlags) {
// Flush metatracing if requested.
for (size_t i = 0; i < num_data_sources; i++) {
auto ds_id = data_source_ids[i];
diff --git a/src/profiling/perf/perf_producer.h b/src/profiling/perf/perf_producer.h
index 83174d3..8cd6eb2 100644
--- a/src/profiling/perf/perf_producer.h
+++ b/src/profiling/perf/perf_producer.h
@@ -78,7 +78,8 @@
void StopDataSource(DataSourceInstanceID instance_id) override;
void Flush(FlushRequestID flush_id,
const DataSourceInstanceID* data_source_ids,
- size_t num_data_sources) override;
+ size_t num_data_sources,
+ FlushFlags) override;
void ClearIncrementalState(const DataSourceInstanceID* data_source_ids,
size_t num_data_sources) override;
diff --git a/src/traced/probes/probes_producer.cc b/src/traced/probes/probes_producer.cc
index f4528ab..0aff1db 100644
--- a/src/traced/probes/probes_producer.cc
+++ b/src/traced/probes/probes_producer.cc
@@ -502,7 +502,8 @@
void ProbesProducer::Flush(FlushRequestID flush_request_id,
const DataSourceInstanceID* data_source_ids,
- size_t num_data_sources) {
+ size_t num_data_sources,
+ FlushFlags) {
PERFETTO_DLOG("ProbesProducer::Flush(%" PRIu64 ") begin", flush_request_id);
PERFETTO_DCHECK(flush_request_id);
auto log_on_exit = base::OnScopeExit([&] {
diff --git a/src/traced/probes/probes_producer.h b/src/traced/probes/probes_producer.h
index b021ee5..e7a4203 100644
--- a/src/traced/probes/probes_producer.h
+++ b/src/traced/probes/probes_producer.h
@@ -56,7 +56,8 @@
void OnTracingSetup() override;
void Flush(FlushRequestID,
const DataSourceInstanceID* data_source_ids,
- size_t num_data_sources) override;
+ size_t num_data_sources,
+ FlushFlags) override;
void ClearIncrementalState(const DataSourceInstanceID* data_source_ids,
size_t num_data_sources) override;
diff --git a/src/traced/service/builtin_producer.cc b/src/traced/service/builtin_producer.cc
index 6516100..b9c5a97 100644
--- a/src/traced/service/builtin_producer.cc
+++ b/src/traced/service/builtin_producer.cc
@@ -284,7 +284,8 @@
void BuiltinProducer::Flush(FlushRequestID flush_id,
const DataSourceInstanceID* ds_ids,
- size_t num_ds_ids) {
+ size_t num_ds_ids,
+ FlushFlags) {
for (size_t i = 0; i < num_ds_ids; i++) {
auto meta_it = metatrace_.writers.find(ds_ids[i]);
if (meta_it != metatrace_.writers.end()) {
diff --git a/src/traced/service/builtin_producer.h b/src/traced/service/builtin_producer.h
index 7f0d892..7eb3f94 100644
--- a/src/traced/service/builtin_producer.h
+++ b/src/traced/service/builtin_producer.h
@@ -43,7 +43,10 @@
void OnConnect() override;
void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
void StartDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
- void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override;
+ void Flush(FlushRequestID,
+ const DataSourceInstanceID*,
+ size_t,
+ FlushFlags) override;
void StopDataSource(DataSourceInstanceID) override;
// nops:
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index d7f5634..7b421c3 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -1748,7 +1748,8 @@
void TracingServiceImpl::Flush(TracingSessionID tsid,
uint32_t timeout_ms,
- ConsumerEndpoint::FlushCallback callback) {
+ ConsumerEndpoint::FlushCallback callback,
+ FlushFlags flush_flags) {
PERFETTO_DCHECK_THREAD(thread_checker_);
TracingSession* tracing_session = GetTracingSession(tsid);
if (!tracing_session) {
@@ -1794,7 +1795,7 @@
ProducerID producer_id = kv.first;
ProducerEndpointImpl* producer = GetProducer(producer_id);
const std::vector<DataSourceInstanceID>& data_sources = kv.second;
- producer->Flush(flush_request_id, data_sources);
+ producer->Flush(flush_request_id, data_sources, flush_flags);
pending_flush.producers.insert(producer_id);
}
@@ -2001,27 +2002,32 @@
PERFETTO_DCHECK_THREAD(thread_checker_);
PERFETTO_DLOG("Triggering final flush for %" PRIu64, tsid);
auto weak_this = weak_ptr_factory_.GetWeakPtr();
- Flush(tsid, 0, [weak_this, tsid](bool success) {
- // This was a DLOG up to Jun 2021 (v16, Android S).
- PERFETTO_LOG("FlushAndDisableTracing(%" PRIu64 ") done, success=%d", tsid,
- success);
- if (!weak_this)
- return;
- TracingSession* session = weak_this->GetTracingSession(tsid);
- session->final_flush_outcome = success ? TraceStats::FINAL_FLUSH_SUCCEEDED
+ Flush(
+ tsid, 0,
+ [weak_this, tsid](bool success) {
+ // This was a DLOG up to Jun 2021 (v16, Android S).
+ PERFETTO_LOG("FlushAndDisableTracing(%" PRIu64 ") done, success=%d",
+ tsid, success);
+ if (!weak_this)
+ return;
+ TracingSession* session = weak_this->GetTracingSession(tsid);
+ session->final_flush_outcome = success
+ ? TraceStats::FINAL_FLUSH_SUCCEEDED
: TraceStats::FINAL_FLUSH_FAILED;
- if (session->consumer_maybe_null) {
- // If the consumer is still attached, just disable the session but give it
- // a chance to read the contents.
- weak_this->DisableTracing(tsid);
- } else {
- // If the consumer detached, destroy the session. If the consumer did
- // start the session in long-tracing mode, the service will have saved
- // the contents to the passed file. If not, the contents will be
- // destroyed.
- weak_this->FreeBuffers(tsid);
- }
- });
+ if (session->consumer_maybe_null) {
+ // If the consumer is still attached, just disable the session but
+ // give it a chance to read the contents.
+ weak_this->DisableTracing(tsid);
+ } else {
+ // If the consumer detached, destroy the session. If the consumer did
+ // start the session in long-tracing mode, the service will have saved
+ // the contents to the passed file. If not, the contents will be
+ // destroyed.
+ weak_this->FreeBuffers(tsid);
+ }
+ },
+ FlushFlags(FlushFlags::Initiator::kTraced,
+ FlushFlags::Reason::kTraceStop));
}
void TracingServiceImpl::PeriodicFlushTask(TracingSessionID tsid,
@@ -2045,10 +2051,14 @@
return;
PERFETTO_DLOG("Triggering periodic flush for trace session %" PRIu64, tsid);
- Flush(tsid, 0, [](bool success) {
- if (!success)
- PERFETTO_ELOG("Periodic flush timed out");
- });
+ Flush(
+ tsid, 0,
+ [](bool success) {
+ if (!success)
+ PERFETTO_ELOG("Periodic flush timed out");
+ },
+ FlushFlags(FlushFlags::Initiator::kTraced,
+ FlushFlags::Reason::kPeriodic));
}
void TracingServiceImpl::PeriodicClearIncrementalStateTask(
@@ -3591,6 +3601,7 @@
void TracingServiceImpl::FlushAndCloneSession(ConsumerEndpointImpl* consumer,
TracingSessionID tsid) {
PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto clone_target = FlushFlags::CloneTarget::kUnknown;
if (tsid == kBugreportSessionId) {
TracingSession* session = FindTracingSessionWithMaxBugreportScore();
@@ -3600,21 +3611,26 @@
return;
}
tsid = session->id;
+ clone_target = FlushFlags::CloneTarget::kBugreport;
}
auto weak_this = weak_ptr_factory_.GetWeakPtr();
auto weak_consumer = consumer->GetWeakPtr();
- Flush(tsid, 0, [weak_this, tsid, weak_consumer](bool final_flush_outcome) {
- PERFETTO_LOG("FlushAndCloneSession(%" PRIu64 ") started, success=%d", tsid,
- final_flush_outcome);
- if (!weak_this || !weak_consumer)
- return;
- base::Uuid uuid;
- base::Status result = weak_this->DoCloneSession(&*weak_consumer, tsid,
- final_flush_outcome, &uuid);
- weak_consumer->consumer_->OnSessionCloned(
- {result.ok(), result.message(), uuid});
- });
+ Flush(
+ tsid, 0,
+ [weak_this, tsid, weak_consumer](bool final_flush_outcome) {
+ PERFETTO_LOG("FlushAndCloneSession(%" PRIu64 ") started, success=%d",
+ tsid, final_flush_outcome);
+ if (!weak_this || !weak_consumer)
+ return;
+ base::Uuid uuid;
+ base::Status result = weak_this->DoCloneSession(
+ &*weak_consumer, tsid, final_flush_outcome, &uuid);
+ weak_consumer->consumer_->OnSessionCloned(
+ {result.ok(), result.message(), uuid});
+ },
+ FlushFlags(FlushFlags::Initiator::kTraced,
+ FlushFlags::Reason::kTraceClone, clone_target));
}
base::Status TracingServiceImpl::DoCloneSession(ConsumerEndpointImpl* consumer,
@@ -3826,13 +3842,14 @@
}
void TracingServiceImpl::ConsumerEndpointImpl::Flush(uint32_t timeout_ms,
- FlushCallback callback) {
+ FlushCallback callback,
+ FlushFlags flush_flags) {
PERFETTO_DCHECK_THREAD(thread_checker_);
if (!tracing_session_id_) {
PERFETTO_LOG("Consumer called Flush() but tracing was not active");
return;
}
- service_->Flush(tracing_session_id_, timeout_ms, callback);
+ service_->Flush(tracing_session_id_, timeout_ms, callback, flush_flags);
}
void TracingServiceImpl::ConsumerEndpointImpl::Detach(const std::string& key) {
@@ -4319,15 +4336,17 @@
void TracingServiceImpl::ProducerEndpointImpl::Flush(
FlushRequestID flush_request_id,
- const std::vector<DataSourceInstanceID>& data_sources) {
+ const std::vector<DataSourceInstanceID>& data_sources,
+ FlushFlags flush_flags) {
PERFETTO_DCHECK_THREAD(thread_checker_);
auto weak_this = weak_ptr_factory_.GetWeakPtr();
- task_runner_->PostTask([weak_this, flush_request_id, data_sources] {
- if (weak_this) {
- weak_this->producer_->Flush(flush_request_id, data_sources.data(),
- data_sources.size());
- }
- });
+ task_runner_->PostTask(
+ [weak_this, flush_request_id, data_sources, flush_flags] {
+ if (weak_this) {
+ weak_this->producer_->Flush(flush_request_id, data_sources.data(),
+ data_sources.size(), flush_flags);
+ }
+ });
}
void TracingServiceImpl::ProducerEndpointImpl::SetupDataSource(
diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h
index 1a146c9..e9c85ee 100644
--- a/src/tracing/core/tracing_service_impl.h
+++ b/src/tracing/core/tracing_service_impl.h
@@ -136,7 +136,9 @@
void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&);
void StartDataSource(DataSourceInstanceID, const DataSourceConfig&);
void StopDataSource(DataSourceInstanceID);
- void Flush(FlushRequestID, const std::vector<DataSourceInstanceID>&);
+ void Flush(FlushRequestID,
+ const std::vector<DataSourceInstanceID>&,
+ FlushFlags);
void OnFreeBuffers(const std::vector<BufferID>& target_buffers);
void ClearIncrementalState(const std::vector<DataSourceInstanceID>&);
@@ -219,7 +221,7 @@
void DisableTracing() override;
void ReadBuffers() override;
void FreeBuffers() override;
- void Flush(uint32_t timeout_ms, FlushCallback) override;
+ void Flush(uint32_t timeout_ms, FlushCallback, FlushFlags) override;
void Detach(const std::string& key) override;
void Attach(const std::string& key) override;
void GetTraceStats() override;
@@ -306,7 +308,8 @@
void DisableTracing(TracingSessionID, bool disable_immediately = false);
void Flush(TracingSessionID tsid,
uint32_t timeout_ms,
- ConsumerEndpoint::FlushCallback);
+ ConsumerEndpoint::FlushCallback,
+ FlushFlags);
void FlushAndDisableTracing(TracingSessionID);
void FlushAndCloneSession(ConsumerEndpointImpl*, TracingSessionID);
diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc
index 7583d33..3aa050c 100644
--- a/src/tracing/core/tracing_service_impl_unittest.cc
+++ b/src/tracing/core/tracing_service_impl_unittest.cc
@@ -786,7 +786,8 @@
bool flushed_writer_1 = false;
bool flushed_writer_2 = false;
auto flush_correct_writer = [&](FlushRequestID flush_req_id,
- const DataSourceInstanceID* id, size_t) {
+ const DataSourceInstanceID* id, size_t,
+ FlushFlags) {
if (*id == id1) {
flushed_writer_1 = true;
writer1->Flush();
@@ -797,7 +798,9 @@
producer->endpoint()->NotifyFlushComplete(flush_req_id);
}
};
- EXPECT_CALL(*producer, Flush(_, _, _))
+ FlushFlags flush_flags(FlushFlags::Initiator::kTraced,
+ FlushFlags::Reason::kTraceStop);
+ EXPECT_CALL(*producer, Flush(_, _, _, flush_flags))
.WillOnce(Invoke(flush_correct_writer))
.WillOnce(Invoke(flush_correct_writer));
@@ -2111,7 +2114,9 @@
}));
consumer2->CloneSession(1);
// CloneSession() will implicitly issue a flush. Linearize with that.
- producer->ExpectFlush(std::vector<TraceWriter*>{writer.get()});
+ FlushFlags expected_flags(FlushFlags::Initiator::kTraced,
+ FlushFlags::Reason::kTraceClone);
+ producer->ExpectFlush(writer.get(), /*reply=*/true, expected_flags);
task_runner.RunUntilCheckpoint("clone_done");
// Delete the initial tracing session.
@@ -2454,7 +2459,9 @@
}
auto flush_request = consumer->Flush();
- producer->ExpectFlush(writer.get());
+ FlushFlags expected_flags(FlushFlags::Initiator::kConsumerSdk,
+ FlushFlags::Reason::kExplicit);
+ producer->ExpectFlush(writer.get(), /*reply=*/true, expected_flags);
ASSERT_TRUE(flush_request.WaitForReply());
consumer->DisableTracing();
@@ -2492,7 +2499,9 @@
tp->set_for_testing()->set_str("payload");
}
- producer->ExpectFlush(writer.get());
+ FlushFlags expected_flags(FlushFlags::Initiator::kTraced,
+ FlushFlags::Reason::kTraceStop);
+ producer->ExpectFlush(writer.get(), /*reply=*/true, expected_flags);
producer->WaitForDataSourceStop("data_source");
consumer->WaitForTracingDisabled();
@@ -2591,10 +2600,13 @@
const int kNumFlushes = 3;
auto checkpoint = task_runner.CreateCheckpoint("all_flushes_done");
int flushes_seen = 0;
- EXPECT_CALL(*producer, Flush(_, _, _))
+ FlushFlags flush_flags(FlushFlags::Initiator::kTraced,
+ FlushFlags::Reason::kPeriodic);
+ EXPECT_CALL(*producer, Flush(_, _, _, flush_flags))
.WillRepeatedly(Invoke([&producer, &writer, &flushes_seen, checkpoint](
FlushRequestID flush_req_id,
- const DataSourceInstanceID*, size_t) {
+ const DataSourceInstanceID*, size_t,
+ FlushFlags) {
{
auto tp = writer->NewTracePacket();
char payload[32];
@@ -4709,6 +4721,10 @@
std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
consumer->Connect(svc.get());
+ std::unique_ptr<MockProducer> producer = CreateMockProducer();
+ producer->Connect(svc.get(), "mock_producer");
+ producer->RegisterDataSource("ds_1");
+
// The consumer that clones it and reads back the data.
std::unique_ptr<MockConsumer> consumer2 = CreateMockConsumer();
consumer2->Connect(svc.get(), 1234);
@@ -4716,9 +4732,18 @@
TraceConfig trace_config;
trace_config.add_buffers()->set_size_kb(32);
trace_config.set_bugreport_score(1);
+ auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
+ ds_cfg->set_name("ds_1");
+ EXPECT_CALL(*producer, SetupDataSource(_, _));
+ EXPECT_CALL(*producer, StartDataSource(_, _));
consumer->EnableTracing(trace_config);
+ producer->WaitForTracingSetup();
+
auto flush_request = consumer->Flush();
+ FlushFlags flush_flags(FlushFlags::Initiator::kConsumerSdk,
+ FlushFlags::Reason::kExplicit);
+ producer->ExpectFlush({}, /*reply=*/true, flush_flags);
ASSERT_TRUE(flush_request.WaitForReply());
auto clone_done = task_runner.CreateCheckpoint("clone_done");
@@ -4727,7 +4752,13 @@
clone_done();
ASSERT_TRUE(args.success);
}));
- consumer2->CloneSession(1);
+
+ FlushFlags flush_flags2(FlushFlags::Initiator::kTraced,
+ FlushFlags::Reason::kTraceClone,
+ FlushFlags::CloneTarget::kBugreport);
+ producer->ExpectFlush({}, /*reply=*/true, flush_flags2);
+
+ consumer2->CloneSession(kBugreportSessionId);
task_runner.RunUntilCheckpoint("clone_done");
}
diff --git a/src/tracing/core/virtual_destructors.cc b/src/tracing/core/virtual_destructors.cc
index d38a776..6c94741 100644
--- a/src/tracing/core/virtual_destructors.cc
+++ b/src/tracing/core/virtual_destructors.cc
@@ -40,4 +40,18 @@
void ConsumerEndpoint::CloneSession(TracingSessionID) {}
void Consumer::OnSessionCloned(const OnSessionClonedArgs&) {}
+void ConsumerEndpoint::Flush(uint32_t, FlushCallback, FlushFlags) {
+ // In the perfetto codebase, this 3-arg Flush is always overridden and this
+ // FATAL is never reached. The only case where this is used is in
+ // arctraceservice's PerfettoClient_test.cpp. That test mocks the old
+ // 2-arg version of Flush but doesn't actually invoke the 3-arg version.
+ PERFETTO_FATAL("ConsumerEndpoint::Flush(3) not implemented");
+}
+
+void ConsumerEndpoint::Flush(uint32_t timeout_ms, FlushCallback callback) {
+ // This 2-arg version of Flush() is invoked by arctraceservice's
+ // PerfettoClient::Flush().
+ Flush(timeout_ms, std::move(callback), FlushFlags(0));
+}
+
} // namespace perfetto
diff --git a/src/tracing/internal/tracing_backend_fake.cc b/src/tracing/internal/tracing_backend_fake.cc
index 4b0d31e..438da32 100644
--- a/src/tracing/internal/tracing_backend_fake.cc
+++ b/src/tracing/internal/tracing_backend_fake.cc
@@ -115,7 +115,9 @@
void StartTracing() override {}
void DisableTracing() override {}
- void Flush(uint32_t /*timeout_ms*/, FlushCallback callback) override {
+ void Flush(uint32_t /*timeout_ms*/,
+ FlushCallback callback,
+ FlushFlags) override {
callback(/*success=*/false);
}
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index e953823..738cf31 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -296,14 +296,15 @@
void TracingMuxerImpl::ProducerImpl::Flush(
FlushRequestID flush_id,
const DataSourceInstanceID* instances,
- size_t instance_count) {
+ size_t instance_count,
+ FlushFlags flush_flags) {
PERFETTO_DCHECK_THREAD(thread_checker_);
bool all_handled = true;
if (muxer_) {
for (size_t i = 0; i < instance_count; i++) {
DataSourceInstanceID ds_id = instances[i];
- bool handled =
- muxer_->FlushDataSource_AsyncBegin(backend_id_, ds_id, flush_id);
+ bool handled = muxer_->FlushDataSource_AsyncBegin(backend_id_, ds_id,
+ flush_id, flush_flags);
if (!handled) {
pending_flushes_[flush_id].insert(ds_id);
all_handled = false;
@@ -1115,34 +1116,33 @@
InterceptorFactory factory,
InterceptorBase::TLSFactory tls_factory,
InterceptorBase::TracePacketCallback packet_callback) {
- task_runner_->PostTask(
- [this, descriptor, factory, tls_factory, packet_callback] {
- // Ignore repeated registrations.
- for (const auto& interceptor : interceptors_) {
- if (interceptor.descriptor.name() == descriptor.name()) {
- PERFETTO_DCHECK(interceptor.tls_factory == tls_factory);
- PERFETTO_DCHECK(interceptor.packet_callback == packet_callback);
- return;
- }
- }
- // Only allow certain interceptors for now.
- if (descriptor.name() != "test_interceptor" &&
- descriptor.name() != "console" &&
- descriptor.name() != "etwexport") {
- PERFETTO_ELOG(
- "Interceptors are experimental. If you want to use them, please "
- "get in touch with the project maintainers "
- "(https://perfetto.dev/docs/contributing/"
- "getting-started#community).");
- return;
- }
- interceptors_.emplace_back();
- RegisteredInterceptor& interceptor = interceptors_.back();
- interceptor.descriptor = descriptor;
- interceptor.factory = factory;
- interceptor.tls_factory = tls_factory;
- interceptor.packet_callback = packet_callback;
- });
+ task_runner_->PostTask([this, descriptor, factory, tls_factory,
+ packet_callback] {
+ // Ignore repeated registrations.
+ for (const auto& interceptor : interceptors_) {
+ if (interceptor.descriptor.name() == descriptor.name()) {
+ PERFETTO_DCHECK(interceptor.tls_factory == tls_factory);
+ PERFETTO_DCHECK(interceptor.packet_callback == packet_callback);
+ return;
+ }
+ }
+ // Only allow certain interceptors for now.
+ if (descriptor.name() != "test_interceptor" &&
+ descriptor.name() != "console" && descriptor.name() != "etwexport") {
+ PERFETTO_ELOG(
+ "Interceptors are experimental. If you want to use them, please "
+ "get in touch with the project maintainers "
+ "(https://perfetto.dev/docs/contributing/"
+ "getting-started#community).");
+ return;
+ }
+ interceptors_.emplace_back();
+ RegisteredInterceptor& interceptor = interceptors_.back();
+ interceptor.descriptor = descriptor;
+ interceptor.factory = factory;
+ interceptor.tls_factory = tls_factory;
+ interceptor.packet_callback = packet_callback;
+ });
}
void TracingMuxerImpl::ActivateTriggers(
@@ -1629,7 +1629,8 @@
bool TracingMuxerImpl::FlushDataSource_AsyncBegin(
TracingBackendId backend_id,
DataSourceInstanceID instance_id,
- FlushRequestID flush_id) {
+ FlushRequestID flush_id,
+ FlushFlags flush_flags) {
PERFETTO_DLOG("Flushing data source %" PRIu64, instance_id);
auto ds = FindDataSource(backend_id, instance_id);
if (!ds) {
@@ -1640,6 +1641,7 @@
uint32_t backend_connection_id = ds.internal_state->backend_connection_id;
FlushArgsImpl flush_args;
+ flush_args.flush_flags = flush_flags;
flush_args.internal_instance_index = ds.instance_idx;
flush_args.async_flush_closure = [this, backend_id, backend_connection_id,
instance_id, ds, flush_id] {
@@ -1924,7 +1926,11 @@
return;
}
- consumer->service_->Flush(timeout_ms, std::move(callback));
+ // For now we don't want to expose the flush reason to the consumer-side SDK
+ // users to avoid misuses until there is a strong need.
+ consumer->service_->Flush(timeout_ms, std::move(callback),
+ FlushFlags(FlushFlags::Initiator::kConsumerSdk,
+ FlushFlags::Reason::kExplicit));
}
void TracingMuxerImpl::StopTracingSession(TracingSessionGlobalID session_id) {
diff --git a/src/tracing/internal/tracing_muxer_impl.h b/src/tracing/internal/tracing_muxer_impl.h
index 220f96b..ab132f3 100644
--- a/src/tracing/internal/tracing_muxer_impl.h
+++ b/src/tracing/internal/tracing_muxer_impl.h
@@ -228,7 +228,10 @@
void StartDataSource(DataSourceInstanceID,
const DataSourceConfig&) override;
void StopDataSource(DataSourceInstanceID) override;
- void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override;
+ void Flush(FlushRequestID,
+ const DataSourceInstanceID*,
+ size_t,
+ FlushFlags) override;
void ClearIncrementalState(const DataSourceInstanceID*, size_t) override;
bool SweepDeadServices();
@@ -511,7 +514,8 @@
const FindDataSourceRes&);
bool FlushDataSource_AsyncBegin(TracingBackendId,
DataSourceInstanceID,
- FlushRequestID);
+ FlushRequestID,
+ FlushFlags);
void FlushDataSource_AsyncEnd(TracingBackendId,
uint32_t backend_connection_id,
DataSourceInstanceID,
diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
index cf34361..a729d3b 100644
--- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
+++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
@@ -221,7 +221,9 @@
consumer_port_.FreeBuffers(req, std::move(async_response));
}
-void ConsumerIPCClientImpl::Flush(uint32_t timeout_ms, FlushCallback callback) {
+void ConsumerIPCClientImpl::Flush(uint32_t timeout_ms,
+ FlushCallback callback,
+ FlushFlags flush_flags) {
if (!connected_) {
PERFETTO_DLOG("Cannot Flush(), not connected to tracing service");
return callback(/*success=*/false);
@@ -229,6 +231,7 @@
protos::gen::FlushRequest req;
req.set_timeout_ms(static_cast<uint32_t>(timeout_ms));
+ req.set_flags(flush_flags.flags());
ipc::Deferred<protos::gen::FlushResponse> async_response;
async_response.Bind(
[callback](ipc::AsyncResult<protos::gen::FlushResponse> response) {
diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.h b/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
index 71f4968..eba824f 100644
--- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
+++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
@@ -66,7 +66,7 @@
void DisableTracing() override;
void ReadBuffers() override;
void FreeBuffers() override;
- void Flush(uint32_t timeout_ms, FlushCallback) override;
+ void Flush(uint32_t timeout_ms, FlushCallback, FlushFlags) override;
void Detach(const std::string& key) override;
void Attach(const std::string& key) override;
void GetTraceStats() override;
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.cc b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
index 6caf224..ea87953 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.cc
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
@@ -374,10 +374,12 @@
const auto* data_source_ids = cmd.flush().data_source_ids().data();
static_assert(sizeof(data_source_ids[0]) == sizeof(DataSourceInstanceID),
"data_source_ids should be 64-bit");
+
+ FlushFlags flags(cmd.flush().flags());
producer_->Flush(
cmd.flush().request_id(),
reinterpret_cast<const DataSourceInstanceID*>(data_source_ids),
- static_cast<size_t>(cmd.flush().data_source_ids().size()));
+ static_cast<size_t>(cmd.flush().data_source_ids().size()), flags);
return;
}
diff --git a/src/tracing/ipc/service/consumer_ipc_service.cc b/src/tracing/ipc/service/consumer_ipc_service.cc
index ac52864..3e01316 100644
--- a/src/tracing/ipc/service/consumer_ipc_service.cc
+++ b/src/tracing/ipc/service/consumer_ipc_service.cc
@@ -129,8 +129,9 @@
if (weak_this)
weak_this->OnFlushCallback(success, std::move(it));
};
- GetConsumerForCurrentRequest()->service_endpoint->Flush(req.timeout_ms(),
- std::move(callback));
+ FlushFlags flags(req.flags());
+ GetConsumerForCurrentRequest()->service_endpoint->Flush(
+ req.timeout_ms(), std::move(callback), flags);
}
// Called by the IPC layer.
diff --git a/src/tracing/ipc/service/producer_ipc_service.cc b/src/tracing/ipc/service/producer_ipc_service.cc
index d13130a..3208096 100644
--- a/src/tracing/ipc/service/producer_ipc_service.cc
+++ b/src/tracing/ipc/service/producer_ipc_service.cc
@@ -506,7 +506,8 @@
void ProducerIPCService::RemoteProducer::Flush(
FlushRequestID flush_request_id,
const DataSourceInstanceID* data_source_ids,
- size_t num_data_sources) {
+ size_t num_data_sources,
+ FlushFlags flush_flags) {
if (!async_producer_commands.IsBound()) {
PERFETTO_DLOG(
"The Service tried to request a flush but the remote Producer has not "
@@ -518,6 +519,7 @@
for (size_t i = 0; i < num_data_sources; i++)
cmd->mutable_flush()->add_data_source_ids(data_source_ids[i]);
cmd->mutable_flush()->set_request_id(flush_request_id);
+ cmd->mutable_flush()->set_flags(flush_flags.flags());
async_producer_commands.Resolve(std::move(cmd));
}
diff --git a/src/tracing/ipc/service/producer_ipc_service.h b/src/tracing/ipc/service/producer_ipc_service.h
index b42ed73..dffba9d 100644
--- a/src/tracing/ipc/service/producer_ipc_service.h
+++ b/src/tracing/ipc/service/producer_ipc_service.h
@@ -93,7 +93,8 @@
void OnTracingSetup() override;
void Flush(FlushRequestID,
const DataSourceInstanceID* data_source_ids,
- size_t num_data_sources) override;
+ size_t num_data_sources,
+ FlushFlags) override;
void ClearIncrementalState(const DataSourceInstanceID* data_source_ids,
size_t num_data_sources) override;
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index a363089..3ba6aab 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -282,7 +282,7 @@
bool handle_flush_asynchronously = false;
std::function<void()> on_start_callback;
std::function<void()> on_stop_callback;
- std::function<void()> on_flush_callback;
+ std::function<void(perfetto::FlushFlags)> on_flush_callback;
std::function<void()> async_stop_closure;
std::function<void()> async_flush_closure;
};
@@ -949,8 +949,9 @@
EXPECT_NE(handle_, nullptr);
if (handle_->handle_flush_asynchronously)
handle_->async_flush_closure = args.HandleFlushAsynchronously();
- if (handle_->on_flush_callback)
- handle_->on_flush_callback();
+ if (handle_->on_flush_callback) {
+ handle_->on_flush_callback(args.flush_flags);
+ }
handle_->on_flush.Notify();
}
@@ -4224,8 +4225,11 @@
WaitableTestEvent producer_on_flush;
WaitableTestEvent consumer_flush_done;
- data_source->on_flush_callback = [&] {
+ data_source->on_flush_callback = [&](perfetto::FlushFlags flush_flags) {
EXPECT_FALSE(consumer_flush_done.notified());
+ EXPECT_EQ(flush_flags.initiator(),
+ perfetto::FlushFlags::Initiator::kConsumerSdk);
+ EXPECT_EQ(flush_flags.reason(), perfetto::FlushFlags::Reason::kExplicit);
producer_on_flush.Notify();
MockDataSource::Trace([](MockDataSource::TraceContext ctx) {
ctx.NewTracePacket()->set_for_testing()->set_str("on-flush");
@@ -4275,7 +4279,7 @@
WaitableTestEvent consumer_flush_done;
data_source->handle_flush_asynchronously = true;
- data_source->on_flush_callback = [&] {
+ data_source->on_flush_callback = [&](perfetto::FlushFlags) {
EXPECT_FALSE(consumer_flush_done.notified());
};
diff --git a/src/tracing/test/mock_consumer.cc b/src/tracing/test/mock_consumer.cc
index e24ffcc..6601681 100644
--- a/src/tracing/test/mock_consumer.cc
+++ b/src/tracing/test/mock_consumer.cc
@@ -91,15 +91,19 @@
task_runner_->RunUntilCheckpoint(checkpoint_name, timeout_ms);
}
-MockConsumer::FlushRequest MockConsumer::Flush(uint32_t timeout_ms) {
+MockConsumer::FlushRequest MockConsumer::Flush(uint32_t timeout_ms,
+ FlushFlags flush_flags) {
static int i = 0;
auto checkpoint_name = "on_consumer_flush_" + std::to_string(i++);
auto on_flush = task_runner_->CreateCheckpoint(checkpoint_name);
std::shared_ptr<bool> result(new bool());
- service_endpoint_->Flush(timeout_ms, [result, on_flush](bool success) {
- *result = success;
- on_flush();
- });
+ service_endpoint_->Flush(
+ timeout_ms,
+ [result, on_flush](bool success) {
+ *result = success;
+ on_flush();
+ },
+ flush_flags);
base::TestTaskRunner* task_runner = task_runner_;
auto wait_for_flush_completion = [result, task_runner,
diff --git a/src/tracing/test/mock_consumer.h b/src/tracing/test/mock_consumer.h
index 2253d93..b7d8d0a 100644
--- a/src/tracing/test/mock_consumer.h
+++ b/src/tracing/test/mock_consumer.h
@@ -56,7 +56,10 @@
void DisableTracing();
void FreeBuffers();
void WaitForTracingDisabled(uint32_t timeout_ms = 3000);
- FlushRequest Flush(uint32_t timeout_ms = 10000);
+ FlushRequest Flush(
+ uint32_t timeout_ms = 10000,
+ FlushFlags = FlushFlags(FlushFlags::Initiator::kConsumerSdk,
+ FlushFlags::Reason::kExplicit));
std::vector<protos::gen::TracePacket> ReadBuffers();
void GetTraceStats();
TraceStats WaitForTraceStats(bool success);
diff --git a/src/tracing/test/mock_producer.cc b/src/tracing/test/mock_producer.cc
index 84ca4ee..ef40dd6 100644
--- a/src/tracing/test/mock_producer.cc
+++ b/src/tracing/test/mock_producer.cc
@@ -192,23 +192,32 @@
return service_endpoint_->CreateTraceWriter(buf_id);
}
-void MockProducer::ExpectFlush(TraceWriter* writer_to_flush, bool reply) {
+void MockProducer::ExpectFlush(TraceWriter* writer_to_flush,
+ bool reply,
+ FlushFlags expected_flags) {
std::vector<TraceWriter*> writers;
if (writer_to_flush)
writers.push_back(writer_to_flush);
- ExpectFlush(writers, reply);
+ ExpectFlush(writers, reply, expected_flags);
}
void MockProducer::ExpectFlush(std::vector<TraceWriter*> writers_to_flush,
- bool reply) {
- auto& expected_call = EXPECT_CALL(*this, Flush(_, _, _));
- expected_call.WillOnce(Invoke(
- [this, writers_to_flush, reply](FlushRequestID flush_req_id,
- const DataSourceInstanceID*, size_t) {
- for (auto* writer : writers_to_flush)
+ bool reply,
+ FlushFlags expected_flags) {
+ auto& expected_call = EXPECT_CALL(*this, Flush(_, _, _, _));
+ expected_call.WillOnce(
+ Invoke([this, writers_to_flush, reply, expected_flags](
+ FlushRequestID flush_req_id, const DataSourceInstanceID*,
+ size_t, FlushFlags actual_flags) {
+ if (expected_flags.flags()) {
+ EXPECT_EQ(actual_flags, expected_flags);
+ }
+ for (auto* writer : writers_to_flush) {
writer->Flush();
- if (reply)
+ }
+ if (reply) {
service_endpoint_->NotifyFlushComplete(flush_req_id);
+ }
}));
}
diff --git a/src/tracing/test/mock_producer.h b/src/tracing/test/mock_producer.h
index 932bd9c..d259a18 100644
--- a/src/tracing/test/mock_producer.h
+++ b/src/tracing/test/mock_producer.h
@@ -76,10 +76,13 @@
// Expect a flush. Flushes |writer_to_flush| if non-null. If |reply| is true,
// replies to the flush request, otherwise ignores it and doesn't reply.
- void ExpectFlush(TraceWriter* writer_to_flush, bool reply = true);
+ void ExpectFlush(TraceWriter* writer_to_flush,
+ bool reply = true,
+ FlushFlags expected_flags = FlushFlags());
// Same as above, but with a vector of writers.
void ExpectFlush(std::vector<TraceWriter*> writers_to_flush,
- bool reply = true);
+ bool reply = true,
+ FlushFlags expected_flags = FlushFlags());
TracingService::ProducerEndpoint* endpoint() {
return service_endpoint_.get();
@@ -100,7 +103,7 @@
MOCK_METHOD(void, OnTracingSetup, (), (override));
MOCK_METHOD(void,
Flush,
- (FlushRequestID, const DataSourceInstanceID*, size_t),
+ (FlushRequestID, const DataSourceInstanceID*, size_t, FlushFlags),
(override));
MOCK_METHOD(void,
ClearIncrementalState,
diff --git a/src/tracing/test/tracing_integration_test.cc b/src/tracing/test/tracing_integration_test.cc
index 29949a8..3d48453 100644
--- a/src/tracing/test/tracing_integration_test.cc
+++ b/src/tracing/test/tracing_integration_test.cc
@@ -73,7 +73,7 @@
MOCK_METHOD(void, OnTracingSetup, (), (override));
MOCK_METHOD(void,
Flush,
- (FlushRequestID, const DataSourceInstanceID*, size_t),
+ (FlushRequestID, const DataSourceInstanceID*, size_t, FlushFlags),
(override));
MOCK_METHOD(void,
ClearIncrementalState,
@@ -525,13 +525,18 @@
// Ask the service to flush, but don't flush our trace writer. This should
// cause our uncommitted SMB chunk to be scraped.
auto on_flush_complete = task_runner_->CreateCheckpoint("on_flush_complete");
- consumer_endpoint_->Flush(5000, [on_flush_complete](bool success) {
- EXPECT_TRUE(success);
- on_flush_complete();
- });
- EXPECT_CALL(producer_, Flush(_, _, _))
+ FlushFlags flush_flags(FlushFlags::Initiator::kConsumerSdk,
+ FlushFlags::Reason::kExplicit);
+ consumer_endpoint_->Flush(
+ 5000,
+ [on_flush_complete](bool success) {
+ EXPECT_TRUE(success);
+ on_flush_complete();
+ },
+ flush_flags);
+ EXPECT_CALL(producer_, Flush(_, _, _, flush_flags))
.WillOnce(Invoke([this](FlushRequestID flush_req_id,
- const DataSourceInstanceID*, size_t) {
+ const DataSourceInstanceID*, size_t, FlushFlags) {
producer_endpoint_->NotifyFlushComplete(flush_req_id);
}));
task_runner_->RunUntilCheckpoint("on_flush_complete");
diff --git a/test/end_to_end_shared_memory_fuzzer.cc b/test/end_to_end_shared_memory_fuzzer.cc
index adde520..05f1eab 100644
--- a/test/end_to_end_shared_memory_fuzzer.cc
+++ b/test/end_to_end_shared_memory_fuzzer.cc
@@ -96,7 +96,10 @@
void StopDataSource(DataSourceInstanceID) override {}
void OnTracingSetup() override {}
- void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override {}
+ void Flush(FlushRequestID,
+ const DataSourceInstanceID*,
+ size_t,
+ FlushFlags) override {}
void ClearIncrementalState(const DataSourceInstanceID*, size_t) override {}
private:
diff --git a/test/fake_producer.cc b/test/fake_producer.cc
index 90c3932..46308f5 100644
--- a/test/fake_producer.cc
+++ b/test/fake_producer.cc
@@ -160,7 +160,8 @@
void FakeProducer::Flush(FlushRequestID flush_request_id,
const DataSourceInstanceID*,
- size_t num_data_sources) {
+ size_t num_data_sources,
+ FlushFlags) {
PERFETTO_DCHECK(num_data_sources > 0);
if (trace_writer_)
trace_writer_->Flush();
diff --git a/test/fake_producer.h b/test/fake_producer.h
index 5922165..0b16590 100644
--- a/test/fake_producer.h
+++ b/test/fake_producer.h
@@ -79,7 +79,10 @@
const DataSourceConfig& source_config) override;
void StopDataSource(DataSourceInstanceID) override;
void OnTracingSetup() override;
- void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override;
+ void Flush(FlushRequestID,
+ const DataSourceInstanceID*,
+ size_t,
+ FlushFlags) override;
void ClearIncrementalState(const DataSourceInstanceID* /*data_source_ids*/,
size_t /*num_data_sources*/) override {}
diff --git a/test/test_helper.cc b/test/test_helper.cc
index 6054f3f..f991837 100644
--- a/test/test_helper.cc
+++ b/test/test_helper.cc
@@ -209,11 +209,12 @@
endpoint_->DisableTracing();
}
-void TestHelper::FlushAndWait(uint32_t timeout_ms) {
+void TestHelper::FlushAndWait(uint32_t timeout_ms, FlushFlags flush_flags) {
static int flush_num = 0;
std::string checkpoint_name = "flush." + std::to_string(flush_num++);
auto checkpoint = CreateCheckpoint(checkpoint_name);
- endpoint_->Flush(timeout_ms, [checkpoint](bool) { checkpoint(); });
+ endpoint_->Flush(
+ timeout_ms, [checkpoint](bool) { checkpoint(); }, flush_flags);
RunUntilCheckpoint(checkpoint_name, timeout_ms + 1000);
}
diff --git a/test/test_helper.h b/test/test_helper.h
index ba00422..91b955d 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -314,7 +314,7 @@
void StartTracing(const TraceConfig& config,
base::ScopedFile = base::ScopedFile());
void DisableTracing();
- void FlushAndWait(uint32_t timeout_ms);
+ void FlushAndWait(uint32_t timeout_ms, FlushFlags = FlushFlags());
void ReadData(uint32_t read_count = 0);
void FreeBuffers();
void DetachConsumer(const std::string& key);