blob: 929ecc7afb8755cbd018f773cc5254e10e43bc6a [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_TRACING_PERFETTO_CONSUMER_HOST_H_
#define SERVICES_TRACING_PERFETTO_CONSUMER_HOST_H_
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process_handle.h"
#include "base/sequence_checker.h"
#include "base/threading/sequence_bound.h"
#include "base/timer/timer.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/tracing/public/mojom/perfetto_service.mojom.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/consumer.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/tracing_service.h"
namespace perfetto {
namespace trace_processor {
class TraceProcessorStorage;
} // namespace trace_processor
} // namespace perfetto
namespace tracing {
class PerfettoService;
// This is a Mojo interface which enables any client
// to act as a Perfetto consumer.
class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost {
public:
static void BindConsumerReceiver(
PerfettoService* service,
mojo::PendingReceiver<mojom::ConsumerHost> receiver);
class StreamWriter;
class TracingSession : public mojom::TracingSessionHost {
public:
TracingSession(
ConsumerHost* host,
mojo::PendingReceiver<mojom::TracingSessionHost> tracing_session_host,
mojo::PendingRemote<mojom::TracingSessionClient> tracing_session_client,
const perfetto::TraceConfig& trace_config,
perfetto::base::ScopedFile output_file,
mojom::TracingClientPriority priority);
TracingSession(const TracingSession&) = delete;
TracingSession& operator=(const TracingSession&) = delete;
~TracingSession() override;
void OnPerfettoEvents(const perfetto::ObservableEvents&);
void OnTraceData(std::vector<perfetto::TracePacket> packets, bool has_more);
void OnTraceStats(bool success, const perfetto::TraceStats&);
void OnTracingDisabled(const std::string& error);
void OnConsumerClientDisconnected();
void Flush(uint32_t timeout, base::OnceCallback<void(bool)> callback);
mojom::TracingClientPriority tracing_priority() const {
return tracing_priority_;
}
bool tracing_enabled() const { return tracing_enabled_; }
ConsumerHost* host() const { return host_; }
// Called by TracingService.
void OnActiveServicePidAdded(base::ProcessId pid);
void OnActiveServicePidRemoved(base::ProcessId pid);
void OnActiveServicePidsInitialized();
void RequestDisableTracing(base::OnceClosure on_disabled_callback);
// mojom::TracingSessionHost implementation.
void ChangeTraceConfig(const perfetto::TraceConfig& config) override;
void DisableTracing() override;
void ReadBuffers(mojo::ScopedDataPipeProducerHandle stream,
ReadBuffersCallback callback) override;
void RequestBufferUsage(RequestBufferUsageCallback callback) override;
void DisableTracingAndEmitJson(
const std::string& agent_label_filter,
mojo::ScopedDataPipeProducerHandle stream,
bool privacy_filtering_enabled,
DisableTracingAndEmitJsonCallback callback) override;
private:
void ExportJson();
void OnJSONTraceData(std::string json, bool has_more);
void OnEnableTracingTimeout();
void MaybeSendEnableTracingAck();
bool IsExpectedPid(base::ProcessId pid) const;
const raw_ptr<ConsumerHost> host_;
mojo::Remote<mojom::TracingSessionClient> tracing_session_client_;
mojo::Receiver<mojom::TracingSessionHost> receiver_;
bool privacy_filtering_enabled_ = false;
bool convert_to_legacy_json_ = false;
base::SequenceBound<StreamWriter> read_buffers_stream_writer_;
RequestBufferUsageCallback request_buffer_usage_callback_;
std::unique_ptr<perfetto::trace_processor::TraceProcessorStorage>
trace_processor_;
std::string json_agent_label_filter_;
base::OnceCallback<void(bool)> flush_callback_;
const mojom::TracingClientPriority tracing_priority_;
base::OnceClosure on_disabled_callback_;
std::set<base::ProcessId> filtered_pids_;
bool tracing_enabled_ = true;
// If set, we didn't issue OnTracingEnabled() on the session yet. If set and
// empty, no more pids are pending and we should issue OnTracingEnabled().
std::optional<std::set<base::ProcessId>> pending_enable_tracing_ack_pids_;
base::OneShotTimer enable_tracing_ack_timer_;
struct DataSourceHandle : public std::pair<std::string, std::string> {
using std::pair<std::string, std::string>::pair;
const std::string& producer_name() const { return first; }
const std::string& data_source_name() const { return second; }
};
std::map<DataSourceHandle, bool /*started*/> data_source_states_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<TracingSession> weak_factory_{this};
};
// The owner of ConsumerHost should make sure to destroy
// |service| after destroying this.
explicit ConsumerHost(PerfettoService* service);
ConsumerHost(const ConsumerHost&) = delete;
ConsumerHost& operator=(const ConsumerHost&) = delete;
~ConsumerHost() override;
PerfettoService* service() const { return service_; }
perfetto::TracingService::ConsumerEndpoint* consumer_endpoint() const {
return consumer_endpoint_.get();
}
// mojom::ConsumerHost implementation.
void EnableTracing(
mojo::PendingReceiver<mojom::TracingSessionHost> tracing_session_host,
mojo::PendingRemote<mojom::TracingSessionClient> tracing_session_client,
const perfetto::TraceConfig& config,
base::File output_file) override;
// perfetto::Consumer implementation.
// This gets called by the Perfetto service as control signals,
// and to send finished protobufs over.
void OnConnect() override;
void OnDisconnect() override;
void OnTracingDisabled(const std::string& error) override;
void OnTraceData(std::vector<perfetto::TracePacket> packets,
bool has_more) override;
void OnObservableEvents(const perfetto::ObservableEvents&) override;
void OnTraceStats(bool success, const perfetto::TraceStats&) override;
void OnSessionCloned(const OnSessionClonedArgs&) override;
// Unused in Chrome.
void OnDetach(bool success) override {}
void OnAttach(bool success, const perfetto::TraceConfig&) override {}
TracingSession* tracing_session_for_testing() {
return tracing_session_.get();
}
private:
void DestructTracingSession();
const raw_ptr<PerfettoService> service_;
std::unique_ptr<TracingSession> tracing_session_;
SEQUENCE_CHECKER(sequence_checker_);
// Keep last to avoid edge-cases where its callbacks come in mid-destruction.
std::unique_ptr<perfetto::TracingService::ConsumerEndpoint>
consumer_endpoint_;
base::WeakPtrFactory<ConsumerHost> weak_factory_{this};
};
} // namespace tracing
#endif // SERVICES_TRACING_PERFETTO_CONSUMER_HOST_H_