1 // Copyright 2015 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.
5 #include "base/trace_event/trace_event_etw_export_win.h"
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/memory/singleton.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/trace_event/trace_event.h"
12 #include "base/trace_event/trace_event_impl.h"
14 // The GetProcAddress technique is borrowed from
15 // https://github.com/randomascii/main/tree/master/xperf/ETWProviders
17 // EVNTAPI is used in evntprov.h which is included by chrome_events_win.h.
18 // We define EVNTAPI without the DECLSPEC_IMPORT specifier so that we can
19 // implement these functions locally instead of using the import library, and
20 // can therefore still run on Windows XP.
21 #define EVNTAPI __stdcall
22 // Include the event register/write/unregister macros compiled from the manifest
23 // file. Note that this includes evntprov.h which requires a Vista+ Windows SDK.
25 // In SHARED_INTERMEDIATE_DIR.
26 #include "base/trace_event/etw_manifest/chrome_events_win.h" // NOLINT
29 // Typedefs for use with GetProcAddress
30 typedef ULONG(__stdcall
* tEventRegister
)(LPCGUID ProviderId
,
31 PENABLECALLBACK EnableCallback
,
32 PVOID CallbackContext
,
33 PREGHANDLE RegHandle
);
34 typedef ULONG(__stdcall
* tEventWrite
)(REGHANDLE RegHandle
,
35 PCEVENT_DESCRIPTOR EventDescriptor
,
37 PEVENT_DATA_DESCRIPTOR UserData
);
38 typedef ULONG(__stdcall
* tEventUnregister
)(REGHANDLE RegHandle
);
40 tEventRegister EventRegisterProc
= nullptr;
41 tEventWrite EventWriteProc
= nullptr;
42 tEventUnregister EventUnregisterProc
= nullptr;
45 // Redirector function for EventRegister. Called by macros in
46 // chrome_events_win.h
47 ULONG EVNTAPI
EventRegister(LPCGUID ProviderId
,
48 PENABLECALLBACK EnableCallback
,
49 PVOID CallbackContext
,
50 PREGHANDLE RegHandle
) {
51 if (EventRegisterProc
)
52 return EventRegisterProc(ProviderId
, EnableCallback
, CallbackContext
,
57 // Redirector function for EventWrite. Called by macros in
58 // chrome_events_win.h
59 ULONG EVNTAPI
EventWrite(REGHANDLE RegHandle
,
60 PCEVENT_DESCRIPTOR EventDescriptor
,
62 PEVENT_DATA_DESCRIPTOR UserData
) {
64 return EventWriteProc(RegHandle
, EventDescriptor
, UserDataCount
, UserData
);
68 // Redirector function for EventUnregister. Called by macros in
69 // chrome_events_win.h
70 ULONG EVNTAPI
EventUnregister(REGHANDLE RegHandle
) {
71 if (EventUnregisterProc
)
72 return EventUnregisterProc(RegHandle
);
77 namespace trace_event
{
79 TraceEventETWExport::TraceEventETWExport() : ETWExportEnabled_(false) {
80 // Find Advapi32.dll. This should always succeed.
81 HMODULE AdvapiDLL
= ::LoadLibraryW(L
"Advapi32.dll");
83 // Try to find the ETW functions. This will fail on XP.
84 EventRegisterProc
= reinterpret_cast<tEventRegister
>(
85 ::GetProcAddress(AdvapiDLL
, "EventRegister"));
86 EventWriteProc
= reinterpret_cast<tEventWrite
>(
87 ::GetProcAddress(AdvapiDLL
, "EventWrite"));
88 EventUnregisterProc
= reinterpret_cast<tEventUnregister
>(
89 ::GetProcAddress(AdvapiDLL
, "EventUnregister"));
91 // Register the ETW provider. If registration fails then the event logging
92 // calls will fail (on XP this call will do nothing).
93 EventRegisterChrome();
97 TraceEventETWExport::~TraceEventETWExport() {
98 EventUnregisterChrome();
102 TraceEventETWExport
* TraceEventETWExport::GetInstance() {
103 return Singleton
<TraceEventETWExport
,
104 StaticMemorySingletonTraits
<TraceEventETWExport
>>::get();
108 void TraceEventETWExport::EnableETWExport() {
109 GetInstance()->ETWExportEnabled_
= true;
113 void TraceEventETWExport::DisableETWExport() {
114 GetInstance()->ETWExportEnabled_
= false;
118 void TraceEventETWExport::AddEvent(
120 const unsigned char* category_group_enabled
,
122 unsigned long long id
,
124 const char** arg_names
,
125 const unsigned char* arg_types
,
126 const unsigned long long* arg_values
,
127 const scoped_refptr
<ConvertableToTraceFormat
>* convertable_values
) {
128 // We bail early in case exporting is disabled or no consumer is listening.
129 if (!GetInstance()->ETWExportEnabled_
|| !EventEnabledChromeEvent())
132 std::string phase_string
;
134 case TRACE_EVENT_PHASE_BEGIN
:
135 phase_string
= "Begin";
137 case TRACE_EVENT_PHASE_END
:
138 phase_string
= "End";
140 case TRACE_EVENT_PHASE_COMPLETE
:
141 phase_string
= "Complete";
143 case TRACE_EVENT_PHASE_INSTANT
:
144 phase_string
= "Instant";
146 case TRACE_EVENT_PHASE_ASYNC_BEGIN
:
147 phase_string
= "Async Begin";
149 case TRACE_EVENT_PHASE_ASYNC_STEP_INTO
:
150 phase_string
= "Async Step Into";
152 case TRACE_EVENT_PHASE_ASYNC_STEP_PAST
:
153 phase_string
= "Async Step Past";
155 case TRACE_EVENT_PHASE_ASYNC_END
:
156 phase_string
= "Async End";
158 case TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN
:
159 phase_string
= "Nestable Async Begin";
161 case TRACE_EVENT_PHASE_NESTABLE_ASYNC_END
:
162 phase_string
= "Nestable Async End";
164 case TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT
:
165 phase_string
= "Nestable Async Instant";
167 case TRACE_EVENT_PHASE_FLOW_BEGIN
:
168 phase_string
= "Phase Flow Begin";
170 case TRACE_EVENT_PHASE_FLOW_STEP
:
171 phase_string
= "Phase Flow Step";
173 case TRACE_EVENT_PHASE_FLOW_END
:
174 phase_string
= "Phase Flow End";
176 case TRACE_EVENT_PHASE_METADATA
:
177 phase_string
= "Phase Metadata";
179 case TRACE_EVENT_PHASE_COUNTER
:
180 phase_string
= "Phase Counter";
182 case TRACE_EVENT_PHASE_SAMPLE
:
183 phase_string
= "Phase Sample";
185 case TRACE_EVENT_PHASE_CREATE_OBJECT
:
186 phase_string
= "Phase Create Object";
188 case TRACE_EVENT_PHASE_SNAPSHOT_OBJECT
:
189 phase_string
= "Phase Snapshot Object";
191 case TRACE_EVENT_PHASE_DELETE_OBJECT
:
192 phase_string
= "Phase Delete Object";
195 phase_string
.push_back(phase
);
199 std::string arg_values_string
[3];
200 for (int i
= 0; i
< num_args
; i
++) {
201 if (arg_types
[i
] == TRACE_VALUE_TYPE_CONVERTABLE
) {
202 convertable_values
[i
]->AppendAsTraceFormat(arg_values_string
+ i
);
204 TraceEvent::TraceValue trace_event
;
205 trace_event
.as_uint
= arg_values
[i
];
206 TraceEvent::AppendValueAsJSON(arg_types
[i
], trace_event
,
207 arg_values_string
+ i
);
211 EventWriteChromeEvent(
212 name
, phase_string
.c_str(), num_args
> 0 ? arg_names
[0] : "",
213 arg_values_string
[0].c_str(), num_args
> 1 ? arg_names
[1] : "",
214 arg_values_string
[1].c_str(), num_args
> 2 ? arg_names
[2] : "",
215 arg_values_string
[2].c_str());
219 void TraceEventETWExport::AddCustomEvent(const char* name
,
221 const char* arg_name_1
,
222 const char* arg_value_1
,
223 const char* arg_name_2
,
224 const char* arg_value_2
,
225 const char* arg_name_3
,
226 const char* arg_value_3
) {
227 if (!GetInstance()->ETWExportEnabled_
|| !EventEnabledChromeEvent())
230 EventWriteChromeEvent(name
, phase
, arg_name_1
, arg_value_1
, arg_name_2
,
231 arg_value_2
, arg_name_3
, arg_value_3
);
234 void TraceEventETWExport::Resurrect() {
235 StaticMemorySingletonTraits
<TraceEventETWExport
>::Resurrect();
238 } // namespace trace_event