/src/node/deps/v8/include/libplatform/v8-tracing.h
Line | Count | Source |
1 | | // Copyright 2016 the V8 project authors. All rights reserved. |
2 | | // Use of this source code is governed by a BSD-style license that can be |
3 | | // found in the LICENSE file. |
4 | | |
5 | | #ifndef V8_LIBPLATFORM_V8_TRACING_H_ |
6 | | #define V8_LIBPLATFORM_V8_TRACING_H_ |
7 | | |
8 | | #include <atomic> |
9 | | #include <memory> |
10 | | #include <unordered_set> |
11 | | #include <vector> |
12 | | |
13 | | #include "libplatform/libplatform-export.h" |
14 | | #include "v8-platform.h" // NOLINT(build/include_directory) |
15 | | |
16 | | namespace perfetto { |
17 | | namespace trace_processor { |
18 | | class TraceProcessorStorage; |
19 | | } |
20 | | class TracingSession; |
21 | | } |
22 | | |
23 | | namespace v8 { |
24 | | |
25 | | namespace base { |
26 | | class Mutex; |
27 | | } // namespace base |
28 | | |
29 | | namespace platform { |
30 | | namespace tracing { |
31 | | |
32 | | class TraceEventListener; |
33 | | |
34 | | const int kTraceMaxNumArgs = 2; |
35 | | |
36 | | class V8_PLATFORM_EXPORT TraceObject { |
37 | | public: |
38 | | union ArgValue { |
39 | | uint64_t as_uint; |
40 | | int64_t as_int; |
41 | | double as_double; |
42 | | const void* as_pointer; |
43 | | const char* as_string; |
44 | | }; |
45 | | |
46 | 0 | TraceObject() = default; |
47 | | ~TraceObject(); |
48 | | void Initialize( |
49 | | char phase, const uint8_t* category_enabled_flag, const char* name, |
50 | | const char* scope, uint64_t id, uint64_t bind_id, int num_args, |
51 | | const char** arg_names, const uint8_t* arg_types, |
52 | | const uint64_t* arg_values, |
53 | | std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, |
54 | | unsigned int flags, int64_t timestamp, int64_t cpu_timestamp); |
55 | | void UpdateDuration(int64_t timestamp, int64_t cpu_timestamp); |
56 | | void InitializeForTesting( |
57 | | char phase, const uint8_t* category_enabled_flag, const char* name, |
58 | | const char* scope, uint64_t id, uint64_t bind_id, int num_args, |
59 | | const char** arg_names, const uint8_t* arg_types, |
60 | | const uint64_t* arg_values, |
61 | | std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, |
62 | | unsigned int flags, int pid, int tid, int64_t ts, int64_t tts, |
63 | | uint64_t duration, uint64_t cpu_duration); |
64 | | |
65 | 0 | int pid() const { return pid_; } |
66 | 0 | int tid() const { return tid_; } |
67 | 0 | char phase() const { return phase_; } |
68 | 0 | const uint8_t* category_enabled_flag() const { |
69 | 0 | return category_enabled_flag_; |
70 | 0 | } |
71 | 0 | const char* name() const { return name_; } |
72 | 0 | const char* scope() const { return scope_; } |
73 | 0 | uint64_t id() const { return id_; } |
74 | 0 | uint64_t bind_id() const { return bind_id_; } |
75 | 0 | int num_args() const { return num_args_; } |
76 | 0 | const char** arg_names() { return arg_names_; } |
77 | 0 | uint8_t* arg_types() { return arg_types_; } |
78 | 0 | ArgValue* arg_values() { return arg_values_; } |
79 | 0 | std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables() { |
80 | 0 | return arg_convertables_; |
81 | 0 | } |
82 | 0 | unsigned int flags() const { return flags_; } |
83 | 0 | int64_t ts() { return ts_; } |
84 | 0 | int64_t tts() { return tts_; } |
85 | 0 | uint64_t duration() { return duration_; } |
86 | 0 | uint64_t cpu_duration() { return cpu_duration_; } |
87 | | |
88 | | private: |
89 | | int pid_; |
90 | | int tid_; |
91 | | char phase_; |
92 | | const char* name_; |
93 | | const char* scope_; |
94 | | const uint8_t* category_enabled_flag_; |
95 | | uint64_t id_; |
96 | | uint64_t bind_id_; |
97 | | int num_args_ = 0; |
98 | | const char* arg_names_[kTraceMaxNumArgs]; |
99 | | uint8_t arg_types_[kTraceMaxNumArgs]; |
100 | | ArgValue arg_values_[kTraceMaxNumArgs]; |
101 | | std::unique_ptr<v8::ConvertableToTraceFormat> |
102 | | arg_convertables_[kTraceMaxNumArgs]; |
103 | | char* parameter_copy_storage_ = nullptr; |
104 | | unsigned int flags_; |
105 | | int64_t ts_; |
106 | | int64_t tts_; |
107 | | uint64_t duration_; |
108 | | uint64_t cpu_duration_; |
109 | | |
110 | | // Disallow copy and assign |
111 | | TraceObject(const TraceObject&) = delete; |
112 | | void operator=(const TraceObject&) = delete; |
113 | | }; |
114 | | |
115 | | class V8_PLATFORM_EXPORT TraceWriter { |
116 | | public: |
117 | | TraceWriter() = default; |
118 | | virtual ~TraceWriter() = default; |
119 | | virtual void AppendTraceEvent(TraceObject* trace_event) = 0; |
120 | | virtual void Flush() = 0; |
121 | | |
122 | | static TraceWriter* CreateJSONTraceWriter(std::ostream& stream); |
123 | | static TraceWriter* CreateJSONTraceWriter(std::ostream& stream, |
124 | | const std::string& tag); |
125 | | |
126 | | static TraceWriter* CreateSystemInstrumentationTraceWriter(); |
127 | | |
128 | | private: |
129 | | // Disallow copy and assign |
130 | | TraceWriter(const TraceWriter&) = delete; |
131 | | void operator=(const TraceWriter&) = delete; |
132 | | }; |
133 | | |
134 | | class V8_PLATFORM_EXPORT TraceBufferChunk { |
135 | | public: |
136 | | explicit TraceBufferChunk(uint32_t seq); |
137 | | |
138 | | void Reset(uint32_t new_seq); |
139 | 0 | bool IsFull() const { return next_free_ == kChunkSize; } |
140 | | TraceObject* AddTraceEvent(size_t* event_index); |
141 | 0 | TraceObject* GetEventAt(size_t index) { return &chunk_[index]; } |
142 | | |
143 | 0 | uint32_t seq() const { return seq_; } |
144 | 0 | size_t size() const { return next_free_; } |
145 | | |
146 | | static const size_t kChunkSize = 64; |
147 | | |
148 | | private: |
149 | | size_t next_free_ = 0; |
150 | | TraceObject chunk_[kChunkSize]; |
151 | | uint32_t seq_; |
152 | | |
153 | | // Disallow copy and assign |
154 | | TraceBufferChunk(const TraceBufferChunk&) = delete; |
155 | | void operator=(const TraceBufferChunk&) = delete; |
156 | | }; |
157 | | |
158 | | class V8_PLATFORM_EXPORT TraceBuffer { |
159 | | public: |
160 | 0 | TraceBuffer() = default; |
161 | 0 | virtual ~TraceBuffer() = default; |
162 | | |
163 | | virtual TraceObject* AddTraceEvent(uint64_t* handle) = 0; |
164 | | virtual TraceObject* GetEventByHandle(uint64_t handle) = 0; |
165 | | virtual bool Flush() = 0; |
166 | | |
167 | | static const size_t kRingBufferChunks = 1024; |
168 | | |
169 | | static TraceBuffer* CreateTraceBufferRingBuffer(size_t max_chunks, |
170 | | TraceWriter* trace_writer); |
171 | | |
172 | | private: |
173 | | // Disallow copy and assign |
174 | | TraceBuffer(const TraceBuffer&) = delete; |
175 | | void operator=(const TraceBuffer&) = delete; |
176 | | }; |
177 | | |
178 | | // Options determines how the trace buffer stores data. |
179 | | enum TraceRecordMode { |
180 | | // Record until the trace buffer is full. |
181 | | RECORD_UNTIL_FULL, |
182 | | |
183 | | // Record until the user ends the trace. The trace buffer is a fixed size |
184 | | // and we use it as a ring buffer during recording. |
185 | | RECORD_CONTINUOUSLY, |
186 | | |
187 | | // Record until the trace buffer is full, but with a huge buffer size. |
188 | | RECORD_AS_MUCH_AS_POSSIBLE, |
189 | | |
190 | | // Echo to console. Events are discarded. |
191 | | ECHO_TO_CONSOLE, |
192 | | }; |
193 | | |
194 | | class V8_PLATFORM_EXPORT TraceConfig { |
195 | | public: |
196 | | typedef std::vector<std::string> StringList; |
197 | | |
198 | | static TraceConfig* CreateDefaultTraceConfig(); |
199 | | |
200 | 0 | TraceConfig() : enable_systrace_(false), enable_argument_filter_(false) {} |
201 | 0 | TraceRecordMode GetTraceRecordMode() const { return record_mode_; } |
202 | 0 | const StringList& GetEnabledCategories() const { |
203 | 0 | return included_categories_; |
204 | 0 | } |
205 | 0 | bool IsSystraceEnabled() const { return enable_systrace_; } |
206 | 0 | bool IsArgumentFilterEnabled() const { return enable_argument_filter_; } |
207 | | |
208 | 0 | void SetTraceRecordMode(TraceRecordMode mode) { record_mode_ = mode; } |
209 | 0 | void EnableSystrace() { enable_systrace_ = true; } |
210 | 0 | void EnableArgumentFilter() { enable_argument_filter_ = true; } |
211 | | |
212 | | void AddIncludedCategory(const char* included_category); |
213 | | |
214 | | bool IsCategoryGroupEnabled(const char* category_group) const; |
215 | | |
216 | | private: |
217 | | TraceRecordMode record_mode_; |
218 | | bool enable_systrace_ : 1; |
219 | | bool enable_argument_filter_ : 1; |
220 | | StringList included_categories_; |
221 | | |
222 | | // Disallow copy and assign |
223 | | TraceConfig(const TraceConfig&) = delete; |
224 | | void operator=(const TraceConfig&) = delete; |
225 | | }; |
226 | | |
227 | | #if defined(_MSC_VER) |
228 | | #define V8_PLATFORM_NON_EXPORTED_BASE(code) \ |
229 | | __pragma(warning(suppress : 4275)) code |
230 | | #else |
231 | | #define V8_PLATFORM_NON_EXPORTED_BASE(code) code |
232 | | #endif // defined(_MSC_VER) |
233 | | |
234 | | class V8_PLATFORM_EXPORT TracingController |
235 | | : public V8_PLATFORM_NON_EXPORTED_BASE(v8::TracingController) { |
236 | | public: |
237 | | TracingController(); |
238 | | ~TracingController() override; |
239 | | |
240 | | #if defined(V8_USE_PERFETTO) |
241 | | // Must be called before StartTracing() if V8_USE_PERFETTO is true. Provides |
242 | | // the output stream for the JSON trace data. |
243 | | void InitializeForPerfetto(std::ostream* output_stream); |
244 | | // Provide an optional listener for testing that will receive trace events. |
245 | | // Must be called before StartTracing(). |
246 | | void SetTraceEventListenerForTesting(TraceEventListener* listener); |
247 | | #else // defined(V8_USE_PERFETTO) |
248 | | // The pointer returned from GetCategoryGroupEnabled() points to a value with |
249 | | // zero or more of the following bits. Used in this class only. The |
250 | | // TRACE_EVENT macros should only use the value as a bool. These values must |
251 | | // be in sync with macro values in TraceEvent.h in Blink. |
252 | | enum CategoryGroupEnabledFlags { |
253 | | // Category group enabled for the recording mode. |
254 | | ENABLED_FOR_RECORDING = 1 << 0, |
255 | | // Category group enabled by SetEventCallbackEnabled(). |
256 | | ENABLED_FOR_EVENT_CALLBACK = 1 << 2, |
257 | | // Category group enabled to export events to ETW. |
258 | | ENABLED_FOR_ETW_EXPORT = 1 << 3 |
259 | | }; |
260 | | |
261 | | // Takes ownership of |trace_buffer|. |
262 | | void Initialize(TraceBuffer* trace_buffer); |
263 | | |
264 | | // v8::TracingController implementation. |
265 | | const uint8_t* GetCategoryGroupEnabled(const char* category_group) override; |
266 | | uint64_t AddTraceEvent( |
267 | | char phase, const uint8_t* category_enabled_flag, const char* name, |
268 | | const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, |
269 | | const char** arg_names, const uint8_t* arg_types, |
270 | | const uint64_t* arg_values, |
271 | | std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, |
272 | | unsigned int flags) override; |
273 | | uint64_t AddTraceEventWithTimestamp( |
274 | | char phase, const uint8_t* category_enabled_flag, const char* name, |
275 | | const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, |
276 | | const char** arg_names, const uint8_t* arg_types, |
277 | | const uint64_t* arg_values, |
278 | | std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, |
279 | | unsigned int flags, int64_t timestamp) override; |
280 | | void UpdateTraceEventDuration(const uint8_t* category_enabled_flag, |
281 | | const char* name, uint64_t handle) override; |
282 | | |
283 | | static const char* GetCategoryGroupName(const uint8_t* category_enabled_flag); |
284 | | |
285 | | void AddTraceStateObserver( |
286 | | v8::TracingController::TraceStateObserver* observer) override; |
287 | | void RemoveTraceStateObserver( |
288 | | v8::TracingController::TraceStateObserver* observer) override; |
289 | | #endif // !defined(V8_USE_PERFETTO) |
290 | | |
291 | | void StartTracing(TraceConfig* trace_config); |
292 | | void StopTracing(); |
293 | | |
294 | | protected: |
295 | | #if !defined(V8_USE_PERFETTO) |
296 | | virtual int64_t CurrentTimestampMicroseconds(); |
297 | | virtual int64_t CurrentCpuTimestampMicroseconds(); |
298 | | #endif // !defined(V8_USE_PERFETTO) |
299 | | |
300 | | private: |
301 | | #if !defined(V8_USE_PERFETTO) |
302 | | void UpdateCategoryGroupEnabledFlag(size_t category_index); |
303 | | void UpdateCategoryGroupEnabledFlags(); |
304 | | #endif // !defined(V8_USE_PERFETTO) |
305 | | |
306 | | std::unique_ptr<base::Mutex> mutex_; |
307 | | std::unique_ptr<TraceConfig> trace_config_; |
308 | | std::atomic_bool recording_{false}; |
309 | | |
310 | | #if defined(V8_USE_PERFETTO) |
311 | | std::ostream* output_stream_ = nullptr; |
312 | | std::unique_ptr<perfetto::trace_processor::TraceProcessorStorage> |
313 | | trace_processor_; |
314 | | TraceEventListener* listener_for_testing_ = nullptr; |
315 | | std::unique_ptr<perfetto::TracingSession> tracing_session_; |
316 | | #else // !defined(V8_USE_PERFETTO) |
317 | | std::unordered_set<v8::TracingController::TraceStateObserver*> observers_; |
318 | | std::unique_ptr<TraceBuffer> trace_buffer_; |
319 | | #endif // !defined(V8_USE_PERFETTO) |
320 | | |
321 | | // Disallow copy and assign |
322 | | TracingController(const TracingController&) = delete; |
323 | | void operator=(const TracingController&) = delete; |
324 | | }; |
325 | | |
326 | | #undef V8_PLATFORM_NON_EXPORTED_BASE |
327 | | |
328 | | } // namespace tracing |
329 | | } // namespace platform |
330 | | } // namespace v8 |
331 | | |
332 | | #endif // V8_LIBPLATFORM_V8_TRACING_H_ |