Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / base / trace_event / trace_event_etw_export_win.cc
blobd199bf5c8b2e4f6f359335b55e045d393adcb0b5
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/google/UIforETW/tree/master/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 *RegHandle = 0;
55 return 0;
58 // Redirector function for EventWrite. Called by macros in
59 // chrome_events_win.h
60 ULONG EVNTAPI EventWrite(REGHANDLE RegHandle,
61 PCEVENT_DESCRIPTOR EventDescriptor,
62 ULONG UserDataCount,
63 PEVENT_DATA_DESCRIPTOR UserData) {
64 if (EventWriteProc)
65 return EventWriteProc(RegHandle, EventDescriptor, UserDataCount, UserData);
66 return 0;
69 // Redirector function for EventUnregister. Called by macros in
70 // chrome_events_win.h
71 ULONG EVNTAPI EventUnregister(REGHANDLE RegHandle) {
72 if (EventUnregisterProc)
73 return EventUnregisterProc(RegHandle);
74 return 0;
77 namespace base {
78 namespace trace_event {
80 TraceEventETWExport::TraceEventETWExport() : ETWExportEnabled_(false) {
81 // Find Advapi32.dll. This should always succeed.
82 HMODULE AdvapiDLL = ::LoadLibraryW(L"Advapi32.dll");
83 if (AdvapiDLL) {
84 // Try to find the ETW functions. This will fail on XP.
85 EventRegisterProc = reinterpret_cast<tEventRegister>(
86 ::GetProcAddress(AdvapiDLL, "EventRegister"));
87 EventWriteProc = reinterpret_cast<tEventWrite>(
88 ::GetProcAddress(AdvapiDLL, "EventWrite"));
89 EventUnregisterProc = reinterpret_cast<tEventUnregister>(
90 ::GetProcAddress(AdvapiDLL, "EventUnregister"));
92 // Register the ETW provider. If registration fails then the event logging
93 // calls will fail (on XP this call will do nothing).
94 EventRegisterChrome();
98 TraceEventETWExport::~TraceEventETWExport() {
99 EventUnregisterChrome();
102 // static
103 TraceEventETWExport* TraceEventETWExport::GetInstance() {
104 return Singleton<TraceEventETWExport,
105 StaticMemorySingletonTraits<TraceEventETWExport>>::get();
108 // static
109 void TraceEventETWExport::EnableETWExport() {
110 if (GetInstance())
111 GetInstance()->ETWExportEnabled_ = true;
114 // static
115 void TraceEventETWExport::DisableETWExport() {
116 if (GetInstance())
117 GetInstance()->ETWExportEnabled_ = false;
120 // static
121 void TraceEventETWExport::AddEvent(
122 char phase,
123 const unsigned char* category_group_enabled,
124 const char* name,
125 unsigned long long id,
126 int num_args,
127 const char** arg_names,
128 const unsigned char* arg_types,
129 const unsigned long long* arg_values,
130 const scoped_refptr<ConvertableToTraceFormat>* convertable_values) {
131 // We bail early in case exporting is disabled or no consumer is listening.
132 if (!GetInstance() || !GetInstance()->ETWExportEnabled_ ||
133 !EventEnabledChromeEvent())
134 return;
136 const char* phase_string = nullptr;
137 // Space to store the phase identifier and null-terminator, when needed.
138 char phase_buffer[2];
139 switch (phase) {
140 case TRACE_EVENT_PHASE_BEGIN:
141 phase_string = "Begin";
142 break;
143 case TRACE_EVENT_PHASE_END:
144 phase_string = "End";
145 break;
146 case TRACE_EVENT_PHASE_COMPLETE:
147 phase_string = "Complete";
148 break;
149 case TRACE_EVENT_PHASE_INSTANT:
150 phase_string = "Instant";
151 break;
152 case TRACE_EVENT_PHASE_ASYNC_BEGIN:
153 phase_string = "Async Begin";
154 break;
155 case TRACE_EVENT_PHASE_ASYNC_STEP_INTO:
156 phase_string = "Async Step Into";
157 break;
158 case TRACE_EVENT_PHASE_ASYNC_STEP_PAST:
159 phase_string = "Async Step Past";
160 break;
161 case TRACE_EVENT_PHASE_ASYNC_END:
162 phase_string = "Async End";
163 break;
164 case TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN:
165 phase_string = "Nestable Async Begin";
166 break;
167 case TRACE_EVENT_PHASE_NESTABLE_ASYNC_END:
168 phase_string = "Nestable Async End";
169 break;
170 case TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT:
171 phase_string = "Nestable Async Instant";
172 break;
173 case TRACE_EVENT_PHASE_FLOW_BEGIN:
174 phase_string = "Phase Flow Begin";
175 break;
176 case TRACE_EVENT_PHASE_FLOW_STEP:
177 phase_string = "Phase Flow Step";
178 break;
179 case TRACE_EVENT_PHASE_FLOW_END:
180 phase_string = "Phase Flow End";
181 break;
182 case TRACE_EVENT_PHASE_METADATA:
183 phase_string = "Phase Metadata";
184 break;
185 case TRACE_EVENT_PHASE_COUNTER:
186 phase_string = "Phase Counter";
187 break;
188 case TRACE_EVENT_PHASE_SAMPLE:
189 phase_string = "Phase Sample";
190 break;
191 case TRACE_EVENT_PHASE_CREATE_OBJECT:
192 phase_string = "Phase Create Object";
193 break;
194 case TRACE_EVENT_PHASE_SNAPSHOT_OBJECT:
195 phase_string = "Phase Snapshot Object";
196 break;
197 case TRACE_EVENT_PHASE_DELETE_OBJECT:
198 phase_string = "Phase Delete Object";
199 break;
200 default:
201 phase_buffer[0] = phase;
202 phase_buffer[1] = 0;
203 phase_string = phase_buffer;
204 break;
207 std::string arg_values_string[3];
208 for (int i = 0; i < num_args; i++) {
209 if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
210 // Temporarily do nothing here. This function consumes 1/3 to 1/2 of
211 // *total* process CPU time when ETW tracing, and many of the strings
212 // created exceed WPA's 4094 byte limit and are shown as:
213 // "Unable to parse data". See crbug.com/488257
214 //convertable_values[i]->AppendAsTraceFormat(arg_values_string + i);
215 } else {
216 TraceEvent::TraceValue trace_event;
217 trace_event.as_uint = arg_values[i];
218 TraceEvent::AppendValueAsJSON(arg_types[i], trace_event,
219 arg_values_string + i);
223 EventWriteChromeEvent(
224 name, phase_string, num_args > 0 ? arg_names[0] : "",
225 arg_values_string[0].c_str(), num_args > 1 ? arg_names[1] : "",
226 arg_values_string[1].c_str(), num_args > 2 ? arg_names[2] : "",
227 arg_values_string[2].c_str());
230 // static
231 void TraceEventETWExport::AddCustomEvent(const char* name,
232 char const* phase,
233 const char* arg_name_1,
234 const char* arg_value_1,
235 const char* arg_name_2,
236 const char* arg_value_2,
237 const char* arg_name_3,
238 const char* arg_value_3) {
239 if (!GetInstance() || !GetInstance()->ETWExportEnabled_ ||
240 !EventEnabledChromeEvent())
241 return;
243 EventWriteChromeEvent(name, phase, arg_name_1, arg_value_1, arg_name_2,
244 arg_value_2, arg_name_3, arg_value_3);
247 void TraceEventETWExport::Resurrect() {
248 StaticMemorySingletonTraits<TraceEventETWExport>::Resurrect();
251 } // namespace trace_event
252 } // namespace base