chromium/base/trace_event/trace_log.cc

// 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.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
#pragma allow_unsafe_buffers
#endif

#include "base/trace_event/trace_log.h"

#include <cmath>
#include <limits>
#include <memory>
#include <string_view>
#include <unordered_set>
#include <utility>

#include "base/auto_reset.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/debug/leak_annotations.h"
#include "base/format_macros.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/stack_allocated.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/process.h"
#include "base/process/process_metrics.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/task/current_thread.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_id_name_manager.h"
#include "base/time/time.h"
#include "base/trace_event/heap_profiler.h"
#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_buffer.h"
#include "base/trace_event/trace_event.h"
#include "base/tracing/perfetto_platform.h"
#include "build/build_config.h"
#include "third_party/perfetto/include/perfetto/ext/trace_processor/export_json.h"  // nogncheck
#include "third_party/perfetto/include/perfetto/trace_processor/trace_processor_storage.h"  // nogncheck
#include "third_party/perfetto/include/perfetto/tracing/console_interceptor.h"
#include "third_party/perfetto/protos/perfetto/config/chrome/chrome_config.gen.h"  // nogncheck
#include "third_party/perfetto/protos/perfetto/config/interceptor_config.gen.h"  // nogncheck
#include "third_party/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.h"  // nogncheck
#include "third_party/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.h"  // nogncheck

#if BUILDFLAG(IS_WIN)
#include "base/trace_event/trace_event_etw_export_win.h"
#endif

#if BUILDFLAG(IS_ANDROID)
#include "base/debug/elf_reader.h"

// The linker assigns the virtual address of the start of current library to
// this symbol.
extern char __executable_start;
#endif

