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
3 // found in the LICENSE file.
6 #ifndef BASE_DEBUG_TRACE_EVENT_IMPL_H_
7 #define BASE_DEBUG_TRACE_EVENT_IMPL_H_
13 #include "base/atomicops.h"
14 #include "base/callback.h"
15 #include "base/containers/hash_tables.h"
16 #include "base/gtest_prod_util.h"
17 #include "base/memory/ref_counted_memory.h"
18 #include "base/memory/scoped_vector.h"
19 #include "base/observer_list.h"
20 #include "base/strings/string_util.h"
21 #include "base/synchronization/condition_variable.h"
22 #include "base/synchronization/lock.h"
23 #include "base/threading/thread.h"
24 #include "base/threading/thread_local.h"
25 #include "base/timer/timer.h"
27 // Older style trace macros with explicit id and extra data
28 // Only these macros result in publishing data to ETW as currently implemented.
29 #define TRACE_EVENT_BEGIN_ETW(name, id, extra) \
30 base::debug::TraceLog::AddTraceEventEtw( \
31 TRACE_EVENT_PHASE_BEGIN, \
32 name, reinterpret_cast<const void*>(id), extra)
34 #define TRACE_EVENT_END_ETW(name, id, extra) \
35 base::debug::TraceLog::AddTraceEventEtw( \
36 TRACE_EVENT_PHASE_END, \
37 name, reinterpret_cast<const void*>(id), extra)
39 #define TRACE_EVENT_INSTANT_ETW(name, id, extra) \
40 base::debug::TraceLog::AddTraceEventEtw( \
41 TRACE_EVENT_PHASE_INSTANT, \
42 name, reinterpret_cast<const void*>(id), extra)
44 template <typename Type>
45 struct DefaultSingletonTraits;
47 #if defined(COMPILER_GCC)
48 namespace BASE_HASH_NAMESPACE {
50 struct hash<base::MessageLoop*> {
51 std::size_t operator()(base::MessageLoop* value) const {
52 return reinterpret_cast<std::size_t>(value);
55 } // BASE_HASH_NAMESPACE
65 // For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided
66 // class must implement this interface.
67 class ConvertableToTraceFormat : public RefCounted<ConvertableToTraceFormat> {
69 // Append the class info to the provided |out| string. The appended
70 // data must be a valid JSON object. Strings must be properly quoted, and
71 // escaped. There is no processing applied to the content after it is
73 virtual void AppendAsTraceFormat(std::string* out) const = 0;
76 virtual ~ConvertableToTraceFormat() {}
79 friend class RefCounted<ConvertableToTraceFormat>;
82 struct TraceEventHandle {
88 const int kTraceMaxNumArgs = 2;
90 class BASE_EXPORT TraceEvent {
94 unsigned long long as_uint;
97 const void* as_pointer;
98 const char* as_string;
104 // We don't need to copy TraceEvent except when TraceEventBuffer is cloned.
105 // Use explicit copy method to avoid accidentally misuse of copy.
106 void CopyFrom(const TraceEvent& other);
111 TimeTicks thread_timestamp,
113 const unsigned char* category_group_enabled,
115 unsigned long long id,
117 const char** arg_names,
118 const unsigned char* arg_types,
119 const unsigned long long* arg_values,
120 const scoped_refptr<ConvertableToTraceFormat>* convertable_values,
121 unsigned char flags);
125 void UpdateDuration(const TimeTicks& now);
127 // Serialize event data to JSON
128 static void AppendEventsAsJSON(const std::vector<TraceEvent>& events,
132 void AppendAsJSON(std::string* out) const;
133 void AppendPrettyPrinted(std::ostringstream* out) const;
135 static void AppendValueAsJSON(unsigned char type,
139 TimeTicks timestamp() const { return timestamp_; }
140 TimeTicks thread_timestamp() const { return thread_timestamp_; }
141 char phase() const { return phase_; }
142 int thread_id() const { return thread_id_; }
143 TimeDelta duration() const { return duration_; }
144 unsigned long long id() const { return id_; }
145 unsigned char flags() const { return flags_; }
147 // Exposed for unittesting:
149 const base::RefCountedString* parameter_copy_storage() const {
150 return parameter_copy_storage_.get();
153 const unsigned char* category_group_enabled() const {
154 return category_group_enabled_;
157 const char* name() const { return name_; }
159 #if defined(OS_ANDROID)
164 // Note: these are ordered by size (largest first) for optimal packing.
165 TimeTicks timestamp_;
166 TimeTicks thread_timestamp_;
168 // id_ can be used to store phase-specific data.
169 unsigned long long id_;
170 TraceValue arg_values_[kTraceMaxNumArgs];
171 const char* arg_names_[kTraceMaxNumArgs];
172 scoped_refptr<ConvertableToTraceFormat> convertable_values_[kTraceMaxNumArgs];
173 const unsigned char* category_group_enabled_;
175 scoped_refptr<base::RefCountedString> parameter_copy_storage_;
178 unsigned char flags_;
179 unsigned char arg_types_[kTraceMaxNumArgs];
181 DISALLOW_COPY_AND_ASSIGN(TraceEvent);
184 // TraceBufferChunk is the basic unit of TraceBuffer.
185 class BASE_EXPORT TraceBufferChunk {
187 TraceBufferChunk(uint32 seq)
192 void Reset(uint32 new_seq);
193 TraceEvent* AddTraceEvent(size_t* event_index);
194 bool IsFull() const { return next_free_ == kTraceBufferChunkSize; }
196 uint32 seq() const { return seq_; }
197 size_t capacity() const { return kTraceBufferChunkSize; }
198 size_t size() const { return next_free_; }
200 TraceEvent* GetEventAt(size_t index) {
201 DCHECK(index < size());
202 return &chunk_[index];
204 const TraceEvent* GetEventAt(size_t index) const {
205 DCHECK(index < size());
206 return &chunk_[index];
209 scoped_ptr<TraceBufferChunk> Clone() const;
211 static const size_t kTraceBufferChunkSize = 64;
215 TraceEvent chunk_[kTraceBufferChunkSize];
219 // TraceBuffer holds the events as they are collected.
220 class BASE_EXPORT TraceBuffer {
222 virtual ~TraceBuffer() {}
224 virtual scoped_ptr<TraceBufferChunk> GetChunk(size_t *index) = 0;
225 virtual void ReturnChunk(size_t index,
226 scoped_ptr<TraceBufferChunk> chunk) = 0;
228 virtual bool IsFull() const = 0;
229 virtual size_t Size() const = 0;
230 virtual size_t Capacity() const = 0;
231 virtual TraceEvent* GetEventByHandle(TraceEventHandle handle) = 0;
233 // For iteration. Each TraceBuffer can only be iterated once.
234 virtual const TraceBufferChunk* NextChunk() = 0;
236 virtual scoped_ptr<TraceBuffer> CloneForIteration() const = 0;
239 // TraceResultBuffer collects and converts trace fragments returned by TraceLog
241 class BASE_EXPORT TraceResultBuffer {
243 typedef base::Callback<void(const std::string&)> OutputCallback;
245 // If you don't need to stream JSON chunks out efficiently, and just want to
246 // get a complete JSON string after calling Finish, use this struct to collect
247 // JSON trace output.
248 struct BASE_EXPORT SimpleOutput {
249 OutputCallback GetCallback();
250 void Append(const std::string& json_string);
252 // Do what you want with the json_output_ string after calling
253 // TraceResultBuffer::Finish.
254 std::string json_output;
258 ~TraceResultBuffer();
260 // Set callback. The callback will be called during Start with the initial
261 // JSON output and during AddFragment and Finish with following JSON output
262 // chunks. The callback target must live past the last calls to
263 // TraceResultBuffer::Start/AddFragment/Finish.
264 void SetOutputCallback(const OutputCallback& json_chunk_callback);
266 // Start JSON output. This resets all internal state, so you can reuse
267 // the TraceResultBuffer by calling Start.
270 // Call AddFragment 0 or more times to add trace fragments from TraceLog.
271 void AddFragment(const std::string& trace_fragment);
273 // When all fragments have been added, call Finish to complete the JSON
278 OutputCallback output_callback_;
282 class BASE_EXPORT CategoryFilter {
284 // The default category filter, used when none is provided.
285 // Allows all categories through, except if they end in the suffix 'Debug' or
287 static const char* kDefaultCategoryFilterString;
289 // |filter_string| is a comma-delimited list of category wildcards.
290 // A category can have an optional '-' prefix to make it an excluded category.
291 // All the same rules apply above, so for example, having both included and
292 // excluded categories in the same list would not be supported.
294 // Example: CategoryFilter"test_MyTest*");
295 // Example: CategoryFilter("test_MyTest*,test_OtherStuff");
296 // Example: CategoryFilter("-excluded_category1,-excluded_category2");
297 // Example: CategoryFilter("-*,webkit"); would disable everything but webkit.
298 // Example: CategoryFilter("-webkit"); would enable everything but webkit.
299 explicit CategoryFilter(const std::string& filter_string);
301 CategoryFilter(const CategoryFilter& cf);
305 CategoryFilter& operator=(const CategoryFilter& rhs);
307 // Writes the string representation of the CategoryFilter. This is a comma
308 // separated string, similar in nature to the one used to determine
309 // enabled/disabled category patterns, except here there is an arbitrary
310 // order, included categories go first, then excluded categories. Excluded
311 // categories are distinguished from included categories by the prefix '-'.
312 std::string ToString() const;
314 // Determines whether category group would be enabled or
315 // disabled by this category filter.
316 bool IsCategoryGroupEnabled(const char* category_group) const;
318 // Merges nested_filter with the current CategoryFilter
319 void Merge(const CategoryFilter& nested_filter);
321 // Clears both included/excluded pattern lists. This would be equivalent to
322 // creating a CategoryFilter with an empty string, through the constructor.
323 // i.e: CategoryFilter("").
325 // When using an empty filter, all categories are considered included as we
326 // are not excluding anything.
330 FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, CategoryFilter);
332 static bool IsEmptyOrContainsLeadingOrTrailingWhitespace(
333 const std::string& str);
335 typedef std::vector<std::string> StringList;
337 void Initialize(const std::string& filter_string);
338 void WriteString(const StringList& values,
340 bool included) const;
341 bool HasIncludedPatterns() const;
343 bool DoesCategoryGroupContainCategory(const char* category_group,
344 const char* category) const;
346 StringList included_;
347 StringList disabled_;
348 StringList excluded_;
351 class TraceSamplingThread;
353 class BASE_EXPORT TraceLog {
355 // Notification is a mask of one or more of the following events.
357 // The trace buffer does not flush dynamically, so when it fills up,
358 // subsequent trace events will be dropped. This callback is generated when
359 // the trace buffer is full. The callback must be thread safe.
360 TRACE_BUFFER_FULL = 1 << 0,
361 // A subscribed trace-event occurred.
362 EVENT_WATCH_NOTIFICATION = 1 << 1
365 // Options determines how the trace buffer stores data.
367 // Record until the trace buffer is full.
368 RECORD_UNTIL_FULL = 1 << 0,
370 // Record until the user ends the trace. The trace buffer is a fixed size
371 // and we use it as a ring buffer during recording.
372 RECORD_CONTINUOUSLY = 1 << 1,
374 // Enable the sampling profiler in the recording mode.
375 ENABLE_SAMPLING = 1 << 2,
377 // Enable the sampling profiler in the monitoring mode.
378 MONITOR_SAMPLING = 1 << 3,
380 // Echo to console. Events are discarded.
381 ECHO_TO_CONSOLE = 1 << 4,
384 static TraceLog* GetInstance();
386 // Convert the given string to trace options. Defaults to RECORD_UNTIL_FULL if
387 // the string does not provide valid options.
388 static Options TraceOptionsFromString(const std::string& str);
390 // Get set of known category groups. This can change as new code paths are
391 // reached. The known category groups are inserted into |category_groups|.
392 void GetKnownCategoryGroups(std::vector<std::string>* category_groups);
394 // Retrieves the current CategoryFilter.
395 const CategoryFilter& GetCurrentCategoryFilter();
397 Options trace_options() const {
398 return static_cast<Options>(subtle::NoBarrier_Load(&trace_options_));
401 // Enables tracing. See CategoryFilter comments for details
402 // on how to control what categories will be traced.
403 void SetEnabled(const CategoryFilter& category_filter, Options options);
405 // Disables tracing for all categories.
407 bool IsEnabled() { return !!enable_count_; }
409 // The number of times we have begun recording traces. If tracing is off,
410 // returns -1. If tracing is on, then it returns the number of times we have
411 // recorded a trace. By watching for this number to increment, you can
412 // passively discover when a new trace has begun. This is then used to
413 // implement the TRACE_EVENT_IS_NEW_TRACE() primitive.
414 int GetNumTracesRecorded();
416 #if defined(OS_ANDROID)
419 void AddClockSyncMetadataEvent();
422 // Enabled state listeners give a callback when tracing is enabled or
423 // disabled. This can be used to tie into other library's tracing systems
425 class EnabledStateObserver {
427 // Called just after the tracing system becomes enabled, outside of the
428 // |lock_|. TraceLog::IsEnabled() is true at this point.
429 virtual void OnTraceLogEnabled() = 0;
431 // Called just after the tracing system disables, outside of the |lock_|.
432 // TraceLog::IsEnabled() is false at this point.
433 virtual void OnTraceLogDisabled() = 0;
435 void AddEnabledStateObserver(EnabledStateObserver* listener);
436 void RemoveEnabledStateObserver(EnabledStateObserver* listener);
437 bool HasEnabledStateObserver(EnabledStateObserver* listener) const;
439 float GetBufferPercentFull() const;
441 // Set the thread-safe notification callback. The callback can occur at any
442 // time and from any thread. WARNING: It is possible for the previously set
443 // callback to be called during OR AFTER a call to SetNotificationCallback.
444 // Therefore, the target of the callback must either be a global function,
445 // ref-counted object or a LazyInstance with Leaky traits (or equivalent).
446 typedef base::Callback<void(int)> NotificationCallback;
447 void SetNotificationCallback(const NotificationCallback& cb);
449 // Not using base::Callback because of its limited by 7 parameters.
450 // Also, using primitive type allows directly passing callback from WebCore.
451 // WARNING: It is possible for the previously set callback to be called
452 // after a call to SetEventCallback() that replaces or clears the callback.
453 // This callback may be invoked on any thread.
454 // TODO(wangxianzhu): For now for TRACE_EVENT_PHASE_COMPLETE events, the
455 // client will still receive pairs of TRACE_EVENT_PHASE_BEGIN and
456 // TRACE_EVENT_PHASE_END events. Should send TRACE_EVENT_PHASE_COMPLETE
457 // directly to clients if it is beneficial and feasible.
458 typedef void (*EventCallback)(TimeTicks timestamp,
460 const unsigned char* category_group_enabled,
462 unsigned long long id,
464 const char* const arg_names[],
465 const unsigned char arg_types[],
466 const unsigned long long arg_values[],
467 unsigned char flags);
468 void SetEventCallback(EventCallback cb);
470 // Flush all collected events to the given output callback. The callback will
471 // be called one or more times either synchronously or asynchronously from
472 // the current thread with IPC-bite-size chunks. The string format is
473 // undefined. Use TraceResultBuffer to convert one or more trace strings to
474 // JSON. The callback can be null if the caller doesn't want any data.
475 // Due to the implementation of thread-local buffers, flush can't be
476 // done when tracing is enabled. If called when tracing is enabled, the
477 // callback will be called directly with (empty_string, false) to indicate
478 // the end of this unsuccessful flush.
479 typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&,
480 bool has_more_events)> OutputCallback;
481 void Flush(const OutputCallback& cb);
482 void FlushButLeaveBufferIntact(const OutputCallback& flush_output_callback);
484 // Called by TRACE_EVENT* macros, don't call this directly.
485 // The name parameter is a category group for example:
486 // TRACE_EVENT0("renderer,webkit", "WebViewImpl::HandleInputEvent")
487 static const unsigned char* GetCategoryGroupEnabled(const char* name);
488 static const char* GetCategoryGroupName(
489 const unsigned char* category_group_enabled);
491 // Called by TRACE_EVENT* macros, don't call this directly.
492 // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied
493 // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above.
494 TraceEventHandle AddTraceEvent(
496 const unsigned char* category_group_enabled,
498 unsigned long long id,
500 const char** arg_names,
501 const unsigned char* arg_types,
502 const unsigned long long* arg_values,
503 const scoped_refptr<ConvertableToTraceFormat>* convertable_values,
504 unsigned char flags);
505 TraceEventHandle AddTraceEventWithThreadIdAndTimestamp(
507 const unsigned char* category_group_enabled,
509 unsigned long long id,
511 const TimeTicks& timestamp,
513 const char** arg_names,
514 const unsigned char* arg_types,
515 const unsigned long long* arg_values,
516 const scoped_refptr<ConvertableToTraceFormat>* convertable_values,
517 unsigned char flags);
518 static void AddTraceEventEtw(char phase,
519 const char* category_group,
522 static void AddTraceEventEtw(char phase,
523 const char* category_group,
525 const std::string& extra);
527 void UpdateTraceEventDuration(TraceEventHandle handle);
529 // For every matching event, a notification will be fired. NOTE: the
530 // notification will fire for each matching event that has already occurred
531 // since tracing was started (including before tracing if the process was
532 // started with tracing turned on).
533 void SetWatchEvent(const std::string& category_name,
534 const std::string& event_name);
535 // Cancel the watch event. If tracing is enabled, this may race with the
536 // watch event notification firing.
537 void CancelWatchEvent();
539 int process_id() const { return process_id_; }
541 // Exposed for unittesting:
543 void InstallWaitableEventForSamplingTesting(WaitableEvent* waitable_event);
545 // Allows deleting our singleton instance.
546 static void DeleteForTesting();
548 // Allow tests to inspect TraceEvents.
549 size_t GetEventsSize() const { return logged_events_->Size(); }
550 TraceEvent* GetEventByHandle(TraceEventHandle handle);
552 void SetProcessID(int process_id);
554 // Process sort indices, if set, override the order of a process will appear
555 // relative to other processes in the trace viewer. Processes are sorted first
556 // on their sort index, ascending, then by their name, and then tid.
557 void SetProcessSortIndex(int sort_index);
559 // Sets the name of the process.
560 void SetProcessName(const std::string& process_name);
562 // Processes can have labels in addition to their names. Use labels, for
563 // instance, to list out the web page titles that a process is handling.
564 void UpdateProcessLabel(int label_id, const std::string& current_label);
565 void RemoveProcessLabel(int label_id);
567 // Thread sort indices, if set, override the order of a thread will appear
568 // within its process in the trace viewer. Threads are sorted first on their
569 // sort index, ascending, then by their name, and then tid.
570 void SetThreadSortIndex(PlatformThreadId , int sort_index);
572 // Allow setting an offset between the current TimeTicks time and the time
573 // that should be reported.
574 void SetTimeOffset(TimeDelta offset);
576 size_t GetObserverCountForTest() const;
578 // Call this method if the current thread may block the message loop to
579 // prevent the thread from using the thread-local buffer because the thread
580 // may not handle the flush request in time causing lost of unflushed events.
581 void SetCurrentThreadBlocksMessageLoop();
584 FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture,
585 TraceBufferRingBufferGetReturnChunk);
586 FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture,
587 TraceBufferRingBufferHalfIteration);
588 FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture,
589 TraceBufferRingBufferFullIteration);
591 // This allows constructor and destructor to be private and usable only
592 // by the Singleton class.
593 friend struct DefaultSingletonTraits<TraceLog>;
595 // Enable/disable each category group based on the current enable_count_
596 // and category_filter_. Disable the category group if enabled_count_ is 0, or
597 // if the category group contains a category that matches an included category
598 // pattern, that category group will be enabled.
599 // On Android, ATRACE_ENABLED flag will be applied if atrace is started.
600 void UpdateCategoryGroupEnabledFlags();
601 void UpdateCategoryGroupEnabledFlag(int category_index);
603 // Helper class for managing notification_thread_count_ and running
604 // notification callbacks. This is very similar to a reader-writer lock, but
605 // shares the lock with TraceLog and manages the notification flags.
606 class NotificationHelper {
608 inline explicit NotificationHelper(TraceLog* trace_log);
609 inline ~NotificationHelper();
611 // Called only while TraceLog::lock_ is held. This ORs the given
612 // notification with any existing notifications.
613 inline void AddNotificationWhileLocked(int notification);
615 // Called only while TraceLog::lock_ is NOT held. If there are any pending
616 // notifications from previous calls to AddNotificationWhileLocked, this
617 // will call the NotificationCallback.
618 inline void SendNotificationIfAny();
621 TraceLog* trace_log_;
622 NotificationCallback callback_copy_;
626 class ThreadLocalEventBuffer;
627 class OptionalAutoLock;
631 const unsigned char* GetCategoryGroupEnabledInternal(const char* name);
632 void AddMetadataEventsWhileLocked();
634 TraceBuffer* trace_buffer() const { return logged_events_.get(); }
635 TraceBuffer* CreateTraceBuffer();
637 void OutputEventToConsoleWhileLocked(unsigned char phase,
638 const TimeTicks& timestamp,
639 TraceEvent* trace_event);
641 TraceEvent* AddEventToThreadSharedChunkWhileLocked(
642 NotificationHelper* notifier, TraceEventHandle* handle);
643 void CheckIfBufferIsFullWhileLocked(NotificationHelper* notifier);
645 TraceEvent* GetEventByHandleInternal(TraceEventHandle handle,
646 OptionalAutoLock* lock);
648 // |generation| is used in the following callbacks to check if the callback
649 // is called for the flush of the current |logged_events_|.
650 void FlushCurrentThread(int generation);
651 void ConvertTraceEventsToTraceFormat(scoped_ptr<TraceBuffer> logged_events,
652 const TraceLog::OutputCallback& flush_output_callback);
653 void FinishFlush(int generation);
654 void OnFlushTimeout(int generation);
656 int generation() const {
657 return static_cast<int>(subtle::NoBarrier_Load(&generation_));
659 bool CheckGeneration(int generation) const {
660 return generation == this->generation();
662 int NextGeneration() {
663 return static_cast<int>(subtle::NoBarrier_AtomicIncrement(&generation_, 1));
666 TimeTicks OffsetNow() const {
667 return OffsetTimestamp(TimeTicks::NowFromSystemTraceTime());
669 TimeTicks OffsetTimestamp(const TimeTicks& timestamp) const {
670 return timestamp - time_offset_;
673 // This lock protects TraceLog member accesses from arbitrary threads.
677 int num_traces_recorded_;
678 subtle::AtomicWord /* bool */ buffer_is_full_;
679 NotificationCallback notification_callback_;
680 scoped_ptr<TraceBuffer> logged_events_;
681 subtle::AtomicWord /* EventCallback */ event_callback_;
682 bool dispatching_to_observer_list_;
683 std::vector<EnabledStateObserver*> enabled_state_observer_list_;
685 std::string process_name_;
686 base::hash_map<int, std::string> process_labels_;
687 int process_sort_index_;
688 base::hash_map<int, int> thread_sort_indices_;
689 base::hash_map<int, std::string> thread_names_;
691 // The following two maps are used only when ECHO_TO_CONSOLE.
692 base::hash_map<int, std::stack<TimeTicks> > thread_event_start_times_;
693 base::hash_map<std::string, int> thread_colors_;
695 // XORed with TraceID to make it unlikely to collide with other processes.
696 unsigned long long process_id_hash_;
700 TimeDelta time_offset_;
702 // Allow tests to wake up when certain events occur.
703 subtle::AtomicWord /* const unsigned char* */ watch_category_;
704 std::string watch_event_name_;
706 subtle::AtomicWord /* Options */ trace_options_;
708 // Sampling thread handles.
709 scoped_ptr<TraceSamplingThread> sampling_thread_;
710 PlatformThreadHandle sampling_thread_handle_;
712 CategoryFilter category_filter_;
714 ThreadLocalPointer<ThreadLocalEventBuffer> thread_local_event_buffer_;
715 ThreadLocalBoolean thread_blocks_message_loop_;
717 // Contains the message loops of threads that have had at least one event
718 // added into the local event buffer. Not using MessageLoopProxy because we
719 // need to know the life time of the message loops.
720 hash_set<MessageLoop*> thread_message_loops_;
722 // For events which can't be added into the thread local buffer, e.g. events
723 // from threads without a message loop.
724 scoped_ptr<TraceBufferChunk> thread_shared_chunk_;
725 size_t thread_shared_chunk_index_;
727 // Set when asynchronous Flush is in progress.
728 OutputCallback flush_output_callback_;
729 scoped_refptr<MessageLoopProxy> flush_message_loop_proxy_;
730 subtle::AtomicWord generation_;
732 DISALLOW_COPY_AND_ASSIGN(TraceLog);
738 #endif // BASE_DEBUG_TRACE_EVENT_IMPL_H_