1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
base / trace_event / trace_log.h [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);
// Called by TRACE_EVENT* macros, don't call this directly.
// If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied
// into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above.
TraceEventHandle AddTraceEvent(char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
TraceArguments* args,
unsigned int flags);
TraceEventHandle 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);
TraceEventHandle 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 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);
void UpdateTraceEventDuration(const unsigned char* category_group_enabled,
const char* name,
TraceEventHandle handle);
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);
// Process sort indices, if set, override the order of a process will appear
// relative to other processes in the trace viewer. Processes are sorted first
// on their sort index, ascending, then by their name, and then tid.
void SetProcessSortIndex(int sort_index);
// Helper function to set process_name in base::CurrentProcess.
void OnSetProcessName(const std::string& process_name);
// 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);
// Thread sort indices, if set, override the order of a thread will appear
// within its process in the trace viewer. Threads are sorted first on their
// sort index, ascending, then by their name, and then tid.
void SetThreadSortIndex(PlatformThreadId thread_id, int sort_index);
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 AddMetadataEventsWhileLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
template <typename T>
void AddMetadataEventWhileLocked(PlatformThreadId thread_id,
const char* metadata_name,
const char* arg_name,
const T& value)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
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_;
int process_sort_index_;
std::unordered_map<PlatformThreadId, int> thread_sort_indices_;
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_