namespace base {
namespace trace_event {

namespace {

// Controls the number of trace events we will buffer in-memory
// before throwing them away.
const size_t kTraceBufferChunkSize =;

const size_t kTraceEventVectorBigBufferChunks =;
static_assert;
const size_t kTraceEventVectorBufferChunks =;
static_assert;
const size_t kTraceEventRingBufferChunks =;

// ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events.
const size_t kEchoToConsoleTraceEventBufferChunks =;

const size_t kTraceEventBufferSizeInBytes =;

bool g_perfetto_initialized_by_tracelog =;

TraceLog* g_trace_log_for_testing =;

ABSL_CONST_INIT thread_local TraceLog::ThreadLocalEventBuffer*
    thread_local_event_buffer =;
ABSL_CONST_INIT thread_local bool thread_blocks_message_loop =;
ABSL_CONST_INIT thread_local bool thread_is_in_trace_event =;

ThreadTicks ThreadNow() {}

template <typename T>
void InitializeMetadataEvent(TraceEvent* trace_event,
                             PlatformThreadId thread_id,
                             const char* metadata_name,
                             const char* arg_name,
                             const T& value) {}

// Use this function instead of TraceEventHandle constructor to keep the
// overhead of ScopedTracer (trace_event.h) constructor minimum.
void MakeHandle(uint32_t chunk_seq,
                size_t chunk_index,
                size_t event_index,
                TraceEventHandle* handle) {}

// The fallback arguments filtering function will filter away every argument.
bool DefaultIsTraceEventArgsAllowlisted(
    const char* category_group_name,
    const char* event_name,
    base::trace_event::ArgumentNameFilterPredicate* arg_name_filter) {}

class PerfettoProtoAppender
    : public base::trace_event::ConvertableToTraceFormat::ProtoAppender {};

void AddConvertableToTraceFormat(
    base::trace_event::ConvertableToTraceFormat* value,
    perfetto::protos::pbzero::DebugAnnotation* annotation) {}

void WriteDebugAnnotations(base::trace_event::TraceEvent* trace_event,
                           perfetto::protos::pbzero::TrackEvent* track_event) {}

void OnAddLegacyTraceEvent(TraceEvent* trace_event,
                           bool thread_will_flush,
                           base::trace_event::TraceEventHandle* handle) {}

void OnUpdateLegacyTraceEventDuration(
    const unsigned char* category_group_enabled,
    const char* name,
    TraceEventHandle handle,
    PlatformThreadId thread_id,
    bool explicit_timestamps,
    const TimeTicks& now,
    const ThreadTicks& thread_now) {}

}  // namespace

#if BUILDFLAG(USE_PERFETTO_TRACE_PROCESSOR)
namespace {
// Perfetto provides us with a fully formed JSON trace file, while
// TraceResultBuffer wants individual JSON fragments without a containing
// object. We therefore need to strip away the outer object, including the
// metadata fields, from the JSON stream.
static constexpr char kJsonPrefix[] =;
static constexpr char kJsonJoiner[] =;
static constexpr char kJsonSuffix[] =;
}  // namespace

class JsonStringOutputWriter
    : public perfetto::trace_processor::json::OutputWriter {};
#endif  // BUILDFLAG(USE_PERFETTO_TRACE_PROCESSOR)

// A helper class that allows the lock to be acquired in the middle of the scope
// and unlocks at the end of scope if locked.
class TraceLog::OptionalAutoLock {};

class TraceLog::ThreadLocalEventBuffer
    : public CurrentThread::DestructionObserver,
      public MemoryDumpProvider {};

TraceLog::ThreadLocalEventBuffer::ThreadLocalEventBuffer(TraceLog* trace_log)
    :{}

TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() {}

TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent(
    TraceEventHandle* handle) {}

void TraceLog::ThreadLocalEventBuffer::WillDestroyCurrentMessageLoop() {}

bool TraceLog::ThreadLocalEventBuffer::OnMemoryDump(const MemoryDumpArgs& args,
                                                    ProcessMemoryDump* pmd) {}

void TraceLog::ThreadLocalEventBuffer::FlushWhileLocked() {}

void TraceLog::SetAddTraceEventOverrides(
    const AddTraceEventOverrideFunction& add_event_override,
    const OnFlushFunction& on_flush_override,
    const UpdateDurationFunction& update_duration_override) {}

struct TraceLog::RegisteredAsyncObserver {};

TraceLogStatus::TraceLogStatus() :{}

TraceLogStatus::~TraceLogStatus() = default;

// static
TraceLog* TraceLog::GetInstance() {}

// static
void TraceLog::ResetForTesting() {}

TraceLog::TraceLog(int generation)
    :{}

TraceLog::~TraceLog() {}

void TraceLog::InitializeThreadLocalEventBufferIfSupported() {}

bool TraceLog::OnMemoryDump(const MemoryDumpArgs& args,
                            ProcessMemoryDump* pmd) {}

const unsigned char* TraceLog::GetCategoryGroupEnabled(
    const char* category_group) {}

const char* TraceLog::GetCategoryGroupName(
    const unsigned char* category_group_enabled) {}

void TraceLog::UpdateCategoryState(TraceCategory* category) {}

void TraceLog::UpdateCategoryRegistry() {}

void TraceLog::SetEnabled(const TraceConfig& trace_config,
                          uint8_t modes_to_enable) {}

std::vector<TraceLog::TrackEventSession> TraceLog::GetTrackEventSessions()
    const {}

perfetto::DataSourceConfig TraceLog::GetCurrentTrackEventDataSourceConfig()
    const {}

void TraceLog::InitializePerfettoIfNeeded() {}

bool TraceLog::IsPerfettoInitializedByTraceLog() const {}

void TraceLog::SetEnabled(const TraceConfig& trace_config,
                          const perfetto::TraceConfig& perfetto_config) {}

void TraceLog::SetEnabledImpl(const TraceConfig& trace_config,
                              const perfetto::TraceConfig& perfetto_config) {}

void TraceLog::SetArgumentFilterPredicate(
    const ArgumentFilterPredicate& argument_filter_predicate) {}

ArgumentFilterPredicate TraceLog::GetArgumentFilterPredicate() const {}

void TraceLog::SetMetadataFilterPredicate(
    const MetadataFilterPredicate& metadata_filter_predicate) {}

MetadataFilterPredicate TraceLog::GetMetadataFilterPredicate() const {}

void TraceLog::SetRecordHostAppPackageName(bool record_host_app_package_name) {}

bool TraceLog::ShouldRecordHostAppPackageName() const {}

TraceLog::InternalTraceOptions TraceLog::GetInternalOptionsFromTraceConfig(
    const TraceConfig& config) {}

TraceConfig TraceLog::GetCurrentTraceConfig() const {}

void TraceLog::SetDisabled() {}

void TraceLog::SetDisabled(uint8_t modes_to_disable) {}

void TraceLog::SetDisabledWhileLocked(uint8_t modes_to_disable) {}

int TraceLog::GetNumTracesRecorded() {}

void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) {}

void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) {}

void TraceLog::AddOwnedEnabledStateObserver(
    std::unique_ptr<EnabledStateObserver> listener) {}

bool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const {}

void TraceLog::AddAsyncEnabledStateObserver(
    WeakPtr<AsyncEnabledStateObserver> listener) {}

void TraceLog::RemoveAsyncEnabledStateObserver(
    AsyncEnabledStateObserver* listener) {}

