blob: 4497ad205590aa77ccf07e654f66d947f4345755 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PRODUCER_H_
#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PRODUCER_H_
#include <memory>
#include "base/component_export.h"
#include "base/memory/raw_ptr.h"
#include "build/build_config.h"
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/basic_types.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/tracing_service.h"
namespace perfetto {
class SharedMemoryArbiter;
} // namespace perfetto
namespace tracing {
// This class represents the perfetto producer endpoint which is used for
// producers to talk to the Perfetto service. It also provides methods to
// interact with the shared memory buffer by binding and creating TraceWriters.
//
// In addition to the PerfettoProducers' pure virtual methods, subclasses must
// implement the remaining methods of the ProducerEndpoint interface.
class COMPONENT_EXPORT(TRACING_CPP) PerfettoProducer {
public:
explicit PerfettoProducer(base::tracing::PerfettoTaskRunner*);
virtual ~PerfettoProducer();
// Setup the shared memory buffer and data sources for startup tracing.
// Returns false on failure. Can be called on any thread.
bool SetupStartupTracing(const base::trace_event::TraceConfig&,
bool privacy_filtering_enabled);
// Schedules the startup tracing timeout if active.
void OnThreadPoolAvailable();
// See SharedMemoryArbiter::CreateStartupTraceWriter.
std::unique_ptr<perfetto::TraceWriter> CreateStartupTraceWriter(
uint16_t target_buffer_reservation_id);
// See SharedMemoryArbiter::BindStartupTargetBuffer. Should be called on the
// producer's task runner.
virtual void BindStartupTargetBuffer(
uint16_t target_buffer_reservation_id,
perfetto::BufferID startup_target_buffer);
// See SharedMemoryArbiter::AbortStartupTracingForReservation. Should be
// called on the producer's task runner.
virtual void AbortStartupTracingForReservation(
uint16_t target_buffer_reservation_id);
// Used by the DataSource implementations to create TraceWriters
// for writing their protobufs, and respond to flushes.
//
// Should only be called while a tracing session is active and a
// SharedMemoryArbiter exists.
//
// Virtual for testing.
virtual std::unique_ptr<perfetto::TraceWriter> CreateTraceWriter(
perfetto::BufferID target_buffer,
perfetto::BufferExhaustedPolicy =
perfetto::BufferExhaustedPolicy::kDefault);
// Returns the SharedMemoryArbiter if available.
// TODO(eseckler): Once startup tracing v2 is available in Chrome, this could
// become GetSharedMemoryArbiter() instead.
virtual perfetto::SharedMemoryArbiter* MaybeSharedMemoryArbiter() = 0;
// Informs the PerfettoProducer a new Data Source was added. This instance
// will also be found in |data_sources| having just be inserted before this
// method is called by PerfettoTracedProcess. This enables the
// PerfettoProducer to perform initialization on new data sources.
virtual void NewDataSourceAdded(
const PerfettoTracedProcess::DataSourceBase* const data_source) = 0;
// Returns true if this PerfettoProducer is currently tracing.
virtual bool IsTracingActive() = 0;
static void DeleteSoonForTesting(
std::unique_ptr<PerfettoProducer> perfetto_producer);
// In tests, PerfettoProducers may leak between tests, but their task sequence
// may become invalid (e.g. TaskEnvironment is destroyed). This resets the
// PerfettoProducer's sequence checker, so that it can later be rebound to a
// new test's sequence. Note that this only resets the producer's sequence
// checker - and there may be other sequence checkers elsewhere, e.g. in
// PosixSystemProducer's socket (which would fail on disconnect if the system
// producer's sequence is reset while it is connected).
void ResetSequenceForTesting();
void set_startup_tracing_timeout_for_testing(base::TimeDelta timeout) {
startup_tracing_timeout_ = timeout;
}
protected:
friend class MockProducerHost;
// May be called on any thread.
virtual bool SetupSharedMemoryForStartupTracing() = 0;
// The PerfettoProducer subclass should call this once the startup tracing
// session was taken over by the tracing service.
// TODO(eseckler): Consider refactoring this into e.g. a delegate interface.
void OnStartupTracingComplete();
bool IsStartupTracingActive();
// TODO(crbug.com/839071): Find a good compromise between performance and
// data granularity (mainly relevant to running with small buffer sizes
// when we use background tracing) on Android.
#if defined(OS_ANDROID)
static constexpr size_t kSMBPageSizeBytes = 4 * 1024;
#else
static constexpr size_t kSMBPageSizeBytes = 32 * 1024;
#endif
// TODO(crbug.com/839071): Figure out a good buffer size.
static constexpr size_t kDefaultSMBSizeBytes = 4 * 1024 * 1024;
// TODO(lri): replace this constant with its version in the client library,
// when we move over.
//
// This value for SharedMemoryArbiter's batch_commits_duration_ms was
// determined by load testing, using the script at
// https://chromium-review.googlesource.com/c/chromium/src/+/1835498. The
// effects of various delays on the overhead of tracing in Chrome
// can be seen at https://screenshot.googleplex.com/KgsJshNCFKq. See commit
// 2fc0474d9 and crbug.com/1029298 for more context.
//
// Note that since this value is non-zero, it could lead to loss of batched
// data at the end of a tracing session. The producer should enable
// asynchronous stopping of datasources and should flush the accumulated
// commits while a datasource is being stopped.
static constexpr uint32_t kShmArbiterBatchCommitDurationMs = 1000;
base::tracing::PerfettoTaskRunner* task_runner();
size_t GetPreferredSmbSizeBytes();
SEQUENCE_CHECKER(sequence_checker_);
private:
void MaybeScheduleStartupTracingTimeout();
void OnStartupTracingTimeout();
// If a startup tracing session is not taken over by the service after this
// delay, the startup session will be aborted and its data lost. This is to
// catch situations where e.g. a subprocess is spawned with startup tracing
// flags, but the tracing session got disabled in the service while it was
// initializing (in which case, the tracing service will not tell the
// subprocess to start tracing after it connects).
base::TimeDelta startup_tracing_timeout_ = base::Seconds(60);
const raw_ptr<base::tracing::PerfettoTaskRunner> task_runner_;
std::atomic<bool> startup_tracing_active_{false};
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<PerfettoProducer> weak_ptr_factory_{this};
};
} // namespace tracing
#endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PRODUCER_H_