#include "src/tracing/service/tracing_service_impl.h"
#include <limits.h>
#include <string.h>
#include <cinttypes>
#include <cstdint>
#include <limits>
#include <optional>
#include <regex>
#include <string>
#include <unordered_set>
#include "perfetto/base/time.h"
#include "perfetto/ext/tracing/core/client_identity.h"
#include "perfetto/tracing/core/clock_snapshots.h"
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
!PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
#include <sys/uio.h>
#include <sys/utsname.h>
#include <unistd.h>
#endif
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
#include "src/android_internal/lazy_library_loader.h"
#include "src/android_internal/tracing_service_proxy.h"
#endif
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
#define PERFETTO_HAS_CHMOD
#include <sys/stat.h>
#endif
#include <algorithm>
#include "perfetto/base/build_config.h"
#include "perfetto/base/status.h"
#include "perfetto/base/task_runner.h"
#include "perfetto/ext/base/android_utils.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/metatrace.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/sys_types.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/base/uuid.h"
#include "perfetto/ext/base/version.h"
#include "perfetto/ext/base/watchdog.h"
#include "perfetto/ext/tracing/core/basic_types.h"
#include "perfetto/ext/tracing/core/consumer.h"
#include "perfetto/ext/tracing/core/observable_events.h"
#include "perfetto/ext/tracing/core/producer.h"
#include "perfetto/ext/tracing/core/shared_memory.h"
#include "perfetto/ext/tracing/core/shared_memory_abi.h"
#include "perfetto/ext/tracing/core/trace_packet.h"
#include "perfetto/ext/tracing/core/trace_writer.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
#include "perfetto/protozero/static_buffer.h"
#include "perfetto/tracing/core/data_source_descriptor.h"
#include "perfetto/tracing/core/tracing_service_capabilities.h"
#include "perfetto/tracing/core/tracing_service_state.h"
#include "src/android_stats/statsd_logging_helper.h"
#include "src/protozero/filtering/message_filter.h"
#include "src/protozero/filtering/string_filter.h"
#include "src/tracing/core/shared_memory_arbiter_impl.h"
#include "src/tracing/service/packet_stream_validator.h"
#include "src/tracing/service/trace_buffer.h"
#include "protos/perfetto/common/builtin_clock.gen.h"
#include "protos/perfetto/common/builtin_clock.pbzero.h"
#include "protos/perfetto/common/trace_stats.pbzero.h"
#include "protos/perfetto/config/trace_config.pbzero.h"
#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
#include "protos/perfetto/trace/perfetto/tracing_service_event.pbzero.h"
#include "protos/perfetto/trace/remote_clock_sync.pbzero.h"
#include "protos/perfetto/trace/system_info.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
#include "protos/perfetto/trace/trace_uuid.pbzero.h"
#include "protos/perfetto/trace/trigger.pbzero.h"
#define PERFETTO_SVC_ERR(...) …
namespace perfetto {
namespace {
constexpr int kMaxBuffersPerConsumer = …;
constexpr uint32_t kDefaultSnapshotsIntervalMs = …;
constexpr int kDefaultWriteIntoFilePeriodMs = …;
constexpr int kMaxConcurrentTracingSessions = …;
constexpr int kMaxConcurrentTracingSessionsPerUid = …;
constexpr int kMaxConcurrentTracingSessionsForStatsdUid = …;
constexpr int64_t kMinSecondsBetweenTracesGuardrail = …;
constexpr uint32_t kMillisPerHour = …;
constexpr uint32_t kMillisPerDay = …;
constexpr uint32_t kMaxTracingDurationMillis = …;
constexpr uint32_t kGuardrailsMaxTracingBufferSizeKb = …;
constexpr uint32_t kGuardrailsMaxTracingDurationMillis = …;
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
struct iovec {
void* iov_base;
size_t iov_len;
};
ssize_t writev(int fd, const struct iovec* iov, int iovcnt) {
ssize_t total_size = 0;
for (int i = 0; i < iovcnt; ++i) {
ssize_t current_size = base::WriteAll(fd, iov[i].iov_base, iov[i].iov_len);
if (current_size != static_cast<ssize_t>(iov[i].iov_len))
return -1;
total_size += current_size;
}
return total_size;
}
#define IOV_MAX …
#endif
int32_t EncodeCommitDataRequest(ProducerID producer_id,
const CommitDataRequest& req_untrusted) { … }
void SerializeAndAppendPacket(std::vector<TracePacket>* packets,
std::vector<uint8_t> packet) { … }
std::tuple<size_t , size_t > EnsureValidShmSizes(
size_t shm_size,
size_t page_size) { … }
bool NameMatchesFilter(const std::string& name,
const std::vector<std::string>& name_filter,
const std::vector<std::string>& name_regex_filter) { … }
base::ScopedFile CreateTraceFile(const std::string& path, bool overwrite) { … }
bool ShouldLogEvent(const TraceConfig& cfg) { … }
void AppendOwnedSlicesToPacket(std::unique_ptr<uint8_t[]> data,
size_t size,
size_t max_slice_size,
perfetto::TracePacket* packet) { … }
TraceFilter;
std::optional<protozero::StringFilter::Policy> ConvertPolicy(
TraceFilter::StringFilterPolicy policy) { … }
}
std::unique_ptr<TracingService> TracingService::CreateInstance(
std::unique_ptr<SharedMemory::Factory> shm_factory,
base::TaskRunner* task_runner,
InitOpts init_opts) { … }
TracingServiceImpl::TracingServiceImpl(
std::unique_ptr<SharedMemory::Factory> shm_factory,
base::TaskRunner* task_runner,
InitOpts init_opts)
: … { … }
TracingServiceImpl::~TracingServiceImpl() { … }
std::unique_ptr<TracingService::ProducerEndpoint>
TracingServiceImpl::ConnectProducer(Producer* producer,
const ClientIdentity& client_identity,
const std::string& producer_name,
size_t shared_memory_size_hint_bytes,
bool in_process,
ProducerSMBScrapingMode smb_scraping_mode,
size_t shared_memory_page_size_hint_bytes,
std::unique_ptr<SharedMemory> shm,
const std::string& sdk_version) { … }
void TracingServiceImpl::DisconnectProducer(ProducerID id) { … }
TracingServiceImpl::ProducerEndpointImpl* TracingServiceImpl::GetProducer(
ProducerID id) const { … }
std::unique_ptr<TracingService::ConsumerEndpoint>
TracingServiceImpl::ConnectConsumer(Consumer* consumer, uid_t uid) { … }
void TracingServiceImpl::DisconnectConsumer(ConsumerEndpointImpl* consumer) { … }
bool TracingServiceImpl::DetachConsumer(ConsumerEndpointImpl* consumer,
const std::string& key) { … }
std::unique_ptr<TracingService::RelayEndpoint>
TracingServiceImpl::ConnectRelayClient(RelayClientID relay_client_id) { … }
void TracingServiceImpl::DisconnectRelayClient(RelayClientID relay_client_id) { … }
bool TracingServiceImpl::AttachConsumer(ConsumerEndpointImpl* consumer,
const std::string& key) { … }
base::Status TracingServiceImpl::EnableTracing(ConsumerEndpointImpl* consumer,
const TraceConfig& cfg,
base::ScopedFile fd) { … }
void TracingServiceImpl::ChangeTraceConfig(ConsumerEndpointImpl* consumer,
const TraceConfig& updated_cfg) { … }
void TracingServiceImpl::StartTracing(TracingSessionID tsid) { … }
void TracingServiceImpl::StopOnDurationMsExpiry(
base::WeakPtr<TracingServiceImpl> weak_this,
TracingSessionID tsid) { … }
void TracingServiceImpl::StartDataSourceInstance(
ProducerEndpointImpl* producer,
TracingSession* tracing_session,
TracingServiceImpl::DataSourceInstance* instance) { … }
void TracingServiceImpl::DisableTracing(TracingSessionID tsid,
bool disable_immediately) { … }
void TracingServiceImpl::NotifyDataSourceStarted(
ProducerID producer_id,
DataSourceInstanceID instance_id) { … }
void TracingServiceImpl::MaybeNotifyAllDataSourcesStarted(
TracingSession* tracing_session) { … }
void TracingServiceImpl::NotifyDataSourceStopped(
ProducerID producer_id,
DataSourceInstanceID instance_id) { … }
void TracingServiceImpl::ActivateTriggers(
ProducerID producer_id,
const std::vector<std::string>& triggers) { … }
void TracingServiceImpl::OnDisableTracingTimeout(TracingSessionID tsid) { … }
void TracingServiceImpl::DisableTracingNotifyConsumerAndFlushFile(
TracingSession* tracing_session) { … }
void TracingServiceImpl::Flush(TracingSessionID tsid,
uint32_t timeout_ms,
ConsumerEndpoint::FlushCallback callback,
FlushFlags flush_flags) { … }
void TracingServiceImpl::FlushDataSourceInstances(
TracingSession* tracing_session,
uint32_t timeout_ms,
const std::map<ProducerID, std::vector<DataSourceInstanceID>>&
data_source_instances,
ConsumerEndpoint::FlushCallback callback,
FlushFlags flush_flags) { … }
void TracingServiceImpl::NotifyFlushDoneForProducer(
ProducerID producer_id,
FlushRequestID flush_request_id) { … }
void TracingServiceImpl::OnFlushTimeout(TracingSessionID tsid,
FlushRequestID flush_request_id) { … }
void TracingServiceImpl::CompleteFlush(TracingSessionID tsid,
ConsumerEndpoint::FlushCallback callback,
bool success) { … }
void TracingServiceImpl::ScrapeSharedMemoryBuffers(
TracingSession* tracing_session,
ProducerEndpointImpl* producer) { … }
void TracingServiceImpl::FlushAndDisableTracing(TracingSessionID tsid) { … }
void TracingServiceImpl::PeriodicFlushTask(TracingSessionID tsid,
bool post_next_only) { … }
void TracingServiceImpl::PeriodicClearIncrementalStateTask(
TracingSessionID tsid,
bool post_next_only) { … }
bool TracingServiceImpl::ReadBuffersIntoConsumer(
TracingSessionID tsid,
ConsumerEndpointImpl* consumer) { … }
bool TracingServiceImpl::ReadBuffersIntoFile(TracingSessionID tsid) { … }
bool TracingServiceImpl::IsWaitingForTrigger(TracingSession* tracing_session) { … }
std::vector<TracePacket> TracingServiceImpl::ReadBuffers(
TracingSession* tracing_session,
size_t threshold,
bool* has_more) { … }
void TracingServiceImpl::MaybeFilterPackets(TracingSession* tracing_session,
std::vector<TracePacket>* packets) { … }
void TracingServiceImpl::MaybeCompressPackets(
TracingSession* tracing_session,
std::vector<TracePacket>* packets) { … }
bool TracingServiceImpl::WriteIntoFile(TracingSession* tracing_session,
std::vector<TracePacket> packets) { … }
void TracingServiceImpl::FreeBuffers(TracingSessionID tsid) { … }
void TracingServiceImpl::RegisterDataSource(ProducerID producer_id,
const DataSourceDescriptor& desc) { … }
void TracingServiceImpl::UpdateDataSource(
ProducerID producer_id,
const DataSourceDescriptor& new_desc) { … }
void TracingServiceImpl::StopDataSourceInstance(ProducerEndpointImpl* producer,
TracingSession* tracing_session,
DataSourceInstance* instance,
bool disable_immediately) { … }
void TracingServiceImpl::UnregisterDataSource(ProducerID producer_id,
const std::string& name) { … }
bool TracingServiceImpl::IsInitiatorPrivileged(
const TracingSession& tracing_session) { … }
TracingServiceImpl::DataSourceInstance* TracingServiceImpl::SetupDataSource(
const TraceConfig::DataSource& cfg_data_source,
const TraceConfig::ProducerConfig& producer_config,
const RegisteredDataSource& data_source,
TracingSession* tracing_session) { … }
void TracingServiceImpl::CopyProducerPageIntoLogBuffer(
ProducerID producer_id_trusted,
const ClientIdentity& client_identity_trusted,
WriterID writer_id,
ChunkID chunk_id,
BufferID buffer_id,
uint16_t num_fragments,
uint8_t chunk_flags,
bool chunk_complete,
const uint8_t* src,
size_t size) { … }
void TracingServiceImpl::ApplyChunkPatches(
ProducerID producer_id_trusted,
const std::vector<CommitDataRequest::ChunkToPatch>& chunks_to_patch) { … }
TracingServiceImpl::TracingSession* TracingServiceImpl::GetDetachedSession(
uid_t uid,
const std::string& key) { … }
TracingServiceImpl::TracingSession* TracingServiceImpl::GetTracingSession(
TracingSessionID tsid) { … }
TracingServiceImpl::TracingSession*
TracingServiceImpl::FindTracingSessionWithMaxBugreportScore() { … }
ProducerID TracingServiceImpl::GetNextProducerID() { … }
TraceBuffer* TracingServiceImpl::GetBufferByID(BufferID buffer_id) { … }
void TracingServiceImpl::OnStartTriggersTimeout(TracingSessionID tsid) { … }
void TracingServiceImpl::UpdateMemoryGuardrail() { … }
void TracingServiceImpl::PeriodicSnapshotTask(TracingSessionID tsid) { … }
void TracingServiceImpl::SnapshotLifecyleEvent(TracingSession* tracing_session,
uint32_t field_id,
bool snapshot_clocks) { … }
void TracingServiceImpl::MaybeSnapshotClocksIntoRingBuffer(
TracingSession* tracing_session) { … }
bool TracingServiceImpl::SnapshotClocks(
TracingSession::ClockSnapshotData* snapshot_data) { … }
void TracingServiceImpl::EmitClockSnapshot(
TracingSession* tracing_session,
TracingSession::ClockSnapshotData snapshot_data,
std::vector<TracePacket>* packets) { … }
void TracingServiceImpl::EmitSyncMarker(std::vector<TracePacket>* packets) { … }
void TracingServiceImpl::EmitStats(TracingSession* tracing_session,
std::vector<TracePacket>* packets) { … }
TraceStats TracingServiceImpl::GetTraceStats(TracingSession* tracing_session) { … }
void TracingServiceImpl::EmitUuid(TracingSession* tracing_session,
std::vector<TracePacket>* packets) { … }
void TracingServiceImpl::MaybeEmitTraceConfig(
TracingSession* tracing_session,
std::vector<TracePacket>* packets) { … }
void TracingServiceImpl::EmitSystemInfo(std::vector<TracePacket>* packets) { … }
void TracingServiceImpl::EmitLifecycleEvents(
TracingSession* tracing_session,
std::vector<TracePacket>* packets) { … }
void TracingServiceImpl::MaybeEmitRemoteClockSync(
TracingSession* tracing_session,
std::vector<TracePacket>* packets) { … }
void TracingServiceImpl::MaybeEmitReceivedTriggers(
TracingSession* tracing_session,
std::vector<TracePacket>* packets) { … }
void TracingServiceImpl::MaybeLogUploadEvent(const TraceConfig& cfg,
const base::Uuid& uuid,
PerfettoStatsdAtom atom,
const std::string& trigger_name) { … }
void TracingServiceImpl::MaybeLogTriggerEvent(const TraceConfig& cfg,
PerfettoTriggerAtom atom,
const std::string& trigger_name) { … }
size_t TracingServiceImpl::PurgeExpiredAndCountTriggerInWindow(
int64_t now_ns,
uint64_t trigger_name_hash) { … }
base::Status TracingServiceImpl::FlushAndCloneSession(
ConsumerEndpointImpl* consumer,
TracingSessionID tsid,
bool skip_trace_filter,
bool for_bugreport) { … }
std::map<ProducerID, std::vector<DataSourceInstanceID>>
TracingServiceImpl::GetFlushableDataSourceInstancesForBuffers(
TracingSession* session,
const std::set<BufferID>& bufs) { … }
void TracingServiceImpl::OnFlushDoneForClone(TracingSessionID tsid,
PendingCloneID clone_id,
const std::set<BufferID>& buf_ids,
bool final_flush_outcome) { … }
bool TracingServiceImpl::DoCloneBuffers(
TracingSession* src,
const std::set<BufferID>& buf_ids,
std::vector<std::unique_ptr<TraceBuffer>>* buf_snaps) { … }
base::Status TracingServiceImpl::FinishCloneSession(
ConsumerEndpointImpl* consumer,
TracingSessionID src_tsid,
std::vector<std::unique_ptr<TraceBuffer>> buf_snaps,
bool skip_trace_filter,
bool final_flush_outcome,
base::Uuid* new_uuid) { … }
bool TracingServiceImpl::TracingSession::IsCloneAllowed(uid_t clone_uid) const { … }
TracingServiceImpl::ConsumerEndpointImpl::ConsumerEndpointImpl(
TracingServiceImpl* service,
base::TaskRunner* task_runner,
Consumer* consumer,
uid_t uid)
: … { … }
TracingServiceImpl::ConsumerEndpointImpl::~ConsumerEndpointImpl() { … }
void TracingServiceImpl::ConsumerEndpointImpl::NotifyOnTracingDisabled(
const std::string& error) { … }
void TracingServiceImpl::ConsumerEndpointImpl::EnableTracing(
const TraceConfig& cfg,
base::ScopedFile fd) { … }
void TracingServiceImpl::ConsumerEndpointImpl::ChangeTraceConfig(
const TraceConfig& cfg) { … }
void TracingServiceImpl::ConsumerEndpointImpl::StartTracing() { … }
void TracingServiceImpl::ConsumerEndpointImpl::DisableTracing() { … }
void TracingServiceImpl::ConsumerEndpointImpl::ReadBuffers() { … }
void TracingServiceImpl::ConsumerEndpointImpl::FreeBuffers() { … }
void TracingServiceImpl::ConsumerEndpointImpl::Flush(uint32_t timeout_ms,
FlushCallback callback,
FlushFlags flush_flags) { … }
void TracingServiceImpl::ConsumerEndpointImpl::Detach(const std::string& key) { … }
void TracingServiceImpl::ConsumerEndpointImpl::Attach(const std::string& key) { … }
void TracingServiceImpl::ConsumerEndpointImpl::GetTraceStats() { … }
void TracingServiceImpl::ConsumerEndpointImpl::ObserveEvents(
uint32_t events_mask) { … }
void TracingServiceImpl::ConsumerEndpointImpl::OnDataSourceInstanceStateChange(
const ProducerEndpointImpl& producer,
const DataSourceInstance& instance) { … }
void TracingServiceImpl::ConsumerEndpointImpl::OnAllDataSourcesStarted() { … }
void TracingServiceImpl::ConsumerEndpointImpl::NotifyCloneSnapshotTrigger(
const std::string& trigger_name) { … }
ObservableEvents*
TracingServiceImpl::ConsumerEndpointImpl::AddObservableEvents() { … }
void TracingServiceImpl::ConsumerEndpointImpl::QueryServiceState(
QueryServiceStateArgs args,
QueryServiceStateCallback callback) { … }
void TracingServiceImpl::ConsumerEndpointImpl::QueryCapabilities(
QueryCapabilitiesCallback callback) { … }
void TracingServiceImpl::ConsumerEndpointImpl::SaveTraceForBugreport(
SaveTraceForBugreportCallback consumer_callback) { … }
void TracingServiceImpl::ConsumerEndpointImpl::CloneSession(
TracingSessionID tsid,
CloneSessionArgs args) { … }
TracingServiceImpl::ProducerEndpointImpl::ProducerEndpointImpl(
ProducerID id,
const ClientIdentity& client_identity,
TracingServiceImpl* service,
base::TaskRunner* task_runner,
Producer* producer,
const std::string& producer_name,
const std::string& sdk_version,
bool in_process,
bool smb_scraping_enabled)
: … { … }
TracingServiceImpl::ProducerEndpointImpl::~ProducerEndpointImpl() { … }
void TracingServiceImpl::ProducerEndpointImpl::Disconnect() { … }
void TracingServiceImpl::ProducerEndpointImpl::RegisterDataSource(
const DataSourceDescriptor& desc) { … }
void TracingServiceImpl::ProducerEndpointImpl::UpdateDataSource(
const DataSourceDescriptor& desc) { … }
void TracingServiceImpl::ProducerEndpointImpl::UnregisterDataSource(
const std::string& name) { … }
void TracingServiceImpl::ProducerEndpointImpl::RegisterTraceWriter(
uint32_t writer_id,
uint32_t target_buffer) { … }
void TracingServiceImpl::ProducerEndpointImpl::UnregisterTraceWriter(
uint32_t writer_id) { … }
void TracingServiceImpl::ProducerEndpointImpl::CommitData(
const CommitDataRequest& req_untrusted,
CommitDataCallback callback) { … }
void TracingServiceImpl::ProducerEndpointImpl::SetupSharedMemory(
std::unique_ptr<SharedMemory> shared_memory,
size_t page_size_bytes,
bool provided_by_producer) { … }
SharedMemory* TracingServiceImpl::ProducerEndpointImpl::shared_memory() const { … }
size_t TracingServiceImpl::ProducerEndpointImpl::shared_buffer_page_size_kb()
const { … }
void TracingServiceImpl::ProducerEndpointImpl::ActivateTriggers(
const std::vector<std::string>& triggers) { … }
void TracingServiceImpl::ProducerEndpointImpl::StopDataSource(
DataSourceInstanceID ds_inst_id) { … }
SharedMemoryArbiter*
TracingServiceImpl::ProducerEndpointImpl::MaybeSharedMemoryArbiter() { … }
bool TracingServiceImpl::ProducerEndpointImpl::IsShmemProvidedByProducer()
const { … }
std::unique_ptr<TraceWriter>
TracingServiceImpl::ProducerEndpointImpl::CreateTraceWriter(
BufferID buf_id,
BufferExhaustedPolicy buffer_exhausted_policy) { … }
void TracingServiceImpl::ProducerEndpointImpl::NotifyFlushComplete(
FlushRequestID id) { … }
void TracingServiceImpl::ProducerEndpointImpl::OnTracingSetup() { … }
void TracingServiceImpl::ProducerEndpointImpl::Flush(
FlushRequestID flush_request_id,
const std::vector<DataSourceInstanceID>& data_sources,
FlushFlags flush_flags) { … }
void TracingServiceImpl::ProducerEndpointImpl::SetupDataSource(
DataSourceInstanceID ds_id,
const DataSourceConfig& config) { … }
void TracingServiceImpl::ProducerEndpointImpl::StartDataSource(
DataSourceInstanceID ds_id,
const DataSourceConfig& config) { … }
void TracingServiceImpl::ProducerEndpointImpl::NotifyDataSourceStarted(
DataSourceInstanceID data_source_id) { … }
void TracingServiceImpl::ProducerEndpointImpl::NotifyDataSourceStopped(
DataSourceInstanceID data_source_id) { … }
void TracingServiceImpl::ProducerEndpointImpl::OnFreeBuffers(
const std::vector<BufferID>& target_buffers) { … }
void TracingServiceImpl::ProducerEndpointImpl::ClearIncrementalState(
const std::vector<DataSourceInstanceID>& data_sources) { … }
void TracingServiceImpl::ProducerEndpointImpl::Sync(
std::function<void()> callback) { … }
TracingServiceImpl::TracingSession::TracingSession(
TracingSessionID session_id,
ConsumerEndpointImpl* consumer,
const TraceConfig& new_config,
base::TaskRunner* task_runner)
: … { … }
TracingServiceImpl::RelayEndpointImpl::RelayEndpointImpl(
RelayClientID relay_client_id,
TracingServiceImpl* service)
: … { … }
TracingServiceImpl::RelayEndpointImpl::~RelayEndpointImpl() = default;
void TracingServiceImpl::RelayEndpointImpl::SyncClocks(
SyncMode sync_mode,
ClockSnapshotVector client_clocks,
ClockSnapshotVector host_clocks) { … }
void TracingServiceImpl::RelayEndpointImpl::Disconnect() { … }
}