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 #include "base/debug/trace_event_win.h" | 4 #include "base/debug/trace_event_win.h" |
5 | 5 |
6 #include "base/logging.h" | 6 #include "base/logging.h" |
7 #include "base/memory/singleton.h" | 7 #include "base/memory/singleton.h" |
8 #include <initguid.h> // NOLINT | 8 #include <initguid.h> // NOLINT |
9 | 9 |
| 10 namespace { |
| 11 // Returns the ETW event type ("opcode") associated with an event. The ETW |
| 12 // event type depends on: |
| 13 // - |internal_type|: Internal type of the event. |
| 14 // - |num_args|: Number of arguments included with the event. |
| 15 // - |with_stack|: Presence of a stack trace with the event. |
| 16 // The bits in the returned event type mean: |
| 17 // - 0-3 LSB: Number of arguments associated with the event. |
| 18 // - 4: Indicates whether a stack trace is included with the event. |
| 19 // - 5-8 MSB: Code associated with an internal event type. |
| 20 base::win::EtwEventType GetEtwEventType(char internal_type, |
| 21 int num_args, |
| 22 bool with_stack) { |
| 23 const base::win::EtwEventType kEtwBeginType = 1; |
| 24 const base::win::EtwEventType kEtwEndType = 2; |
| 25 const base::win::EtwEventType kEtwCompleteType = 3; |
| 26 const base::win::EtwEventType kEtwInstantType = 4; |
| 27 const base::win::EtwEventType kEtwAsyncBeginType = 5; |
| 28 const base::win::EtwEventType kEtwAsyncStepIntoType = 6; |
| 29 const base::win::EtwEventType kEtwAsyncStepPastType = 7; |
| 30 const base::win::EtwEventType kEtwAsyncEndType = 8; |
| 31 const base::win::EtwEventType kEtwFlowBeginType = 9; |
| 32 const base::win::EtwEventType kEtwFlowStepType = 10; |
| 33 const base::win::EtwEventType kEtwFlowEndType = 11; |
| 34 const base::win::EtwEventType kEtwMetadataType = 12; |
| 35 const base::win::EtwEventType kEtwCounterType = 13; |
| 36 const base::win::EtwEventType kEtwSampleType = 14; |
| 37 const base::win::EtwEventType kEtwCreateObjectType = 15; |
| 38 const base::win::EtwEventType kEtwSnapshotObjectType = 16; |
| 39 const base::win::EtwEventType kEtwDeleteObjectType = 17; |
| 40 |
| 41 const base::win::EtwEventType kEtwInternalTypeShiftLeft = 3; |
| 42 const base::win::EtwEventType kEtwStackMask = 0x04; |
| 43 const base::win::EtwEventType kEtwNumArgsMask = 0x03; |
| 44 |
| 45 // This type is used by third party libraries. It's defined here so that |
| 46 // events from these libraries can be handled correctly. |
| 47 const char kTraceEventPhaseInstantOld = 'I'; |
| 48 |
| 49 base::win::EtwEventType etw_type; |
| 50 switch (internal_type) { |
| 51 case TRACE_EVENT_PHASE_BEGIN: |
| 52 etw_type = kEtwBeginType; |
| 53 break; |
| 54 |
| 55 case TRACE_EVENT_PHASE_END: |
| 56 etw_type = kEtwEndType; |
| 57 break; |
| 58 |
| 59 case TRACE_EVENT_PHASE_COMPLETE: |
| 60 etw_type = kEtwCompleteType; |
| 61 break; |
| 62 |
| 63 case TRACE_EVENT_PHASE_INSTANT: |
| 64 case kTraceEventPhaseInstantOld: |
| 65 etw_type = kEtwInstantType; |
| 66 break; |
| 67 |
| 68 case TRACE_EVENT_PHASE_ASYNC_BEGIN: |
| 69 etw_type = kEtwAsyncBeginType; |
| 70 break; |
| 71 |
| 72 case TRACE_EVENT_PHASE_ASYNC_STEP_INTO: |
| 73 etw_type = kEtwAsyncStepIntoType; |
| 74 break; |
| 75 |
| 76 case TRACE_EVENT_PHASE_ASYNC_STEP_PAST: |
| 77 etw_type = kEtwAsyncStepPastType; |
| 78 break; |
| 79 case TRACE_EVENT_PHASE_ASYNC_END: |
| 80 etw_type = kEtwAsyncEndType; |
| 81 break; |
| 82 |
| 83 case TRACE_EVENT_PHASE_FLOW_BEGIN: |
| 84 etw_type = kEtwFlowBeginType; |
| 85 break; |
| 86 |
| 87 case TRACE_EVENT_PHASE_FLOW_STEP: |
| 88 etw_type = kEtwFlowStepType; |
| 89 break; |
| 90 |
| 91 case TRACE_EVENT_PHASE_FLOW_END: |
| 92 etw_type = kEtwFlowEndType; |
| 93 break; |
| 94 |
| 95 case TRACE_EVENT_PHASE_METADATA: |
| 96 etw_type = kEtwMetadataType; |
| 97 break; |
| 98 |
| 99 case TRACE_EVENT_PHASE_COUNTER: |
| 100 etw_type = kEtwCounterType; |
| 101 break; |
| 102 |
| 103 case TRACE_EVENT_PHASE_SAMPLE: |
| 104 etw_type = kEtwSampleType; |
| 105 break; |
| 106 |
| 107 case TRACE_EVENT_PHASE_CREATE_OBJECT: |
| 108 etw_type = kEtwCreateObjectType; |
| 109 break; |
| 110 |
| 111 case TRACE_EVENT_PHASE_SNAPSHOT_OBJECT: |
| 112 etw_type = kEtwSnapshotObjectType; |
| 113 break; |
| 114 |
| 115 case TRACE_EVENT_PHASE_DELETE_OBJECT: |
| 116 etw_type = kEtwAsyncEndType; |
| 117 break; |
| 118 |
| 119 default: |
| 120 NOTREACHED() << "Unknown event type"; |
| 121 etw_type = kEtwInstantType; |
| 122 break; |
| 123 } |
| 124 |
| 125 etw_type = etw_type << kEtwInternalTypeShiftLeft; |
| 126 DCHECK(num_args <= kEtwNumArgsMask); |
| 127 etw_type += static_cast<base::win::EtwEventType>(num_args) & kEtwNumArgsMask; |
| 128 if (with_stack) |
| 129 etw_type |= kEtwStackMask; |
| 130 |
| 131 return etw_type; |
| 132 } |
| 133 |
| 134 // Maximum number of MOF fields for traced events. |
| 135 // See the comment above the declaration of |
| 136 // TraceEventETWProvider::TraceEventWithArgs() for the list of fields. |
| 137 const int kTraceNumFields = 5 + 2 * base::debug::kTraceMaxNumArgs; |
| 138 } // namespace |
| 139 |
10 namespace base { | 140 namespace base { |
11 namespace debug { | 141 namespace debug { |
12 | 142 |
13 using base::win::EtwEventType; | 143 using base::win::EtwEventType; |
14 using base::win::EtwMofEvent; | 144 using base::win::EtwMofEvent; |
15 | 145 |
16 // {3DADA31D-19EF-4dc1-B345-037927193422} | 146 // {3DADA31D-19EF-4dc1-B345-037927193422} |
17 const GUID kChromeTraceProviderName = { | 147 const GUID kChromeTraceProviderName = { |
18 0x3dada31d, 0x19ef, 0x4dc1, 0xb3, 0x45, 0x3, 0x79, 0x27, 0x19, 0x34, 0x22 }; | 148 0x3dada31d, 0x19ef, 0x4dc1, 0xb3, 0x45, 0x3, 0x79, 0x27, 0x19, 0x34, 0x22 }; |
19 | 149 |
20 // {B967AE67-BB22-49d7-9406-55D91EE1D560} | 150 // {B967AE67-BB22-49d7-9406-55D91EE1D560} |
21 const GUID kTraceEventClass32 = { | 151 const GUID kTraceEventClass32 = { |
22 0xb967ae67, 0xbb22, 0x49d7, 0x94, 0x6, 0x55, 0xd9, 0x1e, 0xe1, 0xd5, 0x60 }; | 152 0xb967ae67, 0xbb22, 0x49d7, 0x94, 0x6, 0x55, 0xd9, 0x1e, 0xe1, 0xd5, 0x60 }; |
23 | 153 |
24 // {97BE602D-2930-4ac3-8046-B6763B631DFE} | 154 // {d2d578d9-2936-45b6-a09f-30e32715f41d} |
25 const GUID kTraceEventClass64 = { | 155 const GUID kTraceEventClass = { |
26 0x97be602d, 0x2930, 0x4ac3, 0x80, 0x46, 0xb6, 0x76, 0x3b, 0x63, 0x1d, 0xfe}; | 156 0xd2d578d9, 0x2936, 0x45b6, 0xa0, 0x9f, 0x30, 0xe3, 0x27, 0x15, 0xf4, 0x1d}; |
27 | |
28 | 157 |
29 TraceEventETWProvider::TraceEventETWProvider() : | 158 TraceEventETWProvider::TraceEventETWProvider() : |
30 EtwTraceProvider(kChromeTraceProviderName) { | 159 EtwTraceProvider(kChromeTraceProviderName) { |
31 Register(); | 160 Register(); |
32 } | 161 } |
33 | 162 |
34 TraceEventETWProvider* TraceEventETWProvider::GetInstance() { | 163 TraceEventETWProvider* TraceEventETWProvider::GetInstance() { |
35 return Singleton<TraceEventETWProvider, | 164 return Singleton<TraceEventETWProvider, |
36 StaticMemorySingletonTraits<TraceEventETWProvider> >::get(); | 165 StaticMemorySingletonTraits<TraceEventETWProvider> >::get(); |
37 } | 166 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 backtrace, | 219 backtrace, |
91 NULL); | 220 NULL); |
92 event.SetField(3, sizeof(depth), &depth); | 221 event.SetField(3, sizeof(depth), &depth); |
93 event.SetField(4, sizeof(backtrace[0]) * depth, backtrace); | 222 event.SetField(4, sizeof(backtrace[0]) * depth, backtrace); |
94 } | 223 } |
95 | 224 |
96 // Trace the event. | 225 // Trace the event. |
97 Log(event.get()); | 226 Log(event.get()); |
98 } | 227 } |
99 | 228 |
| 229 void TraceEventETWProvider::TraceEventWithArgs( |
| 230 const char* category_group, |
| 231 const char* name, |
| 232 char type, |
| 233 unsigned long long id, |
| 234 int num_args, |
| 235 const char** arg_names, |
| 236 const unsigned char* arg_types, |
| 237 const unsigned long long* arg_values, |
| 238 const scoped_refptr<ConvertableToTraceFormat>* convertable_values) { |
| 239 // Make sure we don't touch NULL. |
| 240 if (name == NULL) |
| 241 name = ""; |
| 242 if (category_group == NULL) |
| 243 category_group = ""; |
| 244 |
| 245 EtwMofEvent<kTraceNumFields> event(kTraceEventClass, |
| 246 TRACE_LEVEL_INFORMATION); |
| 247 |
| 248 int field_index = 0; |
| 249 event.SetField(field_index++, strlen(name) + 1, name); |
| 250 event.SetField(field_index++, sizeof(id), &id); |
| 251 event.SetField(field_index++, strlen(category_group) + 1, category_group); |
| 252 |
| 253 // Real number of arguments for the event. Might end up being less than |
| 254 // |num_args| when some arguments types are deactivated by flags. |
| 255 unsigned int real_num_args = 0; |
| 256 |
| 257 // Traced arguments values converted to strings. |
| 258 std::string arg_str_values[kTraceMaxNumArgs]; |
| 259 |
| 260 if (enable_flags() & CAPTURE_SIMPLE_ARGUMENTS || |
| 261 enable_flags() & CAPTURE_ALL_ARGUMENTS) { |
| 262 if (num_args > kTraceMaxNumArgs) { |
| 263 NOTREACHED() << "Maximum number of custom fields exceeded in ETW event. " |
| 264 "Extra custom fields will be ignored."; |
| 265 num_args = kTraceMaxNumArgs; |
| 266 } |
| 267 |
| 268 for (int i = 0; i < num_args; ++i) { |
| 269 if (arg_types[i] != TRACE_VALUE_TYPE_CONVERTABLE) { |
| 270 base::debug::TraceEvent::TraceValue value; |
| 271 value.as_uint = arg_values[i]; |
| 272 base::debug::TraceEvent::AppendValueAsJSON(arg_types[i], |
| 273 value, |
| 274 &arg_str_values[i]); |
| 275 } else if (enable_flags() & CAPTURE_ALL_ARGUMENTS) { |
| 276 convertable_values[i]->AppendAsTraceFormat(&arg_str_values[i]); |
| 277 } else { |
| 278 continue; |
| 279 } |
| 280 |
| 281 ++real_num_args; |
| 282 event.SetField(field_index++, strlen(arg_names[i]) + 1, arg_names[i]); |
| 283 event.SetField(field_index++, |
| 284 arg_str_values[i].size() + 1, |
| 285 arg_str_values[i].c_str()); |
| 286 } |
| 287 } |
| 288 bool capture_stack_trace = enable_flags() & CAPTURE_STACK_TRACE; |
| 289 event.SetType(GetEtwEventType(type, real_num_args, capture_stack_trace)); |
| 290 |
| 291 // See whether we're to capture a backtrace. |
| 292 DWORD depth; |
| 293 void* backtrace[32]; |
| 294 if (capture_stack_trace) { |
| 295 DWORD hash = 0; |
| 296 depth = CaptureStackBackTrace(0, |
| 297 arraysize(backtrace), |
| 298 backtrace, |
| 299 NULL); |
| 300 event.SetField(field_index++, sizeof(depth), &depth); |
| 301 event.SetField(field_index++, sizeof(backtrace[0]) * depth, backtrace); |
| 302 } |
| 303 DCHECK(field_index <= kTraceNumFields) |
| 304 << "Maxium number of fields exceeded in ETW event."; |
| 305 |
| 306 // Trace the event. |
| 307 Log(event.get()); |
| 308 } |
| 309 |
100 void TraceEventETWProvider::Trace(const char* name, | 310 void TraceEventETWProvider::Trace(const char* name, |
101 size_t name_len, | 311 size_t name_len, |
102 char type, | 312 char type, |
103 const void* id, | 313 const void* id, |
104 const char* extra, | 314 const char* extra, |
105 size_t extra_len) { | 315 size_t extra_len) { |
106 TraceEventETWProvider* provider = TraceEventETWProvider::GetInstance(); | 316 TraceEventETWProvider* provider = TraceEventETWProvider::GetInstance(); |
107 if (provider && provider->IsTracing()) { | 317 if (provider && provider->IsTracing()) { |
108 // Compute the name & extra lengths if not supplied already. | 318 // Compute the name & extra lengths if not supplied already. |
109 if (name_len == -1) | 319 if (name_len == -1) |
110 name_len = (name == NULL) ? 0 : strlen(name); | 320 name_len = (name == NULL) ? 0 : strlen(name); |
111 if (extra_len == -1) | 321 if (extra_len == -1) |
112 extra_len = (extra == NULL) ? 0 : strlen(extra); | 322 extra_len = (extra == NULL) ? 0 : strlen(extra); |
113 | 323 |
114 provider->TraceEvent(name, name_len, type, id, extra, extra_len); | 324 provider->TraceEvent(name, name_len, type, id, extra, extra_len); |
115 } | 325 } |
116 } | 326 } |
117 | 327 |
| 328 void TraceEventETWProvider::TraceWithArgs( |
| 329 const char* category_group, |
| 330 const char* name, |
| 331 char type, |
| 332 unsigned long long id, |
| 333 int num_args, |
| 334 const char** arg_names, |
| 335 const unsigned char* arg_types, |
| 336 const unsigned long long* arg_values, |
| 337 const scoped_refptr<ConvertableToTraceFormat>* convertable_values) { |
| 338 TraceEventETWProvider* provider = TraceEventETWProvider::GetInstance(); |
| 339 if (provider && provider->IsTracing()) { |
| 340 provider->TraceEventWithArgs(category_group, name, type, id, |
| 341 num_args, arg_names, arg_types, arg_values, |
| 342 convertable_values); |
| 343 } |
| 344 } |
| 345 |
118 void TraceEventETWProvider::Resurrect() { | 346 void TraceEventETWProvider::Resurrect() { |
119 StaticMemorySingletonTraits<TraceEventETWProvider>::Resurrect(); | 347 StaticMemorySingletonTraits<TraceEventETWProvider>::Resurrect(); |
120 } | 348 } |
121 | 349 |
122 } // namespace debug | 350 } // namespace debug |
123 } // namespace base | 351 } // namespace base |
OLD | NEW |