blob: 45c87e9dd1682900694e24db713622617d47df3f [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TRACE_EVENT_TRACE_LOG_H_
#define BASE_TRACE_EVENT_TRACE_LOG_H_
#include <stddef.h>
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "base/base_export.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/platform_thread.h"
#include "base/time/time_override.h"
#include "base/trace_event/builtin_categories.h"
#include "base/trace_event/trace_config.h"
#include "base/trace_event/trace_event_impl.h"
#include "build/build_config.h"
#include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h"
namespace perfetto {
namespace trace_processor {
class TraceProcessorStorage;
} // namespace trace_processor
} // namespace perfetto
namespace base {
class RefCountedString;
namespace trace_event {
class JsonStringOutputWriter;
class BASE_EXPORT TraceLog : public perfetto::TrackEventSessionObserver {
public:
static TraceLog* GetInstance();
TraceLog(const TraceLog&) = delete;
TraceLog& operator=(const TraceLog&) = delete;
// Retrieves a copy (for thread-safety) of the current TraceConfig.
TraceConfig GetCurrentTraceConfig() const;
// See TraceConfig comments for details on how to control which categories
// will be traced.
void SetEnabled(const TraceConfig& trace_config);
// Enable tracing using a customized Perfetto trace config. This allows, for
// example, enabling additional data sources and enabling protobuf output
// instead of the legacy JSON trace format.
void SetEnabled(const TraceConfig& trace_config,
const perfetto::TraceConfig& perfetto_config);
// Disables tracing for all categories.
void SetDisabled();
// Returns true if TraceLog is enabled (i.e. there's an active tracing
// session).
bool IsEnabled() {
// We don't rely on TrackEvent::IsEnabled() because it can be true before
// TraceLog has processed its TrackEventSessionObserver callbacks.
// For example, the code
// if (TrackEvent::IsEnabled()) {
// auto config = TraceLog::GetCurrentTrackEventDataSourceConfig();
// ...
// }
// can fail in a situation when TrackEvent::IsEnabled() is already true, but
// TraceLog::OnSetup() hasn't been called yet, so we don't know the config.
// Instead, we make sure that both OnSetup() and OnStart() have been called
// by tracking the number of active sessions that TraceLog has seen.
AutoLock lock(track_event_lock_);
return active_track_event_sessions_ > 0;
}
// Enabled state listeners give a callback when tracing is enabled or
// disabled. This can be used to tie into other library's tracing systems
// on-demand.
class BASE_EXPORT EnabledStateObserver {
public:
virtual ~EnabledStateObserver() = default;
// Called just after the tracing system becomes enabled, outside of the
// |lock_|. TraceLog::IsEnabled() is true at this point.
virtual void OnTraceLogEnabled() = 0;
// Called just after the tracing system disables, outside of the |lock_|.
// TraceLog::IsEnabled() is false at this point.
virtual void OnTraceLogDisabled() = 0;
};
// Adds an observer. Cannot be called from within the observer callback.
void AddEnabledStateObserver(EnabledStateObserver* listener);
// Removes an observer. Cannot be called from within the observer callback.
void RemoveEnabledStateObserver(EnabledStateObserver* listener);
// Adds an observer that is owned by TraceLog. This is useful for agents that
// implement tracing feature that needs to stay alive as long as TraceLog
// does.
void AddOwnedEnabledStateObserver(
std::unique_ptr<EnabledStateObserver> listener);
bool HasEnabledStateObserver(EnabledStateObserver* listener) const;
// Asynchronous enabled state listeners. When tracing is enabled or disabled,
// for each observer, a task for invoking its appropriate callback is posted
// to the `SequencedTaskRunner` from which AddAsyncEnabledStateObserver() was
// called. This allows the observer to be safely destroyed, provided that it
// happens on the same `SequencedTaskRunner` that invoked
// AddAsyncEnabledStateObserver().
class BASE_EXPORT AsyncEnabledStateObserver {
public:
virtual ~AsyncEnabledStateObserver() = default;
// Posted just after the tracing system becomes enabled, outside |lock_|.
// TraceLog::IsEnabled() is true at this point.
virtual void OnTraceLogEnabled() = 0;
// Posted just after the tracing system becomes disabled, outside |lock_|.
// TraceLog::IsEnabled() is false at this point.
virtual void OnTraceLogDisabled() = 0;
};
// TODO(oysteine): This API originally needed to use WeakPtrs as the observer
// list was copied under the global trace lock, but iterated over outside of
// that lock so that observers could add tracing. The list is now protected by
// its own lock, so this can be changed to a raw ptr.
void AddAsyncEnabledStateObserver(
WeakPtr<AsyncEnabledStateObserver> listener);
void RemoveAsyncEnabledStateObserver(AsyncEnabledStateObserver* listener);
bool HasAsyncEnabledStateObserver(AsyncEnabledStateObserver* listener) const;
void SetArgumentFilterPredicate(
const ArgumentFilterPredicate& argument_filter_predicate);
ArgumentFilterPredicate GetArgumentFilterPredicate() const;
void SetMetadataFilterPredicate(
const MetadataFilterPredicate& metadata_filter_predicate);
MetadataFilterPredicate GetMetadataFilterPredicate() const;
void SetRecordHostAppPackageName(bool record_host_app_package_name);
bool ShouldRecordHostAppPackageName() const;
// Flush all collected events to the given output callback. The callback will
// be called one or more times either synchronously or asynchronously from
// the current thread with IPC-bite-size chunks. The string format is
// undefined. Use TraceResultBuffer to convert one or more trace strings to
// JSON. The callback can be null if the caller doesn't want any data.
// Due to the implementation of thread-local buffers, flush can't be
// done when tracing is enabled. If called when tracing is enabled, the
// callback will be called directly with (empty_string, false) to indicate
// the end of this unsuccessful flush. Flush does the serialization
// on the same thread if the caller doesn't set use_worker_thread explicitly.
using OutputCallback =
base::RepeatingCallback<void(const scoped_refptr<base::RefCountedString>&,
bool has_more_events)>;
void Flush(const OutputCallback& cb, bool use_worker_thread = false);
// Cancels tracing and discards collected data.
void CancelTracing(const OutputCallback& cb);
// Called by TRACE_EVENT* macros, don't call this directly.
// The name parameter is a category group for example:
// TRACE_EVENT0("renderer,webkit", "WebViewImpl::HandleInputEvent")
static const unsigned char* GetCategoryGroupEnabled(const char* name);
static const char* GetCategoryGroupName(
const unsigned char* category_group_enabled);
ProcessId process_id() const { return process_id_; }
std::unordered_map<int, std::string> process_labels() const {
AutoLock lock(lock_);
return process_labels_;
}
// Exposed for unittesting:
// Allows clearing up our singleton instance.
static void ResetForTesting();
void SetProcessID(ProcessId process_id);
// Processes can have labels in addition to their names. Use labels, for
// instance, to list out the web page titles that a process is handling.
int GetNewProcessLabelId();
void UpdateProcessLabel(int label_id, const std::string& current_label);
void RemoveProcessLabel(int label_id);
size_t GetObserverCountForTest() const;
struct TrackEventSession {
uint32_t internal_instance_index;
perfetto::DataSourceConfig config;
perfetto::BackendType backend_type = perfetto::kUnspecifiedBackend;
};
std::vector<TrackEventSession> GetTrackEventSessions() const;
// DEPRECATED. In the presence of multiple simultaneous sessions, this method
// returns only the first session's config. When no tracing sessions are
// active, returns an empty config for compatibility with legacy code.
// TODO(khokhlov): Remove this method and migrate all its uses to
// GetTrackEventSessions().
perfetto::DataSourceConfig GetCurrentTrackEventDataSourceConfig() const;
void InitializePerfettoIfNeeded();
bool IsPerfettoInitializedByTraceLog() const;
void SetEnabledImpl(const TraceConfig& trace_config,
const perfetto::TraceConfig& perfetto_config);
// perfetto::TrackEventSessionObserver implementation.
void OnSetup(const perfetto::DataSourceBase::SetupArgs&) override;
void OnStart(const perfetto::DataSourceBase::StartArgs&) override;
void OnStop(const perfetto::DataSourceBase::StopArgs&) override;
private:
friend class base::NoDestructor<TraceLog>;
struct RegisteredAsyncObserver;
explicit TraceLog(int generation);
~TraceLog() override;
void SetDisabledWhileLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
void FlushInternal(const OutputCallback& cb,
bool use_worker_thread,
bool discard_events);
void OnTraceData(const char* data, size_t size, bool has_more);
// This lock protects TraceLog member accesses (except for members protected
// by thread_info_lock_) from arbitrary threads.
mutable Lock lock_;
// The lock protects observers access.
mutable Lock observers_lock_;
bool dispatching_to_observers_ = false;
std::vector<raw_ptr<EnabledStateObserver, VectorExperimental>>
enabled_state_observers_ GUARDED_BY(observers_lock_);
std::map<AsyncEnabledStateObserver*, RegisteredAsyncObserver> async_observers_
GUARDED_BY(observers_lock_);
// Manages ownership of the owned observers. The owned observers will also be
// added to |enabled_state_observers_|.
std::vector<std::unique_ptr<EnabledStateObserver>>
owned_enabled_state_observer_copy_ GUARDED_BY(observers_lock_);
int next_process_label_id_ GUARDED_BY(lock_) = 0;
std::unordered_map<int, std::string> process_labels_;
ProcessId process_id_;
// Set when asynchronous Flush is in progress.
ArgumentFilterPredicate argument_filter_predicate_;
MetadataFilterPredicate metadata_filter_predicate_;
bool record_host_app_package_name_{false};
std::unique_ptr<perfetto::TracingSession> tracing_session_;
perfetto::TraceConfig perfetto_config_;
std::vector<TrackEventSession> track_event_sessions_
GUARDED_BY(track_event_lock_);
int active_track_event_sessions_ = 0;
mutable Lock track_event_lock_;
#if BUILDFLAG(USE_PERFETTO_TRACE_PROCESSOR)
std::unique_ptr<perfetto::trace_processor::TraceProcessorStorage>
trace_processor_;
std::unique_ptr<JsonStringOutputWriter> json_output_writer_;
OutputCallback proto_output_callback_;
#endif // BUILDFLAG(USE_PERFETTO_TRACE_PROCESSOR)
};
} // namespace trace_event
} // namespace base
#endif // BASE_TRACE_EVENT_TRACE_LOG_H_