| 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
|
|
|