bool TraceLog::HasAsyncEnabledStateObserver(
    AsyncEnabledStateObserver* listener) const {}

void TraceLog::AddIncrementalStateObserver(IncrementalStateObserver* listener) {}

void TraceLog::RemoveIncrementalStateObserver(
    IncrementalStateObserver* listener) {}

void TraceLog::OnIncrementalStateCleared() {}

TraceLogStatus TraceLog::GetStatus() const {}

TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked(
    TraceEventHandle* handle,
    bool check_buffer_is_full) {}

void TraceLog::CheckIfBufferIsFullWhileLocked() {}

// Flush() works as the following:
// 1. Flush() is called in thread A whose task runner is saved in
//    flush_task_runner_;
// 2. If thread_message_loops_ is not empty, thread A posts task to each message
//    loop to flush the thread local buffers; otherwise finish the flush;
// 3. FlushCurrentThread() deletes the thread local event buffer:
//    - The last batch of events of the thread are flushed into the main buffer;
//    - The message loop will be removed from thread_message_loops_;
//    If this is the last message loop, finish the flush;
// 4. If any thread hasn't finish its flush in time, finish the flush.
void TraceLog::Flush(const TraceLog::OutputCallback& cb,
                     bool use_worker_thread) {}

void TraceLog::CancelTracing(const OutputCallback& cb) {}

void TraceLog::FlushInternal(const TraceLog::OutputCallback& cb,
                             bool use_worker_thread,
                             bool discard_events) {}

#if BUILDFLAG(USE_PERFETTO_TRACE_PROCESSOR)
void TraceLog::OnTraceData(const char* data, size_t size, bool has_more) {}
#endif  // BUILDFLAG(USE_PERFETTO_TRACE_PROCESSOR)

// Usually it runs on a different thread.
void TraceLog::ConvertTraceEventsToTraceFormat(
    std::unique_ptr<TraceBuffer> logged_events,
    const OutputCallback& flush_output_callback,
    const ArgumentFilterPredicate& argument_filter_predicate) {}

void TraceLog::FinishFlush(int generation, bool discard_events) {}

// Run in each thread holding a local event buffer.
void TraceLog::FlushCurrentThread(int generation, bool discard_events) {}

void TraceLog::OnFlushTimeout(int generation, bool discard_events) {}

void TraceLog::UseNextTraceBuffer() {}

bool TraceLog::ShouldAddAfterUpdatingState(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    uint64_t id,
    PlatformThreadId thread_id,
    const TimeTicks timestamp,
    TraceArguments* args) {}

TraceEventHandle TraceLog::AddTraceEvent(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    TraceArguments* args,
    unsigned int flags) {}

TraceEventHandle TraceLog::AddTraceEventWithBindId(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    uint64_t bind_id,
    TraceArguments* args,
    unsigned int flags) {}

TraceEventHandle TraceLog::AddTraceEventWithProcessId(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    ProcessId process_id,
    TraceArguments* args,
    unsigned int flags) {}

// Handle legacy calls to AddTraceEventWithThreadIdAndTimestamp
// with kNoId as bind_id
TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    PlatformThreadId thread_id,
    const TimeTicks& timestamp,
    TraceArguments* args,
    unsigned int flags) {}

TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    uint64_t bind_id,
    PlatformThreadId thread_id,
    const TimeTicks& timestamp,
    TraceArguments* args,
    unsigned int flags) {}

TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamps(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    uint64_t bind_id,
    PlatformThreadId thread_id,
    const TimeTicks& timestamp,
    const ThreadTicks& thread_timestamp,
    TraceArguments* args,
    unsigned int flags) NO_THREAD_SAFETY_ANALYSIS {}

void TraceLog::AddMetadataEvent(const unsigned char* category_group_enabled,
                                const char* name,
                                TraceArguments* args,
                                unsigned int flags) {}

// May be called when a COMPELETE event ends and the unfinished event has been
// recycled (phase == TRACE_EVENT_PHASE_END and trace_event == NULL).
std::string TraceLog::EventToConsoleMessage(char phase,
                                            const TimeTicks& timestamp,
                                            TraceEvent* trace_event) {}

void TraceLog::UpdateTraceEventDuration(
    const unsigned char* category_group_enabled,
    const char* name,
    TraceEventHandle handle) {}

void TraceLog::UpdateTraceEventDurationExplicit(
    const unsigned char* category_group_enabled,
    const char* name,
    TraceEventHandle handle,
    PlatformThreadId thread_id,
    bool explicit_timestamps,
    const TimeTicks& now,
    const ThreadTicks& thread_now) {}

