OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 | 5 |
6 #ifndef BASE_DEBUG_TRACE_EVENT_IMPL_H_ | 6 #ifndef BASE_DEBUG_TRACE_EVENT_IMPL_H_ |
7 #define BASE_DEBUG_TRACE_EVENT_IMPL_H_ | 7 #define BASE_DEBUG_TRACE_EVENT_IMPL_H_ |
8 | 8 |
9 #include "build/build_config.h" | 9 #include "build/build_config.h" |
10 | 10 |
11 #include <string> | 11 #include <string> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
14 #include "base/callback.h" | 14 #include "base/callback.h" |
15 #include "base/hash_tables.h" | 15 #include "base/hash_tables.h" |
16 #include "base/memory/ref_counted_memory.h" | 16 #include "base/memory/ref_counted_memory.h" |
17 #include "base/observer_list.h" | 17 #include "base/observer_list.h" |
18 #include "base/string_util.h" | 18 #include "base/string_util.h" |
19 #include "base/synchronization/condition_variable.h" | |
19 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
20 #include "base/timer.h" | 21 #include "base/timer.h" |
21 | 22 |
22 // Older style trace macros with explicit id and extra data | 23 // Older style trace macros with explicit id and extra data |
23 // Only these macros result in publishing data to ETW as currently implemented. | 24 // Only these macros result in publishing data to ETW as currently implemented. |
24 #define TRACE_EVENT_BEGIN_ETW(name, id, extra) \ | 25 #define TRACE_EVENT_BEGIN_ETW(name, id, extra) \ |
25 base::debug::TraceLog::AddTraceEventEtw( \ | 26 base::debug::TraceLog::AddTraceEventEtw( \ |
26 TRACE_EVENT_PHASE_BEGIN, \ | 27 TRACE_EVENT_PHASE_BEGIN, \ |
27 name, reinterpret_cast<const void*>(id), extra) | 28 name, reinterpret_cast<const void*>(id), extra) |
28 | 29 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 void AppendAsJSON(std::string* out) const; | 83 void AppendAsJSON(std::string* out) const; |
83 | 84 |
84 TimeTicks timestamp() const { return timestamp_; } | 85 TimeTicks timestamp() const { return timestamp_; } |
85 | 86 |
86 // Exposed for unittesting: | 87 // Exposed for unittesting: |
87 | 88 |
88 const base::RefCountedString* parameter_copy_storage() const { | 89 const base::RefCountedString* parameter_copy_storage() const { |
89 return parameter_copy_storage_.get(); | 90 return parameter_copy_storage_.get(); |
90 } | 91 } |
91 | 92 |
93 const unsigned char* category_enabled() const { return category_enabled_; } | |
92 const char* name() const { return name_; } | 94 const char* name() const { return name_; } |
93 | 95 |
94 private: | 96 private: |
95 // Note: these are ordered by size (largest first) for optimal packing. | 97 // Note: these are ordered by size (largest first) for optimal packing. |
96 TimeTicks timestamp_; | 98 TimeTicks timestamp_; |
97 // id_ can be used to store phase-specific data. | 99 // id_ can be used to store phase-specific data. |
98 unsigned long long id_; | 100 unsigned long long id_; |
99 TraceValue arg_values_[kTraceMaxNumArgs]; | 101 TraceValue arg_values_[kTraceMaxNumArgs]; |
100 const char* arg_names_[kTraceMaxNumArgs]; | 102 const char* arg_names_[kTraceMaxNumArgs]; |
101 const unsigned char* category_enabled_; | 103 const unsigned char* category_enabled_; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
147 void Finish(); | 149 void Finish(); |
148 | 150 |
149 private: | 151 private: |
150 OutputCallback output_callback_; | 152 OutputCallback output_callback_; |
151 bool append_comma_; | 153 bool append_comma_; |
152 }; | 154 }; |
153 | 155 |
154 | 156 |
155 class BASE_EXPORT TraceLog { | 157 class BASE_EXPORT TraceLog { |
156 public: | 158 public: |
159 // Notification is a mask of one or more of the following events. | |
160 enum Notification { | |
ccameron
2012/08/21 01:06:34
This isn't treated as a bit mask (but rather as a
jbates
2012/08/23 22:45:28
Good catch, TraceControllerImpl::OnTraceNotificati
| |
161 // The trace buffer does not flush dynamically, so when it fills up, | |
162 // subsequent trace events will be dropped. This callback is generated when | |
163 // the trace buffer is full. The callback must be thread safe. | |
164 TRACE_BUFFER_FULL = 1 << 0, | |
165 // A subscribed trace-event occurred. | |
166 EVENT_WATCH_NOTIFICATION = 1 << 1 | |
167 }; | |
168 | |
157 static TraceLog* GetInstance(); | 169 static TraceLog* GetInstance(); |
158 | 170 |
159 // Get set of known categories. This can change as new code paths are reached. | 171 // Get set of known categories. This can change as new code paths are reached. |
160 // The known categories are inserted into |categories|. | 172 // The known categories are inserted into |categories|. |
161 void GetKnownCategories(std::vector<std::string>* categories); | 173 void GetKnownCategories(std::vector<std::string>* categories); |
162 | 174 |
163 // Enable tracing for provided list of categories. If tracing is already | 175 // Enable tracing for provided list of categories. If tracing is already |
164 // enabled, this method does nothing -- changing categories during trace is | 176 // enabled, this method does nothing -- changing categories during trace is |
165 // not supported. | 177 // not supported. |
166 // If both included_categories and excluded_categories are empty, | 178 // If both included_categories and excluded_categories are empty, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
206 // still false at this point TRACE macros will still be capturing | 218 // still false at this point TRACE macros will still be capturing |
207 // data. However, trace macros and methods called within the observer will | 219 // data. However, trace macros and methods called within the observer will |
208 // deadlock. | 220 // deadlock. |
209 virtual void OnTraceLogWillDisable() { } | 221 virtual void OnTraceLogWillDisable() { } |
210 }; | 222 }; |
211 void AddEnabledStateObserver(EnabledStateChangedObserver* listener); | 223 void AddEnabledStateObserver(EnabledStateChangedObserver* listener); |
212 void RemoveEnabledStateObserver(EnabledStateChangedObserver* listener); | 224 void RemoveEnabledStateObserver(EnabledStateChangedObserver* listener); |
213 | 225 |
214 float GetBufferPercentFull() const; | 226 float GetBufferPercentFull() const; |
215 | 227 |
216 // When enough events are collected, they are handed (in bulk) to | 228 // Set the thread-safe notification callback. The callback can occur at any |
217 // the output callback. If no callback is set, the output will be | 229 // time. After calling SetNotificationCallback(NotificationCallback()) to |
218 // silently dropped. The callback must be thread safe. The string format is | 230 // clear the callback, it is guaranteed that the old callback will no longer |
231 // be called. Warning: it is possible for the old callback to be called during | |
232 // a call to SetNotificationCallback. | |
233 typedef base::Callback<void(int)> NotificationCallback; | |
234 void SetNotificationCallback(const NotificationCallback& cb); | |
235 | |
236 // Flush all collected events to the given output callback. The callback will | |
237 // be called one or more times with IPC-bite-size chunks. The string format is | |
219 // undefined. Use TraceResultBuffer to convert one or more trace strings to | 238 // undefined. Use TraceResultBuffer to convert one or more trace strings to |
220 // JSON. | 239 // JSON. |
221 typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&)> | 240 typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&)> |
222 OutputCallback; | 241 OutputCallback; |
223 void SetOutputCallback(const OutputCallback& cb); | 242 void Flush(const OutputCallback& cb); |
224 | |
225 // The trace buffer does not flush dynamically, so when it fills up, | |
226 // subsequent trace events will be dropped. This callback is generated when | |
227 // the trace buffer is full. The callback must be thread safe. | |
228 typedef base::Callback<void(void)> BufferFullCallback; | |
229 void SetBufferFullCallback(const BufferFullCallback& cb); | |
230 | |
231 // Flushes all logged data to the callback. | |
232 void Flush(); | |
233 | 243 |
234 // Called by TRACE_EVENT* macros, don't call this directly. | 244 // Called by TRACE_EVENT* macros, don't call this directly. |
235 static const unsigned char* GetCategoryEnabled(const char* name); | 245 static const unsigned char* GetCategoryEnabled(const char* name); |
236 static const char* GetCategoryName(const unsigned char* category_enabled); | 246 static const char* GetCategoryName(const unsigned char* category_enabled); |
237 | 247 |
238 // Called by TRACE_EVENT* macros, don't call this directly. | 248 // Called by TRACE_EVENT* macros, don't call this directly. |
239 // Returns the index in the internal vector of the event if it was added, or | 249 // Returns the index in the internal vector of the event if it was added, or |
240 // -1 if the event was not added. | 250 // -1 if the event was not added. |
241 // On end events, the return value of the begin event can be specified along | 251 // On end events, the return value of the begin event can be specified along |
242 // with a threshold in microseconds. If the elapsed time between begin and end | 252 // with a threshold in microseconds. If the elapsed time between begin and end |
(...skipping 13 matching lines...) Expand all Loading... | |
256 unsigned char flags); | 266 unsigned char flags); |
257 static void AddTraceEventEtw(char phase, | 267 static void AddTraceEventEtw(char phase, |
258 const char* name, | 268 const char* name, |
259 const void* id, | 269 const void* id, |
260 const char* extra); | 270 const char* extra); |
261 static void AddTraceEventEtw(char phase, | 271 static void AddTraceEventEtw(char phase, |
262 const char* name, | 272 const char* name, |
263 const void* id, | 273 const void* id, |
264 const std::string& extra); | 274 const std::string& extra); |
265 | 275 |
276 // After |num_occurrences| of given event have been seen on a particular | |
277 // process since tracing was enabled, a notification will be fired. The event | |
278 // count is not distributed across processes, so |num_occurrences| must occur | |
279 // on one process. The watch event is automatically cleared after the | |
280 // notification. |num_occurrences| must be greater than 0. | |
281 // NOTE: If |num_occurrences| events have already occurred, the notification | |
ccameron
2012/08/21 01:06:34
I have a preference for not supporting this semant
jbates
2012/08/23 22:45:28
This is important to catch the events that occur a
| |
282 // will fire during the call to SetWatchEvent. | |
283 void SetWatchEvent(const char* category_name, | |
284 const char* event_name, | |
285 int num_occurrences); | |
286 // Cancel the watch event. If tracing is enabled, this may race with the | |
287 // watch event notification firing. | |
288 void CancelWatchEvent(); | |
289 | |
266 int process_id() const { return process_id_; } | 290 int process_id() const { return process_id_; } |
267 | 291 |
268 // Exposed for unittesting: | 292 // Exposed for unittesting: |
269 | 293 |
270 // Allows deleting our singleton instance. | 294 // Allows deleting our singleton instance. |
271 static void DeleteForTesting(); | 295 static void DeleteForTesting(); |
272 | 296 |
273 // Allows resurrecting our singleton instance post-AtExit processing. | 297 // Allows resurrecting our singleton instance post-AtExit processing. |
274 static void Resurrect(); | 298 static void Resurrect(); |
275 | 299 |
276 // Allow tests to inspect TraceEvents. | 300 // Allow tests to inspect TraceEvents. |
277 size_t GetEventsSize() const { return logged_events_.size(); } | 301 size_t GetEventsSize() const { return logged_events_.size(); } |
278 const TraceEvent& GetEventAt(size_t index) const { | 302 const TraceEvent& GetEventAt(size_t index) const { |
279 DCHECK(index < logged_events_.size()); | 303 DCHECK(index < logged_events_.size()); |
280 return logged_events_[index]; | 304 return logged_events_[index]; |
281 } | 305 } |
282 | 306 |
283 void SetProcessID(int process_id); | 307 void SetProcessID(int process_id); |
284 | 308 |
285 private: | 309 private: |
286 // This allows constructor and destructor to be private and usable only | 310 // This allows constructor and destructor to be private and usable only |
287 // by the Singleton class. | 311 // by the Singleton class. |
288 friend struct StaticMemorySingletonTraits<TraceLog>; | 312 friend struct StaticMemorySingletonTraits<TraceLog>; |
289 | 313 |
314 // Helper class for managing notification_thread_count_ and running | |
315 // notification callbacks. | |
316 class NotificationHelper { | |
317 public: | |
318 inline NotificationHelper(TraceLog* trace_log); | |
319 inline ~NotificationHelper(); | |
320 | |
321 // Called only while TraceLog::lock_ is held. | |
322 inline void AddNotificationWhileLocked(int notification); | |
323 | |
324 // Called only while TraceLog::lock_ is NOT held. | |
325 inline void SendNotificationIfAny(); | |
326 | |
327 private: | |
328 TraceLog* trace_log_; | |
329 NotificationCallback callback_copy_; | |
330 int notification_; | |
331 }; | |
332 | |
290 TraceLog(); | 333 TraceLog(); |
291 ~TraceLog(); | 334 ~TraceLog(); |
292 const unsigned char* GetCategoryEnabledInternal(const char* name); | 335 const unsigned char* GetCategoryEnabledInternal(const char* name); |
293 void AddThreadNameMetadataEvents(); | 336 void AddThreadNameMetadataEvents(); |
294 void AddClockSyncMetadataEvents(); | 337 void AddClockSyncMetadataEvents(); |
295 | 338 |
296 // TODO(nduca): switch to per-thread trace buffers to reduce thread | 339 // TODO(nduca): switch to per-thread trace buffers to reduce thread |
297 // synchronization. | 340 // synchronization. |
298 Lock lock_; | 341 Lock lock_; |
299 bool enabled_; | 342 bool enabled_; |
300 OutputCallback output_callback_; | 343 base::ConditionVariable notification_condition_; |
301 BufferFullCallback buffer_full_callback_; | 344 NotificationCallback notification_callback_; |
ccameron
2012/08/21 01:06:34
I see no concurrency issues with this implementati
jbates
2012/08/23 22:45:28
As discussed, added comments around the Notificati
| |
345 // Number of threads that are have a copy of the notification callback. | |
346 int notification_thread_count_; | |
302 std::vector<TraceEvent> logged_events_; | 347 std::vector<TraceEvent> logged_events_; |
303 std::vector<std::string> included_categories_; | 348 std::vector<std::string> included_categories_; |
304 std::vector<std::string> excluded_categories_; | 349 std::vector<std::string> excluded_categories_; |
305 bool dispatching_to_observer_list_; | 350 bool dispatching_to_observer_list_; |
306 ObserverList<EnabledStateChangedObserver> enabled_state_observer_list_; | 351 ObserverList<EnabledStateChangedObserver> enabled_state_observer_list_; |
307 | 352 |
308 base::hash_map<int, std::string> thread_names_; | 353 base::hash_map<int, std::string> thread_names_; |
309 | 354 |
310 // XORed with TraceID to make it unlikely to collide with other processes. | 355 // XORed with TraceID to make it unlikely to collide with other processes. |
311 unsigned long long process_id_hash_; | 356 unsigned long long process_id_hash_; |
312 | 357 |
313 int process_id_; | 358 int process_id_; |
314 | 359 |
360 // Allow tests to wake up when certain events occur. | |
361 const unsigned char* watch_category_; | |
362 std::string watch_event_name_; | |
363 int watch_count_; | |
364 | |
315 DISALLOW_COPY_AND_ASSIGN(TraceLog); | 365 DISALLOW_COPY_AND_ASSIGN(TraceLog); |
316 }; | 366 }; |
317 | 367 |
318 } // namespace debug | 368 } // namespace debug |
319 } // namespace base | 369 } // namespace base |
320 | 370 |
321 #endif // BASE_DEBUG_TRACE_EVENT_IMPL_H_ | 371 #endif // BASE_DEBUG_TRACE_EVENT_IMPL_H_ |
OLD | NEW |