| 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 |