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 { | |
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 and from any thread. After calling |
218 // silently dropped. The callback must be thread safe. The string format is | 230 // SetNotificationCallback(NotificationCallback()) to clear the callback, it |
231 // is guaranteed that the old callback will no longer be called. Warning: it | |
jar (doing other things)
2012/08/29 22:38:19
How do you guarantee that the "old callback will n
jbates
2012/08/29 23:12:06
After SetNotificationCallback returns, the calling
jar (doing other things)
2012/08/29 23:35:45
Is the callback made under the protection of a loc
jbates
2012/08/30 00:55:14
As discussed, you were correct in suspecting this
| |
232 // is possible for the old callback to be called during a call to | |
233 // SetNotificationCallback. | |
234 typedef base::Callback<void(int)> NotificationCallback; | |
235 void SetNotificationCallback(const NotificationCallback& cb); | |
236 | |
237 // Flush all collected events to the given output callback. The callback will | |
238 // 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 | 239 // undefined. Use TraceResultBuffer to convert one or more trace strings to |
220 // JSON. | 240 // JSON. |
221 typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&)> | 241 typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&)> |
222 OutputCallback; | 242 OutputCallback; |
223 void SetOutputCallback(const OutputCallback& cb); | 243 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 | 244 |
234 // Called by TRACE_EVENT* macros, don't call this directly. | 245 // Called by TRACE_EVENT* macros, don't call this directly. |
235 static const unsigned char* GetCategoryEnabled(const char* name); | 246 static const unsigned char* GetCategoryEnabled(const char* name); |
236 static const char* GetCategoryName(const unsigned char* category_enabled); | 247 static const char* GetCategoryName(const unsigned char* category_enabled); |
237 | 248 |
238 // Called by TRACE_EVENT* macros, don't call this directly. | 249 // 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 | 250 // Returns the index in the internal vector of the event if it was added, or |
240 // -1 if the event was not added. | 251 // -1 if the event was not added. |
241 // On end events, the return value of the begin event can be specified along | 252 // 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 | 253 // with a threshold in microseconds. If the elapsed time between begin and end |
(...skipping 13 matching lines...) Expand all Loading... | |
256 unsigned char flags); | 267 unsigned char flags); |
257 static void AddTraceEventEtw(char phase, | 268 static void AddTraceEventEtw(char phase, |
258 const char* name, | 269 const char* name, |
259 const void* id, | 270 const void* id, |
260 const char* extra); | 271 const char* extra); |
261 static void AddTraceEventEtw(char phase, | 272 static void AddTraceEventEtw(char phase, |
262 const char* name, | 273 const char* name, |
263 const void* id, | 274 const void* id, |
264 const std::string& extra); | 275 const std::string& extra); |
265 | 276 |
277 // For every matching event, a notification will be fired. NOTE: the | |
278 // notification will fire for each matching event that has already occurred | |
279 // since tracing was started (including before tracing if the process was | |
280 // started with tracing turned on). | |
281 void SetWatchEvent(const std::string& category_name, | |
282 const std::string& event_name); | |
283 // Cancel the watch event. If tracing is enabled, this may race with the | |
284 // watch event notification firing. | |
285 void CancelWatchEvent(); | |
286 | |
266 int process_id() const { return process_id_; } | 287 int process_id() const { return process_id_; } |
267 | 288 |
268 // Exposed for unittesting: | 289 // Exposed for unittesting: |
269 | 290 |
270 // Allows deleting our singleton instance. | 291 // Allows deleting our singleton instance. |
271 static void DeleteForTesting(); | 292 static void DeleteForTesting(); |
272 | 293 |
273 // Allows resurrecting our singleton instance post-AtExit processing. | 294 // Allows resurrecting our singleton instance post-AtExit processing. |
274 static void Resurrect(); | 295 static void Resurrect(); |
275 | 296 |
276 // Allow tests to inspect TraceEvents. | 297 // Allow tests to inspect TraceEvents. |
277 size_t GetEventsSize() const { return logged_events_.size(); } | 298 size_t GetEventsSize() const { return logged_events_.size(); } |
278 const TraceEvent& GetEventAt(size_t index) const { | 299 const TraceEvent& GetEventAt(size_t index) const { |
279 DCHECK(index < logged_events_.size()); | 300 DCHECK(index < logged_events_.size()); |
280 return logged_events_[index]; | 301 return logged_events_[index]; |
281 } | 302 } |
282 | 303 |
283 void SetProcessID(int process_id); | 304 void SetProcessID(int process_id); |
284 | 305 |
285 private: | 306 private: |
286 // This allows constructor and destructor to be private and usable only | 307 // This allows constructor and destructor to be private and usable only |
287 // by the Singleton class. | 308 // by the Singleton class. |
288 friend struct StaticMemorySingletonTraits<TraceLog>; | 309 friend struct StaticMemorySingletonTraits<TraceLog>; |
289 | 310 |
311 // Helper class for managing notification_thread_count_ and running | |
312 // notification callbacks. This is very similar to a reader-writer lock, but | |
313 // shares the lock with TraceLog and manages the notification flags. | |
314 class NotificationHelper { | |
315 public: | |
316 inline NotificationHelper(TraceLog* trace_log); | |
jar (doing other things)
2012/08/29 22:38:19
nit: explicit.
jbates
2012/08/29 23:12:06
Done.
| |
317 inline ~NotificationHelper(); | |
318 | |
319 // Called only while TraceLog::lock_ is held. | |
320 inline void AddNotificationWhileLocked(int notification); | |
jar (doing other things)
2012/08/29 22:38:19
What is the distinction betwene "AddNotification"
jbates
2012/08/29 23:12:06
Updated comments.
| |
321 | |
322 // Called only while TraceLog::lock_ is NOT held. | |
323 inline void SendNotificationIfAny(); | |
324 | |
325 private: | |
326 TraceLog* trace_log_; | |
327 NotificationCallback callback_copy_; | |
328 int notification_; | |
329 }; | |
330 | |
290 TraceLog(); | 331 TraceLog(); |
291 ~TraceLog(); | 332 ~TraceLog(); |
292 const unsigned char* GetCategoryEnabledInternal(const char* name); | 333 const unsigned char* GetCategoryEnabledInternal(const char* name); |
293 void AddThreadNameMetadataEvents(); | 334 void AddThreadNameMetadataEvents(); |
294 void AddClockSyncMetadataEvents(); | 335 void AddClockSyncMetadataEvents(); |
295 | 336 |
296 // TODO(nduca): switch to per-thread trace buffers to reduce thread | 337 // TODO(nduca): switch to per-thread trace buffers to reduce thread |
297 // synchronization. | 338 // synchronization. |
298 Lock lock_; | 339 Lock lock_; |
jar (doing other things)
2012/08/29 22:38:19
Can you clarify what is protected by this lock?
jbates
2012/08/29 23:12:06
Done.
| |
299 bool enabled_; | 340 bool enabled_; |
300 OutputCallback output_callback_; | 341 base::ConditionVariable notification_condition_; |
301 BufferFullCallback buffer_full_callback_; | 342 NotificationCallback notification_callback_; |
343 // Number of threads that have a copy of the notification callback. | |
344 int notification_thread_count_; | |
302 std::vector<TraceEvent> logged_events_; | 345 std::vector<TraceEvent> logged_events_; |
303 std::vector<std::string> included_categories_; | 346 std::vector<std::string> included_categories_; |
304 std::vector<std::string> excluded_categories_; | 347 std::vector<std::string> excluded_categories_; |
305 bool dispatching_to_observer_list_; | 348 bool dispatching_to_observer_list_; |
306 ObserverList<EnabledStateChangedObserver> enabled_state_observer_list_; | 349 ObserverList<EnabledStateChangedObserver> enabled_state_observer_list_; |
307 | 350 |
308 base::hash_map<int, std::string> thread_names_; | 351 base::hash_map<int, std::string> thread_names_; |
309 | 352 |
310 // XORed with TraceID to make it unlikely to collide with other processes. | 353 // XORed with TraceID to make it unlikely to collide with other processes. |
311 unsigned long long process_id_hash_; | 354 unsigned long long process_id_hash_; |
312 | 355 |
313 int process_id_; | 356 int process_id_; |
314 | 357 |
358 // Allow tests to wake up when certain events occur. | |
359 const unsigned char* watch_category_; | |
360 std::string watch_event_name_; | |
361 | |
315 DISALLOW_COPY_AND_ASSIGN(TraceLog); | 362 DISALLOW_COPY_AND_ASSIGN(TraceLog); |
316 }; | 363 }; |
317 | 364 |
318 } // namespace debug | 365 } // namespace debug |
319 } // namespace base | 366 } // namespace base |
320 | 367 |
321 #endif // BASE_DEBUG_TRACE_EVENT_IMPL_H_ | 368 #endif // BASE_DEBUG_TRACE_EVENT_IMPL_H_ |
OLD | NEW |