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 #include "base/debug/trace_event_impl.h" | 5 #include "base/debug/trace_event_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/debug/leak_annotations.h" | 10 #include "base/debug/leak_annotations.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 BASE_EXPORT TRACE_EVENT_API_ATOMIC_WORD g_trace_state1; | 45 BASE_EXPORT TRACE_EVENT_API_ATOMIC_WORD g_trace_state1; |
46 BASE_EXPORT TRACE_EVENT_API_ATOMIC_WORD g_trace_state2; | 46 BASE_EXPORT TRACE_EVENT_API_ATOMIC_WORD g_trace_state2; |
47 | 47 |
48 namespace base { | 48 namespace base { |
49 namespace debug { | 49 namespace debug { |
50 | 50 |
51 // Controls the number of trace events we will buffer in-memory | 51 // Controls the number of trace events we will buffer in-memory |
52 // before throwing them away. | 52 // before throwing them away. |
53 const size_t kTraceEventBufferSize = 500000; | 53 const size_t kTraceEventBufferSize = 500000; |
54 const size_t kTraceEventBatchSize = 1000; | 54 const size_t kTraceEventBatchSize = 1000; |
| 55 const size_t kTraceEventInitialBufferSize = 1024; |
55 | 56 |
56 #define TRACE_EVENT_MAX_CATEGORIES 100 | 57 #define TRACE_EVENT_MAX_CATEGORIES 100 |
57 | 58 |
58 namespace { | 59 namespace { |
59 | 60 |
60 // Parallel arrays g_categories and g_category_enabled are separate so that | 61 // Parallel arrays g_categories and g_category_enabled are separate so that |
61 // a pointer to a member of g_category_enabled can be easily converted to an | 62 // a pointer to a member of g_category_enabled can be easily converted to an |
62 // index into g_categories. This allows macros to deal only with char enabled | 63 // index into g_categories. This allows macros to deal only with char enabled |
63 // pointers from g_category_enabled, and we can convert internally to determine | 64 // pointers from g_category_enabled, and we can convert internally to determine |
64 // the category name from the char enabled pointer. | 65 // the category name from the char enabled pointer. |
65 const char* g_categories[TRACE_EVENT_MAX_CATEGORIES] = { | 66 const char* g_categories[TRACE_EVENT_MAX_CATEGORIES] = { |
66 "tracing already shutdown", | 67 "tracing already shutdown", |
67 "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES", | 68 "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES", |
68 "__metadata", | 69 "__metadata", |
69 }; | 70 }; |
| 71 |
70 // The enabled flag is char instead of bool so that the API can be used from C. | 72 // The enabled flag is char instead of bool so that the API can be used from C. |
71 unsigned char g_category_enabled[TRACE_EVENT_MAX_CATEGORIES] = { 0 }; | 73 unsigned char g_category_enabled[TRACE_EVENT_MAX_CATEGORIES] = { 0 }; |
72 const int g_category_already_shutdown = 0; | 74 const int g_category_already_shutdown = 0; |
73 const int g_category_categories_exhausted = 1; | 75 const int g_category_categories_exhausted = 1; |
74 const int g_category_metadata = 2; | 76 const int g_category_metadata = 2; |
75 int g_category_index = 3; // skip initial 3 categories | 77 int g_category_index = 3; // skip initial 3 categories |
76 | 78 |
77 // The name of the current thread. This is used to decide if the current | 79 // The name of the current thread. This is used to decide if the current |
78 // thread name has changed. We combine all the seen thread names into the | 80 // thread name has changed. We combine all the seen thread names into the |
79 // output name for the thread. | 81 // output name for the thread. |
80 LazyInstance<ThreadLocalPointer<const char> >::Leaky | 82 LazyInstance<ThreadLocalPointer<const char> >::Leaky |
81 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; | 83 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; |
82 | 84 |
83 const char kRecordUntilFull[] = "record-until-full"; | 85 const char kRecordUntilFull[] = "record-until-full"; |
| 86 const char kRecordContinuously[] = "record-continuously"; |
| 87 |
| 88 size_t NextIndex(size_t index) { |
| 89 index++; |
| 90 if (index >= kTraceEventBufferSize) |
| 91 index = 0; |
| 92 return index; |
| 93 } |
84 | 94 |
85 } // namespace | 95 } // namespace |
86 | 96 |
| 97 class TraceBufferRingBuffer : public TraceBuffer { |
| 98 public: |
| 99 TraceBufferRingBuffer() |
| 100 : unused_event_index_(0), |
| 101 oldest_event_index_(0) { |
| 102 logged_events_.reserve(kTraceEventInitialBufferSize); |
| 103 } |
| 104 |
| 105 ~TraceBufferRingBuffer() {} |
| 106 |
| 107 void AddEvent(const TraceEvent& event) OVERRIDE { |
| 108 if (unused_event_index_ < Size()) |
| 109 logged_events_[unused_event_index_] = event; |
| 110 else |
| 111 logged_events_.push_back(event); |
| 112 |
| 113 unused_event_index_ = NextIndex(unused_event_index_); |
| 114 if (unused_event_index_ == oldest_event_index_) { |
| 115 oldest_event_index_ = NextIndex(oldest_event_index_); |
| 116 } |
| 117 } |
| 118 |
| 119 bool HasMoreEvents() const OVERRIDE { |
| 120 return oldest_event_index_ != unused_event_index_; |
| 121 } |
| 122 |
| 123 const TraceEvent& NextEvent() OVERRIDE { |
| 124 DCHECK(HasMoreEvents()); |
| 125 |
| 126 size_t next = oldest_event_index_; |
| 127 oldest_event_index_ = NextIndex(oldest_event_index_); |
| 128 return GetEventAt(next); |
| 129 } |
| 130 |
| 131 bool IsFull() const OVERRIDE { |
| 132 return false; |
| 133 } |
| 134 |
| 135 size_t CountEnabledByName(const unsigned char* category, |
| 136 const std::string& event_name) const OVERRIDE { |
| 137 size_t notify_count = 0; |
| 138 size_t index = oldest_event_index_; |
| 139 while (index != unused_event_index_) { |
| 140 const TraceEvent& event = GetEventAt(index); |
| 141 if (category == event.category_enabled() && |
| 142 strcmp(event_name.c_str(), event.name()) == 0) { |
| 143 ++notify_count; |
| 144 } |
| 145 index = NextIndex(index); |
| 146 } |
| 147 return notify_count; |
| 148 } |
| 149 |
| 150 const TraceEvent& GetEventAt(size_t index) const OVERRIDE { |
| 151 DCHECK(index < logged_events_.size()); |
| 152 return logged_events_[index]; |
| 153 } |
| 154 |
| 155 size_t Size() const OVERRIDE { |
| 156 return logged_events_.size(); |
| 157 } |
| 158 |
| 159 private: |
| 160 size_t unused_event_index_; |
| 161 size_t oldest_event_index_; |
| 162 std::vector<TraceEvent> logged_events_; |
| 163 |
| 164 DISALLOW_COPY_AND_ASSIGN(TraceBufferRingBuffer); |
| 165 }; |
| 166 |
| 167 class TraceBufferVector : public TraceBuffer { |
| 168 public: |
| 169 TraceBufferVector() : current_iteration_index_(0) { |
| 170 logged_events_.reserve(kTraceEventInitialBufferSize); |
| 171 } |
| 172 |
| 173 ~TraceBufferVector() { |
| 174 } |
| 175 |
| 176 void AddEvent(const TraceEvent& event) OVERRIDE { |
| 177 // Note, we have two callers which need to be handled. The first is |
| 178 // AddTraceEventWithThreadIdAndTimestamp() which checks Size() and does an |
| 179 // early exit if full. The second is AddThreadNameMetadataEvents(). |
| 180 // We can not DECHECK(!IsFull()) because we have to add the metadata |
| 181 // events even if the buffer is full. |
| 182 logged_events_.push_back(event); |
| 183 } |
| 184 |
| 185 bool HasMoreEvents() const OVERRIDE { |
| 186 return current_iteration_index_ < Size(); |
| 187 } |
| 188 |
| 189 const TraceEvent& NextEvent() OVERRIDE { |
| 190 DCHECK(HasMoreEvents()); |
| 191 return GetEventAt(current_iteration_index_++); |
| 192 } |
| 193 |
| 194 bool IsFull() const OVERRIDE { |
| 195 return Size() >= kTraceEventBufferSize; |
| 196 } |
| 197 |
| 198 size_t CountEnabledByName(const unsigned char* category, |
| 199 const std::string& event_name) const OVERRIDE { |
| 200 size_t notify_count = 0; |
| 201 for (size_t i = 0; i < Size(); i++) { |
| 202 const TraceEvent& event = GetEventAt(i); |
| 203 if (category == event.category_enabled() && |
| 204 strcmp(event_name.c_str(), event.name()) == 0) { |
| 205 ++notify_count; |
| 206 } |
| 207 } |
| 208 return notify_count; |
| 209 } |
| 210 |
| 211 const TraceEvent& GetEventAt(size_t index) const OVERRIDE { |
| 212 DCHECK(index < logged_events_.size()); |
| 213 return logged_events_[index]; |
| 214 } |
| 215 |
| 216 size_t Size() const OVERRIDE { |
| 217 return logged_events_.size(); |
| 218 } |
| 219 |
| 220 private: |
| 221 size_t current_iteration_index_; |
| 222 std::vector<TraceEvent> logged_events_; |
| 223 |
| 224 DISALLOW_COPY_AND_ASSIGN(TraceBufferVector); |
| 225 }; |
| 226 |
87 //////////////////////////////////////////////////////////////////////////////// | 227 //////////////////////////////////////////////////////////////////////////////// |
88 // | 228 // |
89 // TraceEvent | 229 // TraceEvent |
90 // | 230 // |
91 //////////////////////////////////////////////////////////////////////////////// | 231 //////////////////////////////////////////////////////////////////////////////// |
92 | 232 |
93 namespace { | 233 namespace { |
94 | 234 |
95 size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; } | 235 size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; } |
96 | 236 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 start_pos += 2; | 371 start_pos += 2; |
232 } | 372 } |
233 *out += "\""; | 373 *out += "\""; |
234 break; | 374 break; |
235 default: | 375 default: |
236 NOTREACHED() << "Don't know how to print this value"; | 376 NOTREACHED() << "Don't know how to print this value"; |
237 break; | 377 break; |
238 } | 378 } |
239 } | 379 } |
240 | 380 |
241 void TraceEvent::AppendEventsAsJSON(const std::vector<TraceEvent>& events, | |
242 size_t start, | |
243 size_t count, | |
244 std::string* out) { | |
245 for (size_t i = 0; i < count && start + i < events.size(); ++i) { | |
246 if (i > 0) | |
247 *out += ","; | |
248 events[i + start].AppendAsJSON(out); | |
249 } | |
250 } | |
251 | |
252 void TraceEvent::AppendAsJSON(std::string* out) const { | 381 void TraceEvent::AppendAsJSON(std::string* out) const { |
253 int64 time_int64 = timestamp_.ToInternalValue(); | 382 int64 time_int64 = timestamp_.ToInternalValue(); |
254 int process_id = TraceLog::GetInstance()->process_id(); | 383 int process_id = TraceLog::GetInstance()->process_id(); |
255 // Category name checked at category creation time. | 384 // Category name checked at category creation time. |
256 DCHECK(!strchr(name_, '"')); | 385 DCHECK(!strchr(name_, '"')); |
257 StringAppendF(out, | 386 StringAppendF(out, |
258 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," | 387 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," |
259 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{", | 388 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{", |
260 TraceLog::GetCategoryName(category_enabled_), | 389 TraceLog::GetCategoryName(category_enabled_), |
261 process_id, | 390 process_id, |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 // content/browser/devtools/devtools_tracing_handler:TraceOptionsFromString | 633 // content/browser/devtools/devtools_tracing_handler:TraceOptionsFromString |
505 TraceLog::Options TraceLog::TraceOptionsFromString(const std::string& options) { | 634 TraceLog::Options TraceLog::TraceOptionsFromString(const std::string& options) { |
506 std::vector<std::string> split; | 635 std::vector<std::string> split; |
507 base::SplitString(options, ',', &split); | 636 base::SplitString(options, ',', &split); |
508 int ret = 0; | 637 int ret = 0; |
509 for (std::vector<std::string>::iterator iter = split.begin(); | 638 for (std::vector<std::string>::iterator iter = split.begin(); |
510 iter != split.end(); | 639 iter != split.end(); |
511 ++iter) { | 640 ++iter) { |
512 if (*iter == kRecordUntilFull) { | 641 if (*iter == kRecordUntilFull) { |
513 ret |= RECORD_UNTIL_FULL; | 642 ret |= RECORD_UNTIL_FULL; |
| 643 } else if (*iter == kRecordContinuously) { |
| 644 ret |= RECORD_CONTINUOUSLY; |
514 } else { | 645 } else { |
515 NOTREACHED(); // Unknown option provided. | 646 NOTREACHED(); // Unknown option provided. |
516 } | 647 } |
517 } | 648 } |
518 // Check to see if any RECORD_* options are set, and if none, then provide | 649 if (!(ret & RECORD_UNTIL_FULL) && !(ret & RECORD_CONTINUOUSLY)) |
519 // a default. | |
520 // TODO(dsinclair): Remove this comment when we have more then one RECORD_* | |
521 // flag and the code's structure is then sensible. | |
522 if (!(ret & RECORD_UNTIL_FULL)) | |
523 ret |= RECORD_UNTIL_FULL; // Default when no options are specified. | 650 ret |= RECORD_UNTIL_FULL; // Default when no options are specified. |
524 | 651 |
525 return static_cast<Options>(ret); | 652 return static_cast<Options>(ret); |
526 } | 653 } |
527 | 654 |
528 TraceLog::TraceLog() | 655 TraceLog::TraceLog() |
529 : enable_count_(0), | 656 : enable_count_(0), |
| 657 logged_events_(NULL), |
530 dispatching_to_observer_list_(false), | 658 dispatching_to_observer_list_(false), |
531 watch_category_(NULL), | 659 watch_category_(NULL), |
532 trace_options_(RECORD_UNTIL_FULL), | 660 trace_options_(RECORD_UNTIL_FULL), |
533 sampling_thread_handle_(0) { | 661 sampling_thread_handle_(0) { |
534 // Trace is enabled or disabled on one thread while other threads are | 662 // Trace is enabled or disabled on one thread while other threads are |
535 // accessing the enabled flag. We don't care whether edge-case events are | 663 // accessing the enabled flag. We don't care whether edge-case events are |
536 // traced or not, so we allow races on the enabled flag to keep the trace | 664 // traced or not, so we allow races on the enabled flag to keep the trace |
537 // macros fast. | 665 // macros fast. |
538 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: | 666 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: |
539 // ANNOTATE_BENIGN_RACE_SIZED(g_category_enabled, sizeof(g_category_enabled), | 667 // ANNOTATE_BENIGN_RACE_SIZED(g_category_enabled, sizeof(g_category_enabled), |
540 // "trace_event category enabled"); | 668 // "trace_event category enabled"); |
541 for (int i = 0; i < TRACE_EVENT_MAX_CATEGORIES; ++i) { | 669 for (int i = 0; i < TRACE_EVENT_MAX_CATEGORIES; ++i) { |
542 ANNOTATE_BENIGN_RACE(&g_category_enabled[i], | 670 ANNOTATE_BENIGN_RACE(&g_category_enabled[i], |
543 "trace_event category enabled"); | 671 "trace_event category enabled"); |
544 } | 672 } |
545 #if defined(OS_NACL) // NaCl shouldn't expose the process id. | 673 #if defined(OS_NACL) // NaCl shouldn't expose the process id. |
546 SetProcessID(0); | 674 SetProcessID(0); |
547 #else | 675 #else |
548 SetProcessID(static_cast<int>(GetCurrentProcId())); | 676 SetProcessID(static_cast<int>(GetCurrentProcId())); |
549 #endif | 677 #endif |
| 678 |
| 679 logged_events_.reset(GetTraceBuffer()); |
550 } | 680 } |
551 | 681 |
552 TraceLog::~TraceLog() { | 682 TraceLog::~TraceLog() { |
553 } | 683 } |
554 | 684 |
555 const unsigned char* TraceLog::GetCategoryEnabled(const char* name) { | 685 const unsigned char* TraceLog::GetCategoryEnabled(const char* name) { |
556 TraceLog* tracelog = GetInstance(); | 686 TraceLog* tracelog = GetInstance(); |
557 if (!tracelog) { | 687 if (!tracelog) { |
558 DCHECK(!g_category_enabled[g_category_already_shutdown]); | 688 DCHECK(!g_category_enabled[g_category_already_shutdown]); |
559 return &g_category_enabled[g_category_already_shutdown]; | 689 return &g_category_enabled[g_category_already_shutdown]; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 included_categories.end()); | 805 included_categories.end()); |
676 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0); | 806 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0); |
677 } else { | 807 } else { |
678 // If either old or new included categories are empty, allow all events. | 808 // If either old or new included categories are empty, allow all events. |
679 included_categories_.clear(); | 809 included_categories_.clear(); |
680 excluded_categories_.clear(); | 810 excluded_categories_.clear(); |
681 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED); | 811 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED); |
682 } | 812 } |
683 return; | 813 return; |
684 } | 814 } |
685 trace_options_ = options; | 815 |
| 816 if (options != trace_options_) { |
| 817 trace_options_ = options; |
| 818 logged_events_.reset(GetTraceBuffer()); |
| 819 } |
686 | 820 |
687 if (dispatching_to_observer_list_) { | 821 if (dispatching_to_observer_list_) { |
688 DLOG(ERROR) << | 822 DLOG(ERROR) << |
689 "Cannot manipulate TraceLog::Enabled state from an observer."; | 823 "Cannot manipulate TraceLog::Enabled state from an observer."; |
690 return; | 824 return; |
691 } | 825 } |
692 | 826 |
693 dispatching_to_observer_list_ = true; | 827 dispatching_to_observer_list_ = true; |
694 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, | 828 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, |
695 OnTraceLogWillEnable()); | 829 OnTraceLogWillEnable()); |
696 dispatching_to_observer_list_ = false; | 830 dispatching_to_observer_list_ = false; |
697 | 831 |
698 logged_events_.reserve(1024); | |
699 included_categories_ = included_categories; | 832 included_categories_ = included_categories; |
700 excluded_categories_ = excluded_categories; | 833 excluded_categories_ = excluded_categories; |
701 // Note that if both included and excluded_categories are empty, the else | 834 // Note that if both included and excluded_categories are empty, the else |
702 // clause below excludes nothing, thereby enabling all categories. | 835 // clause below excludes nothing, thereby enabling all categories. |
703 if (!included_categories_.empty()) | 836 if (!included_categories_.empty()) |
704 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0); | 837 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0); |
705 else | 838 else |
706 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED); | 839 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED); |
707 | 840 |
708 if (options & ENABLE_SAMPLING) { | 841 if (options & ENABLE_SAMPLING) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
804 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { | 937 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { |
805 enabled_state_observer_list_.AddObserver(listener); | 938 enabled_state_observer_list_.AddObserver(listener); |
806 } | 939 } |
807 | 940 |
808 void TraceLog::RemoveEnabledStateObserver( | 941 void TraceLog::RemoveEnabledStateObserver( |
809 EnabledStateChangedObserver* listener) { | 942 EnabledStateChangedObserver* listener) { |
810 enabled_state_observer_list_.RemoveObserver(listener); | 943 enabled_state_observer_list_.RemoveObserver(listener); |
811 } | 944 } |
812 | 945 |
813 float TraceLog::GetBufferPercentFull() const { | 946 float TraceLog::GetBufferPercentFull() const { |
814 return (float)((double)logged_events_.size()/(double)kTraceEventBufferSize); | 947 return (float)((double)logged_events_->Size()/(double)kTraceEventBufferSize); |
815 } | 948 } |
816 | 949 |
817 void TraceLog::SetNotificationCallback( | 950 void TraceLog::SetNotificationCallback( |
818 const TraceLog::NotificationCallback& cb) { | 951 const TraceLog::NotificationCallback& cb) { |
819 AutoLock lock(lock_); | 952 AutoLock lock(lock_); |
820 notification_callback_ = cb; | 953 notification_callback_ = cb; |
821 } | 954 } |
822 | 955 |
| 956 TraceBuffer* TraceLog::GetTraceBuffer() { |
| 957 if (trace_options_ & RECORD_CONTINUOUSLY) |
| 958 return new TraceBufferRingBuffer(); |
| 959 return new TraceBufferVector(); |
| 960 } |
| 961 |
823 void TraceLog::SetEventCallback(EventCallback cb) { | 962 void TraceLog::SetEventCallback(EventCallback cb) { |
824 AutoLock lock(lock_); | 963 AutoLock lock(lock_); |
825 event_callback_ = cb; | 964 event_callback_ = cb; |
826 }; | 965 }; |
827 | 966 |
828 void TraceLog::Flush(const TraceLog::OutputCallback& cb) { | 967 void TraceLog::Flush(const TraceLog::OutputCallback& cb) { |
829 std::vector<TraceEvent> previous_logged_events; | 968 scoped_ptr<TraceBuffer> previous_logged_events; |
830 { | 969 { |
831 AutoLock lock(lock_); | 970 AutoLock lock(lock_); |
832 previous_logged_events.swap(logged_events_); | 971 previous_logged_events.swap(logged_events_); |
| 972 logged_events_.reset(GetTraceBuffer()); |
833 } // release lock | 973 } // release lock |
834 | 974 |
835 for (size_t i = 0; | 975 while (previous_logged_events->HasMoreEvents()) { |
836 i < previous_logged_events.size(); | |
837 i += kTraceEventBatchSize) { | |
838 scoped_refptr<RefCountedString> json_events_str_ptr = | 976 scoped_refptr<RefCountedString> json_events_str_ptr = |
839 new RefCountedString(); | 977 new RefCountedString(); |
840 TraceEvent::AppendEventsAsJSON(previous_logged_events, | 978 |
841 i, | 979 for (size_t i = 0; i < kTraceEventBatchSize; ++i) { |
842 kTraceEventBatchSize, | 980 if (i > 0) |
843 &(json_events_str_ptr->data())); | 981 *(&(json_events_str_ptr->data())) += ","; |
| 982 |
| 983 previous_logged_events->NextEvent().AppendAsJSON( |
| 984 &(json_events_str_ptr->data())); |
| 985 |
| 986 if (!previous_logged_events->HasMoreEvents()) |
| 987 break; |
| 988 } |
| 989 |
844 cb.Run(json_events_str_ptr); | 990 cb.Run(json_events_str_ptr); |
845 } | 991 } |
846 } | 992 } |
847 | 993 |
848 void TraceLog::AddTraceEvent(char phase, | 994 void TraceLog::AddTraceEvent(char phase, |
849 const unsigned char* category_enabled, | 995 const unsigned char* category_enabled, |
850 const char* name, | 996 const char* name, |
851 unsigned long long id, | 997 unsigned long long id, |
852 int num_args, | 998 int num_args, |
853 const char** arg_names, | 999 const char** arg_names, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 | 1031 |
886 TimeTicks now = timestamp - time_offset_; | 1032 TimeTicks now = timestamp - time_offset_; |
887 EventCallback event_callback_copy; | 1033 EventCallback event_callback_copy; |
888 | 1034 |
889 NotificationHelper notifier(this); | 1035 NotificationHelper notifier(this); |
890 | 1036 |
891 { | 1037 { |
892 AutoLock lock(lock_); | 1038 AutoLock lock(lock_); |
893 if (*category_enabled != CATEGORY_ENABLED) | 1039 if (*category_enabled != CATEGORY_ENABLED) |
894 return; | 1040 return; |
895 if (logged_events_.size() >= kTraceEventBufferSize) | 1041 if (logged_events_->IsFull()) |
896 return; | 1042 return; |
897 | 1043 |
898 const char* new_name = ThreadIdNameManager::GetInstance()-> | 1044 const char* new_name = ThreadIdNameManager::GetInstance()-> |
899 GetName(thread_id); | 1045 GetName(thread_id); |
900 // Check if the thread name has been set or changed since the previous | 1046 // Check if the thread name has been set or changed since the previous |
901 // call (if any), but don't bother if the new name is empty. Note this will | 1047 // call (if any), but don't bother if the new name is empty. Note this will |
902 // not detect a thread name change within the same char* buffer address: we | 1048 // not detect a thread name change within the same char* buffer address: we |
903 // favor common case performance over corner case correctness. | 1049 // favor common case performance over corner case correctness. |
904 if (new_name != g_current_thread_name.Get().Get() && | 1050 if (new_name != g_current_thread_name.Get().Get() && |
905 new_name && *new_name) { | 1051 new_name && *new_name) { |
(...skipping 12 matching lines...) Expand all Loading... |
918 bool found = std::find(existing_names.begin(), | 1064 bool found = std::find(existing_names.begin(), |
919 existing_names.end(), | 1065 existing_names.end(), |
920 new_name) != existing_names.end(); | 1066 new_name) != existing_names.end(); |
921 if (!found) { | 1067 if (!found) { |
922 existing_name->second.push_back(','); | 1068 existing_name->second.push_back(','); |
923 existing_name->second.append(new_name); | 1069 existing_name->second.append(new_name); |
924 } | 1070 } |
925 } | 1071 } |
926 } | 1072 } |
927 | 1073 |
928 logged_events_.push_back( | 1074 logged_events_->AddEvent(TraceEvent(thread_id, |
929 TraceEvent(thread_id, | 1075 now, phase, category_enabled, name, id, |
930 now, phase, category_enabled, name, id, | 1076 num_args, arg_names, arg_types, arg_values, |
931 num_args, arg_names, arg_types, arg_values, | 1077 flags)); |
932 flags)); | |
933 | 1078 |
934 if (logged_events_.size() == kTraceEventBufferSize) | 1079 if (logged_events_->IsFull()) |
935 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); | 1080 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); |
936 | 1081 |
937 if (watch_category_ == category_enabled && watch_event_name_ == name) | 1082 if (watch_category_ == category_enabled && watch_event_name_ == name) |
938 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); | 1083 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); |
939 | 1084 |
940 event_callback_copy = event_callback_; | 1085 event_callback_copy = event_callback_; |
941 } // release lock | 1086 } // release lock |
942 | 1087 |
943 notifier.SendNotificationIfAny(); | 1088 notifier.SendNotificationIfAny(); |
944 if (event_callback_copy != NULL) { | 1089 if (event_callback_copy != NULL) { |
(...skipping 22 matching lines...) Expand all Loading... |
967 #if defined(OS_WIN) | 1112 #if defined(OS_WIN) |
968 TraceEventETWProvider::Trace(name, phase, id, extra); | 1113 TraceEventETWProvider::Trace(name, phase, id, extra); |
969 #endif | 1114 #endif |
970 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name, | 1115 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name, |
971 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); | 1116 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); |
972 } | 1117 } |
973 | 1118 |
974 void TraceLog::SetWatchEvent(const std::string& category_name, | 1119 void TraceLog::SetWatchEvent(const std::string& category_name, |
975 const std::string& event_name) { | 1120 const std::string& event_name) { |
976 const unsigned char* category = GetCategoryEnabled(category_name.c_str()); | 1121 const unsigned char* category = GetCategoryEnabled(category_name.c_str()); |
977 int notify_count = 0; | 1122 size_t notify_count = 0; |
978 { | 1123 { |
979 AutoLock lock(lock_); | 1124 AutoLock lock(lock_); |
980 watch_category_ = category; | 1125 watch_category_ = category; |
981 watch_event_name_ = event_name; | 1126 watch_event_name_ = event_name; |
982 | 1127 |
983 // First, search existing events for watch event because we want to catch it | 1128 // First, search existing events for watch event because we want to catch |
984 // even if it has already occurred. | 1129 // it even if it has already occurred. |
985 for (size_t i = 0u; i < logged_events_.size(); ++i) { | 1130 notify_count = logged_events_->CountEnabledByName(category, event_name); |
986 if (category == logged_events_[i].category_enabled() && | |
987 strcmp(event_name.c_str(), logged_events_[i].name()) == 0) { | |
988 ++notify_count; | |
989 } | |
990 } | |
991 } // release lock | 1131 } // release lock |
992 | 1132 |
993 // Send notification for each event found. | 1133 // Send notification for each event found. |
994 for (int i = 0; i < notify_count; ++i) { | 1134 for (size_t i = 0; i < notify_count; ++i) { |
995 NotificationHelper notifier(this); | 1135 NotificationHelper notifier(this); |
996 lock_.Acquire(); | 1136 lock_.Acquire(); |
997 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); | 1137 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); |
998 lock_.Release(); | 1138 lock_.Release(); |
999 notifier.SendNotificationIfAny(); | 1139 notifier.SendNotificationIfAny(); |
1000 } | 1140 } |
1001 } | 1141 } |
1002 | 1142 |
1003 void TraceLog::CancelWatchEvent() { | 1143 void TraceLog::CancelWatchEvent() { |
1004 AutoLock lock(lock_); | 1144 AutoLock lock(lock_); |
1005 watch_category_ = NULL; | 1145 watch_category_ = NULL; |
1006 watch_event_name_ = ""; | 1146 watch_event_name_ = ""; |
1007 } | 1147 } |
1008 | 1148 |
1009 void TraceLog::AddThreadNameMetadataEvents() { | 1149 void TraceLog::AddThreadNameMetadataEvents() { |
1010 lock_.AssertAcquired(); | 1150 lock_.AssertAcquired(); |
1011 for(hash_map<int, std::string>::iterator it = thread_names_.begin(); | 1151 for(hash_map<int, std::string>::iterator it = thread_names_.begin(); |
1012 it != thread_names_.end(); | 1152 it != thread_names_.end(); |
1013 it++) { | 1153 it++) { |
1014 if (!it->second.empty()) { | 1154 if (!it->second.empty()) { |
1015 int num_args = 1; | 1155 int num_args = 1; |
1016 const char* arg_name = "name"; | 1156 const char* arg_name = "name"; |
1017 unsigned char arg_type; | 1157 unsigned char arg_type; |
1018 unsigned long long arg_value; | 1158 unsigned long long arg_value; |
1019 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value); | 1159 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value); |
1020 logged_events_.push_back( | 1160 logged_events_->AddEvent(TraceEvent(it->first, |
1021 TraceEvent(it->first, | 1161 TimeTicks(), TRACE_EVENT_PHASE_METADATA, |
1022 TimeTicks(), TRACE_EVENT_PHASE_METADATA, | 1162 &g_category_enabled[g_category_metadata], |
1023 &g_category_enabled[g_category_metadata], | 1163 "thread_name", trace_event_internal::kNoEventId, |
1024 "thread_name", trace_event_internal::kNoEventId, | 1164 num_args, &arg_name, &arg_type, &arg_value, |
1025 num_args, &arg_name, &arg_type, &arg_value, | 1165 TRACE_EVENT_FLAG_NONE)); |
1026 TRACE_EVENT_FLAG_NONE)); | |
1027 } | 1166 } |
1028 } | 1167 } |
1029 } | 1168 } |
1030 | 1169 |
1031 void TraceLog::InstallWaitableEventForSamplingTesting( | 1170 void TraceLog::InstallWaitableEventForSamplingTesting( |
1032 WaitableEvent* waitable_event) { | 1171 WaitableEvent* waitable_event) { |
1033 sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event); | 1172 sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event); |
1034 } | 1173 } |
1035 | 1174 |
1036 void TraceLog::DeleteForTesting() { | 1175 void TraceLog::DeleteForTesting() { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1098 0, // num_args | 1237 0, // num_args |
1099 NULL, // arg_names | 1238 NULL, // arg_names |
1100 NULL, // arg_types | 1239 NULL, // arg_types |
1101 NULL, // arg_values | 1240 NULL, // arg_values |
1102 TRACE_EVENT_FLAG_NONE); // flags | 1241 TRACE_EVENT_FLAG_NONE); // flags |
1103 } | 1242 } |
1104 } | 1243 } |
1105 | 1244 |
1106 } // namespace trace_event_internal | 1245 } // namespace trace_event_internal |
1107 | 1246 |
OLD | NEW |