1 // Copyright (c) 2011 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 #include "base/debug/trace_event_win.h"
6
7 #include "base/logging.h"
8 #include "base/memory/singleton.h"
9 #include <initguid.h> // NOLINT
10
11 namespace base {
12 namespace debug {
13
14 using base::win::EtwEventType;
15 using base::win::EtwMofEvent;
16
17 // {3DADA31D-19EF-4dc1-B345-037927193422}
18 const GUID kChromeTraceProviderName = {
19 0x3dada31d, 0x19ef, 0x4dc1, 0xb3, 0x45, 0x3, 0x79, 0x27, 0x19, 0x34, 0x22 };
20
21 // {B967AE67-BB22-49d7-9406-55D91EE1D560}
22 const GUID kTraceEventClass32 = {
23 0xb967ae67, 0xbb22, 0x49d7, 0x94, 0x6, 0x55, 0xd9, 0x1e, 0xe1, 0xd5, 0x60 };
24
25 // {97BE602D-2930-4ac3-8046-B6763B631DFE}
26 const GUID kTraceEventClass64 = {
27 0x97be602d, 0x2930, 0x4ac3, 0x80, 0x46, 0xb6, 0x76, 0x3b, 0x63, 0x1d, 0xfe};
28
29
TraceLog()30 TraceLog::TraceLog() : EtwTraceProvider(kChromeTraceProviderName) {
31 Register();
32 }
33
GetInstance()34 TraceLog* TraceLog::GetInstance() {
35 return Singleton<TraceLog, StaticMemorySingletonTraits<TraceLog> >::get();
36 }
37
StartTracing()38 bool TraceLog::StartTracing() {
39 return true;
40 }
41
TraceEvent(const char * name,size_t name_len,EventType type,const void * id,const char * extra,size_t extra_len)42 void TraceLog::TraceEvent(const char* name,
43 size_t name_len,
44 EventType type,
45 const void* id,
46 const char* extra,
47 size_t extra_len) {
48 // Make sure we don't touch NULL.
49 if (name == NULL)
50 name = "";
51 if (extra == NULL)
52 extra = "";
53
54 EtwEventType etw_type = 0;
55 switch (type) {
56 case TraceLog::EVENT_BEGIN:
57 etw_type = kTraceEventTypeBegin;
58 break;
59 case TraceLog::EVENT_END:
60 etw_type = kTraceEventTypeEnd;
61 break;
62
63 case TraceLog::EVENT_INSTANT:
64 etw_type = kTraceEventTypeInstant;
65 break;
66
67 default:
68 NOTREACHED() << "Unknown event type";
69 etw_type = kTraceEventTypeInstant;
70 break;
71 }
72
73 EtwMofEvent<5> event(kTraceEventClass32,
74 etw_type,
75 TRACE_LEVEL_INFORMATION);
76 event.SetField(0, name_len + 1, name);
77 event.SetField(1, sizeof(id), &id);
78 event.SetField(2, extra_len + 1, extra);
79
80 // See whether we're to capture a backtrace.
81 void* backtrace[32];
82 if (enable_flags() & CAPTURE_STACK_TRACE) {
83 DWORD hash = 0;
84 DWORD depth = CaptureStackBackTrace(0,
85 arraysize(backtrace),
86 backtrace,
87 &hash);
88 event.SetField(3, sizeof(depth), &depth);
89 event.SetField(4, sizeof(backtrace[0]) * depth, backtrace);
90 }
91
92 // Trace the event.
93 Log(event.get());
94 }
95
Trace(const char * name,size_t name_len,EventType type,const void * id,const char * extra,size_t extra_len)96 void TraceLog::Trace(const char* name,
97 size_t name_len,
98 EventType type,
99 const void* id,
100 const char* extra,
101 size_t extra_len) {
102 TraceLog* provider = TraceLog::GetInstance();
103 if (provider && provider->IsTracing()) {
104 // Compute the name & extra lengths if not supplied already.
105 if (name_len == -1)
106 name_len = (name == NULL) ? 0 : strlen(name);
107 if (extra_len == -1)
108 extra_len = (extra == NULL) ? 0 : strlen(extra);
109
110 provider->TraceEvent(name, name_len, type, id, extra, extra_len);
111 }
112 }
113
Resurrect()114 void TraceLog::Resurrect() {
115 StaticMemorySingletonTraits<TraceLog>::Resurrect();
116 }
117
118 } // namespace debug
119 } // namespace base
120