Center distiller results on desktop
[chromium-blink-merge.git] / base / trace_event / trace_event_etw_export_win.cc
blobf7f9eccaa4564194a0d40325d8895d80e0858e8a
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
28 namespace {
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,
36 ULONG UserDataCount,
37 PEVENT_DATA_DESCRIPTOR UserData);
38 typedef ULONG(__stdcall* tEventUnregister)(REGHANDLE RegHandle);
40 tEventRegister EventRegisterProc = nullptr;
41 tEventWrite EventWriteProc = nullptr;
42 tEventUnregister EventUnregisterProc = nullptr;
43 } // namespace
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,
53 RegHandle);
54 return 0;
57 // Redirector function for EventWrite. Called by macros in
58 // chrome_events_win.h
59 ULONG EVNTAPI EventWrite(REGHANDLE RegHandle,
60 PCEVENT_DESCRIPTOR EventDescriptor,
61 ULONG UserDataCount,
62 PEVENT_DATA_DESCRIPTOR UserData) {
63 if (EventWriteProc)
64 return EventWriteProc(RegHandle, EventDescriptor, UserDataCount, UserData);
65 return 0;
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);
73 return 0;
76 namespace base {
77 namespace trace_event {
79 TraceEventETWExport::TraceEventETWExport() : ETWExportEnabled_(false) {
80 // Find Advapi32.dll. This should always succeed.
81 HMODULE AdvapiDLL = ::LoadLibraryW(L"Advapi32.dll");
82 if (AdvapiDLL) {
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();
101 // static
102 TraceEventETWExport* TraceEventETWExport::GetInstance() {
103 return Singleton<TraceEventETWExport,
104 StaticMemorySingletonTraits<TraceEventETWExport>>::get();
107 // static
108 void TraceEventETWExport::EnableETWExport() {
109 GetInstance()->ETWExportEnabled_ = true;
112 // static
113 void TraceEventETWExport::DisableETWExport() {
114 GetInstance()->ETWExportEnabled_ = false;
117 // static
118 void TraceEventETWExport::AddEvent(
119 char phase,
120 const unsigned char* category_group_enabled,
121 const char* name,
122 unsigned long long id,
123 int num_args,
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())
130 return;
132 std::string phase_string;
133 switch (phase) {
134 case TRACE_EVENT_PHASE_BEGIN:
135 phase_string = "Begin";
136 break;
137 case TRACE_EVENT_PHASE_END:
138 phase_string = "End";
139 break;
140 case TRACE_EVENT_PHASE_COMPLETE:
141 phase_string = "Complete";
142 break;
143 case TRACE_EVENT_PHASE_INSTANT:
144 phase_string = "Instant";
145 break;
146 case TRACE_EVENT_PHASE_ASYNC_BEGIN:
147 phase_string = "Async Begin";
148 break;
149 case TRACE_EVENT_PHASE_ASYNC_STEP_INTO:
150 phase_string = "Async Step Into";
151 break;
152 case TRACE_EVENT_PHASE_ASYNC_STEP_PAST:
153 phase_string = "Async Step Past";
154 break;
155 case TRACE_EVENT_PHASE_ASYNC_END:
156 phase_string = "Async End";
157 break;
158 case TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN:
159 phase_string = "Nestable Async Begin";
160 break;
161 case TRACE_EVENT_PHASE_NESTABLE_ASYNC_END:
162 phase_string = "Nestable Async End";
163 break;
164 case TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT:
165 phase_string = "Nestable Async Instant";
166 break;
167 case TRACE_EVENT_PHASE_FLOW_BEGIN:
168 phase_string = "Phase Flow Begin";
169 break;
170 case TRACE_EVENT_PHASE_FLOW_STEP:
171 phase_string = "Phase Flow Step";
172 break;
173 case TRACE_EVENT_PHASE_FLOW_END:
174 phase_string = "Phase Flow End";
175 break;
176 case TRACE_EVENT_PHASE_METADATA:
177 phase_string = "Phase Metadata";
178 break;
179 case TRACE_EVENT_PHASE_COUNTER:
180 phase_string = "Phase Counter";
181 break;
182 case TRACE_EVENT_PHASE_SAMPLE:
183 phase_string = "Phase Sample";
184 break;
185 case TRACE_EVENT_PHASE_CREATE_OBJECT:
186 phase_string = "Phase Create Object";
187 break;
188 case TRACE_EVENT_PHASE_SNAPSHOT_OBJECT:
189 phase_string = "Phase Snapshot Object";
190 break;
191 case TRACE_EVENT_PHASE_DELETE_OBJECT:
192 phase_string = "Phase Delete Object";
193 break;
194 default:
195 phase_string.push_back(phase);
196 break;
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);
203 } else {
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());
218 // static
219 void TraceEventETWExport::AddCustomEvent(const char* name,
220 char const* phase,
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())
228 return;
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
239 } // namespace base