uint64_t TraceLog::MangleEventId(uint64_t id) {}

template <typename T>
void TraceLog::AddMetadataEventWhileLocked(PlatformThreadId thread_id,
                                           const char* metadata_name,
                                           const char* arg_name,
                                           const T& value) {}

void TraceLog::AddMetadataEventsWhileLocked() {}

TraceEvent* TraceLog::GetEventByHandle(TraceEventHandle handle) {}

TraceEvent* TraceLog::GetEventByHandleInternal(TraceEventHandle handle,
                                               OptionalAutoLock* lock)
    NO_THREAD_SAFETY_ANALYSIS {}

void TraceLog::SetProcessID(ProcessId process_id) {}

void TraceLog::SetProcessSortIndex(int sort_index) {}

void TraceLog::OnSetProcessName(const std::string& process_name) {}

int TraceLog::GetNewProcessLabelId() {}

void TraceLog::UpdateProcessLabel(int label_id,
                                  const std::string& current_label) {}

void TraceLog::RemoveProcessLabel(int label_id) {}

void TraceLog::SetThreadSortIndex(PlatformThreadId thread_id, int sort_index) {}

size_t TraceLog::GetObserverCountForTest() const {}

void TraceLog::SetCurrentThreadBlocksMessageLoop() {}

TraceBuffer* TraceLog::CreateTraceBuffer() {}

#if BUILDFLAG(IS_WIN)
void TraceLog::UpdateETWCategoryGroupEnabledFlags() {
  // Go through each category and set/clear the ETW bit depending on whether the
  // category is enabled.
  for (TraceCategory& category : CategoryRegistry::GetAllCategories()) {
    if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled(
            category.name())) {
      category.set_state_flag(TraceCategory::ENABLED_FOR_ETW_EXPORT);
    } else {
      category.clear_state_flag(TraceCategory::ENABLED_FOR_ETW_EXPORT);
    }
  }
}
#endif  // BUILDFLAG(IS_WIN)

void TraceLog::SetTraceBufferForTesting(
    std::unique_ptr<TraceBuffer> trace_buffer) {}

void TraceLog::OnSetup(const perfetto::DataSourceBase::SetupArgs& args) {}

void TraceLog::OnStart(const perfetto::DataSourceBase::StartArgs&) {}

void TraceLog::OnStop(const perfetto::DataSourceBase::StopArgs& args) {}

void ConvertableToTraceFormat::EstimateTraceMemoryOverhead(
    TraceEventMemoryOverhead* overhead) {}

}  // namespace trace_event
}  // namespace base

namespace trace_event_internal {

base::trace_event::TraceEventHandle AddTraceEvent(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    base::trace_event::TraceArguments* args,
    unsigned int flags) {}

base::trace_event::TraceEventHandle AddTraceEventWithBindId(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    uint64_t bind_id,
    base::trace_event::TraceArguments* args,
    unsigned int flags) {}

base::trace_event::TraceEventHandle AddTraceEventWithProcessId(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    base::ProcessId process_id,
    base::trace_event::TraceArguments* args,
    unsigned int flags) {}

base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    base::PlatformThreadId thread_id,
    const base::TimeTicks& timestamp,
    base::trace_event::TraceArguments* args,
    unsigned int flags) {}

base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    uint64_t bind_id,
    base::PlatformThreadId thread_id,
    const base::TimeTicks& timestamp,
    base::trace_event::TraceArguments* args,
    unsigned int flags) {}

base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamps(
    char phase,
    const unsigned char* category_group_enabled,
    const char* name,
    const char* scope,
    uint64_t id,
    base::PlatformThreadId thread_id,
    const base::TimeTicks& timestamp,
    const base::ThreadTicks& thread_timestamp,
    unsigned int flags) {}

void AddMetadataEvent(const unsigned char* category_group_enabled,
                      const char* name,
                      base::trace_event::TraceArguments* args,
                      unsigned int flags) {}

int GetNumTracesRecorded() {}

void UpdateTraceEventDuration(const unsigned char* category_group_enabled,
                              const char* name,
                              base::trace_event::TraceEventHandle handle) {}

void UpdateTraceEventDurationExplicit(
    const unsigned char* category_group_enabled,
    const char* name,
    base::trace_event::TraceEventHandle handle,
    base::PlatformThreadId thread_id,
    bool explicit_timestamps,
    const base::TimeTicks& now,
    const base::ThreadTicks& thread_now) {}

}  // namespace trace_event_internal