Chromium Code Reviews| 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..434e2d0cbac78515257bfa223db0d9a395d2e6fa |
| --- /dev/null |
| +++ b/base/trace_event/trace_event_etw_export_win.cc |
| @@ -0,0 +1,237 @@ |
| +// 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/someonegg/heap_monitor/tree/master/MultiProvider |
|
brucedawson
2015/03/29 20:39:22
Can you update this reference to this address:
htt
Georges Khalil
2015/03/30 14:50:05
Oops, didn't know that it was copied, should have
|
| +// |
| +// 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. |
| +#include "base/trace_event/etw_manifest/chrome_events_win.h" // In SHARED_INTERMEDIATE_DIR. NOLINT. |
|
brucedawson
2015/03/29 20:39:22
Move the comment to stay in line limits?
Georges Khalil
2015/03/30 14:50:05
Done.
- Moved In SHARED_INTERMEDIATE_DIR to earli
|
| + |
| +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 |