forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrace_event_etw_export_win.cc
239 lines (216 loc) · 8.19 KB
/
trace_event_etw_export_win.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/trace_event/trace_event_etw_export_win.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_impl.h"
// The GetProcAddress technique is borrowed from
// https://github.com/randomascii/main/tree/master/xperf/ETWProviders
//
// EVNTAPI is used in evntprov.h which is included by chrome_events_win.h.
// We define EVNTAPI without the DECLSPEC_IMPORT specifier so that we can
// implement these functions locally instead of using the import library, and
// can therefore still run on Windows XP.
#define EVNTAPI __stdcall
// Include the event register/write/unregister macros compiled from the manifest
// file. Note that this includes evntprov.h which requires a Vista+ Windows SDK.
//
// In SHARED_INTERMEDIATE_DIR.
#include "base/trace_event/etw_manifest/chrome_events_win.h" // NOLINT
namespace {
// Typedefs for use with GetProcAddress
typedef ULONG(__stdcall* tEventRegister)(LPCGUID ProviderId,
PENABLECALLBACK EnableCallback,
PVOID CallbackContext,
PREGHANDLE RegHandle);
typedef ULONG(__stdcall* tEventWrite)(REGHANDLE RegHandle,
PCEVENT_DESCRIPTOR EventDescriptor,
ULONG UserDataCount,
PEVENT_DATA_DESCRIPTOR UserData);
typedef ULONG(__stdcall* tEventUnregister)(REGHANDLE RegHandle);
tEventRegister EventRegisterProc = nullptr;
tEventWrite EventWriteProc = nullptr;
tEventUnregister EventUnregisterProc = nullptr;
} // namespace
// Redirector function for EventRegister. Called by macros in
// chrome_events_win.h
ULONG EVNTAPI EventRegister(LPCGUID ProviderId,
PENABLECALLBACK EnableCallback,
PVOID CallbackContext,
PREGHANDLE RegHandle) {
if (EventRegisterProc)
return EventRegisterProc(ProviderId, EnableCallback, CallbackContext,
RegHandle);
return 0;
}
// Redirector function for EventWrite. Called by macros in
// chrome_events_win.h
ULONG EVNTAPI EventWrite(REGHANDLE RegHandle,
PCEVENT_DESCRIPTOR EventDescriptor,
ULONG UserDataCount,
PEVENT_DATA_DESCRIPTOR UserData) {
if (EventWriteProc)
return EventWriteProc(RegHandle, EventDescriptor, UserDataCount, UserData);
return 0;
}
// Redirector function for EventUnregister. Called by macros in
// chrome_events_win.h
ULONG EVNTAPI EventUnregister(REGHANDLE RegHandle) {
if (EventUnregisterProc)
return EventUnregisterProc(RegHandle);
return 0;
}
namespace base {
namespace trace_event {
TraceEventETWExport::TraceEventETWExport() : ETWExportEnabled_(false) {
// Find Advapi32.dll. This should always succeed.
HMODULE AdvapiDLL = ::LoadLibraryW(L"Advapi32.dll");
if (AdvapiDLL) {
// Try to find the ETW functions. This will fail on XP.
EventRegisterProc = reinterpret_cast<tEventRegister>(
::GetProcAddress(AdvapiDLL, "EventRegister"));
EventWriteProc = reinterpret_cast<tEventWrite>(
::GetProcAddress(AdvapiDLL, "EventWrite"));
EventUnregisterProc = reinterpret_cast<tEventUnregister>(
::GetProcAddress(AdvapiDLL, "EventUnregister"));
// Register the ETW provider. If registration fails then the event logging
// calls will fail (on XP this call will do nothing).
EventRegisterChrome();
}
}
TraceEventETWExport::~TraceEventETWExport() {
EventUnregisterChrome();
}
// static
TraceEventETWExport* TraceEventETWExport::GetInstance() {
return Singleton<TraceEventETWExport,
StaticMemorySingletonTraits<TraceEventETWExport>>::get();
}
// static
void TraceEventETWExport::EnableETWExport() {
GetInstance()->ETWExportEnabled_ = true;
}
// static
void TraceEventETWExport::DisableETWExport() {
GetInstance()->ETWExportEnabled_ = false;
}
// static
void TraceEventETWExport::AddEvent(
char phase,
const unsigned char* category_group_enabled,
const char* name,
unsigned long long id,
int num_args,
const char** arg_names,
const unsigned char* arg_types,
const unsigned long long* arg_values,
const scoped_refptr<ConvertableToTraceFormat>* convertable_values) {
// We bail early in case exporting is disabled or no consumer is listening.
if (!GetInstance()->ETWExportEnabled_ || !EventEnabledChromeEvent())
return;
std::string phase_string;
switch (phase) {
case TRACE_EVENT_PHASE_BEGIN:
phase_string = "Begin";
break;
case TRACE_EVENT_PHASE_END:
phase_string = "End";
break;
case TRACE_EVENT_PHASE_COMPLETE:
phase_string = "Complete";
break;
case TRACE_EVENT_PHASE_INSTANT:
phase_string = "Instant";
break;
case TRACE_EVENT_PHASE_ASYNC_BEGIN:
phase_string = "Async Begin";
break;
case TRACE_EVENT_PHASE_ASYNC_STEP_INTO:
phase_string = "Async Step Into";
break;
case TRACE_EVENT_PHASE_ASYNC_STEP_PAST:
phase_string = "Async Step Past";
break;
case TRACE_EVENT_PHASE_ASYNC_END:
phase_string = "Async End";
break;
case TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN:
phase_string = "Nestable Async Begin";
break;
case TRACE_EVENT_PHASE_NESTABLE_ASYNC_END:
phase_string = "Nestable Async End";
break;
case TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT:
phase_string = "Nestable Async Instant";
break;
case TRACE_EVENT_PHASE_FLOW_BEGIN:
phase_string = "Phase Flow Begin";
break;
case TRACE_EVENT_PHASE_FLOW_STEP:
phase_string = "Phase Flow Step";
break;
case TRACE_EVENT_PHASE_FLOW_END:
phase_string = "Phase Flow End";
break;
case TRACE_EVENT_PHASE_METADATA:
phase_string = "Phase Metadata";
break;
case TRACE_EVENT_PHASE_COUNTER:
phase_string = "Phase Counter";
break;
case TRACE_EVENT_PHASE_SAMPLE:
phase_string = "Phase Sample";
break;
case TRACE_EVENT_PHASE_CREATE_OBJECT:
phase_string = "Phase Create Object";
break;
case TRACE_EVENT_PHASE_SNAPSHOT_OBJECT:
phase_string = "Phase Snapshot Object";
break;
case TRACE_EVENT_PHASE_DELETE_OBJECT:
phase_string = "Phase Delete Object";
break;
default:
phase_string.push_back(phase);
break;
}
std::string arg_values_string[3];
for (int i = 0; i < num_args; i++) {
if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
convertable_values[i]->AppendAsTraceFormat(arg_values_string + i);
} else {
TraceEvent::TraceValue trace_event;
trace_event.as_uint = arg_values[i];
TraceEvent::AppendValueAsJSON(arg_types[i], trace_event,
arg_values_string + i);
}
}
EventWriteChromeEvent(
name, phase_string.c_str(), num_args > 0 ? arg_names[0] : "",
arg_values_string[0].c_str(), num_args > 1 ? arg_names[1] : "",
arg_values_string[1].c_str(), num_args > 2 ? arg_names[2] : "",
arg_values_string[2].c_str());
}
// static
void TraceEventETWExport::AddCustomEvent(const char* name,
char const* phase,
const char* arg_name_1,
const char* arg_value_1,
const char* arg_name_2,
const char* arg_value_2,
const char* arg_name_3,
const char* arg_value_3) {
if (!GetInstance()->ETWExportEnabled_ || !EventEnabledChromeEvent())
return;
EventWriteChromeEvent(name, phase, arg_name_1, arg_value_1, arg_name_2,
arg_value_2, arg_name_3, arg_value_3);
}
void TraceEventETWExport::Resurrect() {
StaticMemorySingletonTraits<TraceEventETWExport>::Resurrect();
}
} // namespace trace_event
} // namespace base