Index: base/trace_event/trace_event_etw_export_win.cc |
diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e12782c15939c8f4bff08c5e5e7a7c40f31508e0 |
--- /dev/null |
+++ b/base/trace_event/trace_event_etw_export_win.cc |
@@ -0,0 +1,239 @@ |
+// Copyright (c) 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 |