OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 |
| 6 #ifndef BASE_DEBUG_TRACE_EVENT_IMPL_H_ |
| 7 #define BASE_DEBUG_TRACE_EVENT_IMPL_H_ |
| 8 #pragma once |
| 9 |
| 10 #include "build/build_config.h" |
| 11 |
| 12 #include <string> |
| 13 #include <vector> |
| 14 |
| 15 #include "base/callback.h" |
| 16 #include "base/hash_tables.h" |
| 17 #include "base/memory/ref_counted_memory.h" |
| 18 #include "base/string_util.h" |
| 19 #include "base/synchronization/lock.h" |
| 20 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
| 21 #include "base/timer.h" |
| 22 |
| 23 // Older style trace macros with explicit id and extra data |
| 24 // Only these macros result in publishing data to ETW as currently implemented. |
| 25 #define TRACE_EVENT_BEGIN_ETW(name, id, extra) \ |
| 26 base::debug::TraceLog::AddTraceEventEtw( \ |
| 27 TRACE_EVENT_PHASE_BEGIN, \ |
| 28 name, reinterpret_cast<const void*>(id), extra) |
| 29 |
| 30 #define TRACE_EVENT_END_ETW(name, id, extra) \ |
| 31 base::debug::TraceLog::AddTraceEventEtw( \ |
| 32 TRACE_EVENT_PHASE_END, \ |
| 33 name, reinterpret_cast<const void*>(id), extra) |
| 34 |
| 35 #define TRACE_EVENT_INSTANT_ETW(name, id, extra) \ |
| 36 base::debug::TraceLog::AddTraceEventEtw( \ |
| 37 TRACE_EVENT_PHASE_INSTANT, \ |
| 38 name, reinterpret_cast<const void*>(id), extra) |
| 39 |
| 40 template <typename Type> |
| 41 struct StaticMemorySingletonTraits; |
| 42 |
| 43 namespace base { |
| 44 |
| 45 class RefCountedString; |
| 46 |
| 47 namespace debug { |
| 48 |
| 49 const int kTraceMaxNumArgs = 2; |
| 50 |
| 51 // Output records are "Events" and can be obtained via the |
| 52 // OutputCallback whenever the tracing system decides to flush. This |
| 53 // can happen at any time, on any thread, or you can programatically |
| 54 // force it to happen. |
| 55 class BASE_EXPORT TraceEvent { |
| 56 public: |
| 57 union TraceValue { |
| 58 bool as_bool; |
| 59 unsigned long long as_uint; |
| 60 long long as_int; |
| 61 double as_double; |
| 62 const void* as_pointer; |
| 63 const char* as_string; |
| 64 }; |
| 65 |
| 66 TraceEvent(); |
| 67 TraceEvent(int thread_id, |
| 68 TimeTicks timestamp, |
| 69 char phase, |
| 70 const unsigned char* category_enabled, |
| 71 const char* name, |
| 72 unsigned long long id, |
| 73 int num_args, |
| 74 const char** arg_names, |
| 75 const unsigned char* arg_types, |
| 76 const unsigned long long* arg_values, |
| 77 unsigned char flags); |
| 78 ~TraceEvent(); |
| 79 |
| 80 // Serialize event data to JSON |
| 81 static void AppendEventsAsJSON(const std::vector<TraceEvent>& events, |
| 82 size_t start, |
| 83 size_t count, |
| 84 std::string* out); |
| 85 void AppendAsJSON(std::string* out) const; |
| 86 |
| 87 TimeTicks timestamp() const { return timestamp_; } |
| 88 |
| 89 // Exposed for unittesting: |
| 90 |
| 91 const base::RefCountedString* parameter_copy_storage() const { |
| 92 return parameter_copy_storage_.get(); |
| 93 } |
| 94 |
| 95 const char* name() const { return name_; } |
| 96 |
| 97 private: |
| 98 // Note: these are ordered by size (largest first) for optimal packing. |
| 99 TimeTicks timestamp_; |
| 100 // id_ can be used to store phase-specific data. |
| 101 unsigned long long id_; |
| 102 TraceValue arg_values_[kTraceMaxNumArgs]; |
| 103 const char* arg_names_[kTraceMaxNumArgs]; |
| 104 const unsigned char* category_enabled_; |
| 105 const char* name_; |
| 106 scoped_refptr<base::RefCountedString> parameter_copy_storage_; |
| 107 int thread_id_; |
| 108 char phase_; |
| 109 unsigned char flags_; |
| 110 unsigned char arg_types_[kTraceMaxNumArgs]; |
| 111 }; |
| 112 |
| 113 |
| 114 // TraceResultBuffer collects and converts trace fragments returned by TraceLog |
| 115 // to JSON output. |
| 116 class BASE_EXPORT TraceResultBuffer { |
| 117 public: |
| 118 typedef base::Callback<void(const std::string&)> OutputCallback; |
| 119 |
| 120 // If you don't need to stream JSON chunks out efficiently, and just want to |
| 121 // get a complete JSON string after calling Finish, use this struct to collect |
| 122 // JSON trace output. |
| 123 struct BASE_EXPORT SimpleOutput { |
| 124 OutputCallback GetCallback(); |
| 125 void Append(const std::string& json_string); |
| 126 |
| 127 // Do what you want with the json_output_ string after calling |
| 128 // TraceResultBuffer::Finish. |
| 129 std::string json_output; |
| 130 }; |
| 131 |
| 132 TraceResultBuffer(); |
| 133 ~TraceResultBuffer(); |
| 134 |
| 135 // Set callback. The callback will be called during Start with the initial |
| 136 // JSON output and during AddFragment and Finish with following JSON output |
| 137 // chunks. The callback target must live past the last calls to |
| 138 // TraceResultBuffer::Start/AddFragment/Finish. |
| 139 void SetOutputCallback(const OutputCallback& json_chunk_callback); |
| 140 |
| 141 // Start JSON output. This resets all internal state, so you can reuse |
| 142 // the TraceResultBuffer by calling Start. |
| 143 void Start(); |
| 144 |
| 145 // Call AddFragment 0 or more times to add trace fragments from TraceLog. |
| 146 void AddFragment(const std::string& trace_fragment); |
| 147 |
| 148 // When all fragments have been added, call Finish to complete the JSON |
| 149 // formatted output. |
| 150 void Finish(); |
| 151 |
| 152 private: |
| 153 OutputCallback output_callback_; |
| 154 bool append_comma_; |
| 155 }; |
| 156 |
| 157 |
| 158 class BASE_EXPORT TraceLog { |
| 159 public: |
| 160 static TraceLog* GetInstance(); |
| 161 |
| 162 // Get set of known categories. This can change as new code paths are reached. |
| 163 // The known categories are inserted into |categories|. |
| 164 void GetKnownCategories(std::vector<std::string>* categories); |
| 165 |
| 166 // Enable tracing for provided list of categories. If tracing is already |
| 167 // enabled, this method does nothing -- changing categories during trace is |
| 168 // not supported. |
| 169 // If both included_categories and excluded_categories are empty, |
| 170 // all categories are traced. |
| 171 // Else if included_categories is non-empty, only those are traced. |
| 172 // Else if excluded_categories is non-empty, everything but those are traced. |
| 173 // Wildcards * and ? are supported (see MatchPattern in string_util.h). |
| 174 void SetEnabled(const std::vector<std::string>& included_categories, |
| 175 const std::vector<std::string>& excluded_categories); |
| 176 |
| 177 // |categories| is a comma-delimited list of category wildcards. |
| 178 // A category can have an optional '-' prefix to make it an excluded category. |
| 179 // All the same rules apply above, so for example, having both included and |
| 180 // excluded categories in the same list would not be supported. |
| 181 // |
| 182 // Example: SetEnabled("test_MyTest*"); |
| 183 // Example: SetEnabled("test_MyTest*,test_OtherStuff"); |
| 184 // Example: SetEnabled("-excluded_category1,-excluded_category2"); |
| 185 void SetEnabled(const std::string& categories); |
| 186 |
| 187 // Retieves the categories set via a prior call to SetEnabled(). Only |
| 188 // meaningful if |IsEnabled()| is true. |
| 189 void GetEnabledTraceCategories(std::vector<std::string>* included_out, |
| 190 std::vector<std::string>* excluded_out); |
| 191 |
| 192 // Disable tracing for all categories. |
| 193 void SetDisabled(); |
| 194 // Helper method to enable/disable tracing for all categories. |
| 195 void SetEnabled(bool enabled); |
| 196 bool IsEnabled() { return enabled_; } |
| 197 |
| 198 float GetBufferPercentFull() const; |
| 199 |
| 200 // When enough events are collected, they are handed (in bulk) to |
| 201 // the output callback. If no callback is set, the output will be |
| 202 // silently dropped. The callback must be thread safe. The string format is |
| 203 // undefined. Use TraceResultBuffer to convert one or more trace strings to |
| 204 // JSON. |
| 205 typedef RefCountedData<std::string> RefCountedString; |
| 206 typedef base::Callback<void(const scoped_refptr<RefCountedString>&)> |
| 207 OutputCallback; |
| 208 void SetOutputCallback(const OutputCallback& cb); |
| 209 |
| 210 // The trace buffer does not flush dynamically, so when it fills up, |
| 211 // subsequent trace events will be dropped. This callback is generated when |
| 212 // the trace buffer is full. The callback must be thread safe. |
| 213 typedef base::Callback<void(void)> BufferFullCallback; |
| 214 void SetBufferFullCallback(const BufferFullCallback& cb); |
| 215 |
| 216 // Flushes all logged data to the callback. |
| 217 void Flush(); |
| 218 |
| 219 // Called by TRACE_EVENT* macros, don't call this directly. |
| 220 static const unsigned char* GetCategoryEnabled(const char* name); |
| 221 static const char* GetCategoryName(const unsigned char* category_enabled); |
| 222 |
| 223 // Called by TRACE_EVENT* macros, don't call this directly. |
| 224 // Returns the index in the internal vector of the event if it was added, or |
| 225 // -1 if the event was not added. |
| 226 // On end events, the return value of the begin event can be specified along |
| 227 // with a threshold in microseconds. If the elapsed time between begin and end |
| 228 // is less than the threshold, the begin/end event pair is dropped. |
| 229 // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied |
| 230 // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above. |
| 231 int AddTraceEvent(char phase, |
| 232 const unsigned char* category_enabled, |
| 233 const char* name, |
| 234 unsigned long long id, |
| 235 int num_args, |
| 236 const char** arg_names, |
| 237 const unsigned char* arg_types, |
| 238 const unsigned long long* arg_values, |
| 239 int threshold_begin_id, |
| 240 long long threshold, |
| 241 unsigned char flags); |
| 242 static void AddTraceEventEtw(char phase, |
| 243 const char* name, |
| 244 const void* id, |
| 245 const char* extra); |
| 246 static void AddTraceEventEtw(char phase, |
| 247 const char* name, |
| 248 const void* id, |
| 249 const std::string& extra); |
| 250 |
| 251 // A wrapper around AddTraceEvent used by TRACE_COUNTERx macros |
| 252 // that allows only integer values for the counters. |
| 253 void AddCounterEvent(const unsigned char* category_enabled, |
| 254 const char* name, |
| 255 unsigned long long id, |
| 256 const char* arg1_name, int arg1_val, |
| 257 const char* arg2_name, int arg2_val, |
| 258 unsigned char flags); |
| 259 |
| 260 // Mangle |ptr| with a hash based on the process ID so that if |ptr| occurs on |
| 261 // more than one process, it will not collide. |
| 262 unsigned long long GetInterProcessID(void* ptr) const { |
| 263 return static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(ptr)) ^ |
| 264 process_id_hash_; |
| 265 } |
| 266 |
| 267 int process_id() const { return process_id_; } |
| 268 |
| 269 // Exposed for unittesting: |
| 270 |
| 271 // Allows deleting our singleton instance. |
| 272 static void DeleteForTesting(); |
| 273 |
| 274 // Allows resurrecting our singleton instance post-AtExit processing. |
| 275 static void Resurrect(); |
| 276 |
| 277 // Allow tests to inspect TraceEvents. |
| 278 size_t GetEventsSize() const { return logged_events_.size(); } |
| 279 const TraceEvent& GetEventAt(size_t index) const { |
| 280 DCHECK(index < logged_events_.size()); |
| 281 return logged_events_[index]; |
| 282 } |
| 283 |
| 284 void SetProcessID(int process_id); |
| 285 |
| 286 private: |
| 287 // This allows constructor and destructor to be private and usable only |
| 288 // by the Singleton class. |
| 289 friend struct StaticMemorySingletonTraits<TraceLog>; |
| 290 |
| 291 TraceLog(); |
| 292 ~TraceLog(); |
| 293 const unsigned char* GetCategoryEnabledInternal(const char* name); |
| 294 void AddThreadNameMetadataEvents(); |
| 295 void AddClockSyncMetadataEvents(); |
| 296 |
| 297 // TODO(nduca): switch to per-thread trace buffers to reduce thread |
| 298 // synchronization. |
| 299 Lock lock_; |
| 300 bool enabled_; |
| 301 OutputCallback output_callback_; |
| 302 BufferFullCallback buffer_full_callback_; |
| 303 std::vector<TraceEvent> logged_events_; |
| 304 std::vector<std::string> included_categories_; |
| 305 std::vector<std::string> excluded_categories_; |
| 306 |
| 307 base::hash_map<int, std::string> thread_names_; |
| 308 |
| 309 // XORed with TraceID to make it unlikely to collide with other processes. |
| 310 unsigned long long process_id_hash_; |
| 311 |
| 312 int process_id_; |
| 313 |
| 314 DISALLOW_COPY_AND_ASSIGN(TraceLog); |
| 315 }; |
| 316 |
| 317 } // namespace debug |
| 318 } // namespace base |
| 319 |
| 320 #endif // BASE_DEBUG_TRACE_EVENT_IMPL_H_ |
OLD | NEW |