summaryrefslogtreecommitdiffstats
path: root/base/trace_event
diff options
context:
space:
mode:
authorgeorgesak <georgesak@chromium.org>2015-04-16 02:25:19 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-16 09:25:30 +0000
commit28ad5e6b1100a7f0d25a5e6741f7241a86cf61bd (patch)
tree3885c9798551719729e067833a42150b58856cc1 /base/trace_event
parentc1379a6aa216b1b63620e6a1a9cf4fb90c430d96 (diff)
downloadchromium_src-28ad5e6b1100a7f0d25a5e6741f7241a86cf61bd.zip
chromium_src-28ad5e6b1100a7f0d25a5e6741f7241a86cf61bd.tar.gz
chromium_src-28ad5e6b1100a7f0d25a5e6741f7241a86cf61bd.tar.bz2
Add option to export tracing events to ETW.
- Exporting of ETW events can be turned on using --trace-export-events-to-etw. BUG= Committed: https://crrev.com/1cc86c4f686869f32dfede093a07828c73563892 Cr-Commit-Position: refs/heads/master@{#324982} Review URL: https://codereview.chromium.org/1038453002 Cr-Commit-Position: refs/heads/master@{#325408}
Diffstat (limited to 'base/trace_event')
-rw-r--r--base/trace_event/BUILD.gn6
-rw-r--r--base/trace_event/etw_manifest/BUILD.gn37
-rw-r--r--base/trace_event/etw_manifest/BUILD/message_compiler.py16
-rw-r--r--base/trace_event/etw_manifest/chrome_events_win.man84
-rw-r--r--base/trace_event/etw_manifest/etw_manifest.gyp39
-rw-r--r--base/trace_event/trace_event.gypi2
-rw-r--r--base/trace_event/trace_event.h7
-rw-r--r--base/trace_event/trace_event_etw_export_win.cc239
-rw-r--r--base/trace_event/trace_event_etw_export_win.h73
-rw-r--r--base/trace_event/trace_event_impl.cc15
-rw-r--r--base/trace_event/trace_event_impl.h3
11 files changed, 518 insertions, 3 deletions
diff --git a/base/trace_event/BUILD.gn b/base/trace_event/BUILD.gn
index d32bd28..ed8761f 100644
--- a/base/trace_event/BUILD.gn
+++ b/base/trace_event/BUILD.gn
@@ -26,6 +26,8 @@ source_set("trace_event") {
"trace_event_android.cc",
"trace_event_argument.cc",
"trace_event_argument.h",
+ "trace_event_etw_export_win.cc",
+ "trace_event_etw_export_win.h",
"trace_event_impl.cc",
"trace_event_impl.h",
"trace_event_impl_constants.cc",
@@ -63,6 +65,10 @@ source_set("trace_event") {
"//base/third_party/dynamic_annotations",
]
+ if (is_win) {
+ deps += [ "//base/trace_event/etw_manifest:chrome_events_win" ]
+ }
+
allow_circular_includes_from = [
"//base/debug",
"//base/memory",
diff --git a/base/trace_event/etw_manifest/BUILD.gn b/base/trace_event/etw_manifest/BUILD.gn
new file mode 100644
index 0000000..07cf80e
--- /dev/null
+++ b/base/trace_event/etw_manifest/BUILD.gn
@@ -0,0 +1,37 @@
+# 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.
+
+assert(is_win, "This only runs on Windows.")
+
+# Makes the .h/.rc files from the .man file.
+action("chrome_events_win") {
+ visibility = [
+ "//base/trace_event/*",
+ "//chrome:main_dll",
+ ]
+ script = "build/message_compiler.py"
+
+ sources = [
+ "chrome_events_win.man",
+ ]
+
+ outputs = [
+ "$target_gen_dir/chrome_events_win.h",
+ "$target_gen_dir/chrome_events_win.rc",
+ ]
+
+ args = [
+ # Where to put the header.
+ "-h",
+ rebase_path("$target_gen_dir", root_build_dir),
+
+ # Where to put the .rc file.
+ "-r",
+ rebase_path("$target_gen_dir", root_build_dir),
+
+ # Generate the user-mode code.
+ "-um",
+ rebase_path("chrome_events_win.man", root_build_dir),
+ ]
+}
diff --git a/base/trace_event/etw_manifest/BUILD/message_compiler.py b/base/trace_event/etw_manifest/BUILD/message_compiler.py
new file mode 100644
index 0000000..be5927d
--- /dev/null
+++ b/base/trace_event/etw_manifest/BUILD/message_compiler.py
@@ -0,0 +1,16 @@
+# 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.
+
+# Runs the Microsoft Message Compiler (mc.exe). This Python adapter is for the
+# GN build, which can only run Python and not native binaries.
+
+import subprocess
+import sys
+
+# mc writes to stderr, so this explicily redirects to stdout and eats it.
+try:
+ subprocess.check_output(["mc.exe"] + sys.argv[1:], stderr=subprocess.STDOUT)
+except subprocess.CalledProcessError as e:
+ print e.output
+ sys.exit(e.returncode)
diff --git a/base/trace_event/etw_manifest/chrome_events_win.man b/base/trace_event/etw_manifest/chrome_events_win.man
new file mode 100644
index 0000000..10a8ddf
--- /dev/null
+++ b/base/trace_event/etw_manifest/chrome_events_win.man
@@ -0,0 +1,84 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes'?>
+<instrumentationManifest
+ xmlns="http://schemas.microsoft.com/win/2004/08/events"
+ xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd"
+ >
+ <instrumentation>
+ <events>
+ <provider
+ guid="{D2D578D9-2936-45B6-A09f-30E32715F42D}"
+ messageFileName="chrome.dll"
+ name="Chrome"
+ resourceFileName="chrome.dll"
+ symbol="CHROME"
+ >
+ <channels>
+ <importChannel
+ chid="SYSTEM"
+ name="System"
+ />
+ </channels>
+ <templates>
+ <template tid="tid_chrome_event">
+ <data
+ inType="win:AnsiString"
+ name="Name"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Phase"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Name 1"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Value 1"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Name 2"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Value 2"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Name 3"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Value 3"
+ />
+ </template>
+ </templates>
+ <events>
+ <event
+ channel="SYSTEM"
+ level="win:Informational"
+ message="$(string.ChromeEvent.EventMessage)"
+ opcode="win:Info"
+ symbol="ChromeEvent"
+ template="tid_chrome_event"
+ value="1"
+ />
+ </events>
+ </provider>
+ </events>
+ </instrumentation>
+ <localization xmlns="http://schemas.microsoft.com/win/2004/08/events">
+ <resources culture="en-US">
+ <stringTable>
+ <string
+ id="ChromeEvent.EventMessage"
+ value="Chrome Event: %1 (%2)"
+ />
+ </stringTable>
+ </resources>
+ </localization>
+</instrumentationManifest>
diff --git a/base/trace_event/etw_manifest/etw_manifest.gyp b/base/trace_event/etw_manifest/etw_manifest.gyp
new file mode 100644
index 0000000..b0a8712
--- /dev/null
+++ b/base/trace_event/etw_manifest/etw_manifest.gyp
@@ -0,0 +1,39 @@
+# 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.
+{
+ 'targets': [
+ {
+ # GN version: //base/trace_event/etw_manifest/BUILD.gn
+ 'target_name': 'etw_manifest',
+ 'type': 'static_library',
+ 'conditions': [
+ ['OS=="win"', {
+ 'sources': [
+ 'chrome_events_win.man',
+ ],
+ 'variables': {
+ 'man_output_dir': '<(SHARED_INTERMEDIATE_DIR)/base/trace_event/etw_manifest',
+ },
+ 'rules': [{
+ # Rule to run the message compiler.
+ 'rule_name': 'message_compiler',
+ 'extension': 'man',
+ 'outputs': [
+ '<(man_output_dir)/chrome_events_win.h',
+ '<(man_output_dir)/chrome_events_win.rc',
+ ],
+ 'action': [
+ 'mc.exe',
+ '-h', '<(man_output_dir)',
+ '-r', '<(man_output_dir)/.',
+ '-um',
+ '<(RULE_INPUT_PATH)',
+ ],
+ 'message': 'Running message compiler on <(RULE_INPUT_PATH)',
+ }],
+ }],
+ ],
+ }
+ ]
+}
diff --git a/base/trace_event/trace_event.gypi b/base/trace_event/trace_event.gypi
index 9be9149..392f063 100644
--- a/base/trace_event/trace_event.gypi
+++ b/base/trace_event/trace_event.gypi
@@ -26,6 +26,8 @@
'trace_event/trace_event_android.cc',
'trace_event/trace_event_argument.cc',
'trace_event/trace_event_argument.h',
+ 'trace_event/trace_event_etw_export_win.cc',
+ 'trace_event/trace_event_etw_export_win.h',
'trace_event/trace_event_impl.cc',
'trace_event/trace_event_impl.h',
'trace_event/trace_event_impl_constants.cc',
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index 1bf9429..7c4d3ab 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -828,9 +828,10 @@
category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE)
#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
- UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \
- (base::trace_event::TraceLog::ENABLED_FOR_RECORDING | \
- base::trace_event::TraceLog::ENABLED_FOR_EVENT_CALLBACK))
+ UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \
+ (base::trace_event::TraceLog::ENABLED_FOR_RECORDING | \
+ base::trace_event::TraceLog::ENABLED_FOR_EVENT_CALLBACK | \
+ base::trace_event::TraceLog::ENABLED_FOR_ETW_EXPORT))
// Macro to efficiently determine if a given category group is enabled.
#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
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 0000000..f7f9ecc
--- /dev/null
+++ b/base/trace_event/trace_event_etw_export_win.cc
@@ -0,0 +1,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
diff --git a/base/trace_event/trace_event_etw_export_win.h b/base/trace_event/trace_event_etw_export_win.h
new file mode 100644
index 0000000..0a551c3
--- /dev/null
+++ b/base/trace_event/trace_event_etw_export_win.h
@@ -0,0 +1,73 @@
+// 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.
+
+// This file contains the Windows-specific exporting to ETW.
+#ifndef BASE_TRACE_EVENT_TRACE_ETW_EXPORT_H_
+#define BASE_TRACE_EVENT_TRACE_ETW_EXPORT_H_
+
+#include "base/base_export.h"
+#include "base/trace_event/trace_event_impl.h"
+
+// Fwd.
+template <typename Type>
+struct StaticMemorySingletonTraits;
+
+namespace base {
+namespace trace_event {
+
+class BASE_EXPORT TraceEventETWExport {
+ public:
+ ~TraceEventETWExport();
+
+ // Retrieves the singleton.
+ // Note that this may return NULL post-AtExit processing.
+ static TraceEventETWExport* GetInstance();
+
+ // Enables/disables exporting of events to ETW. If disabled,
+ // AddEvent and AddCustomEvent will simply return when called.
+ static void EnableETWExport();
+ static void DisableETWExport();
+
+ static bool isETWExportEnabled() { return GetInstance()->ETWExportEnabled_; }
+
+ // Exports an event to ETW. This is mainly used in
+ // TraceLog::AddTraceEventWithThreadIdAndTimestamp to export internal events.
+ static void 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);
+
+ // Exports an event to ETW. This should be used when exporting an event only
+ // to ETW. Supports three arguments to be passed to ETW.
+ // TODO(georgesak): Allow different providers.
+ static void 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);
+
+ void Resurrect();
+
+ private:
+ bool ETWExportEnabled_;
+ // Ensure only the provider can construct us.
+ friend struct StaticMemorySingletonTraits<TraceEventETWExport>;
+ TraceEventETWExport();
+
+ DISALLOW_COPY_AND_ASSIGN(TraceEventETWExport);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_TRACE_ETW_EXPORT_H_
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index f312c71..12f9598 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -36,6 +36,7 @@
#include "base/trace_event/trace_event_synthetic_delay.h"
#if defined(OS_WIN)
+#include "base/trace_event/trace_event_etw_export_win.h"
#include "base/trace_event/trace_event_win.h"
#endif
@@ -1292,6 +1293,11 @@ void TraceLog::UpdateCategoryGroupEnabledFlag(size_t category_index) {
if (event_callback_ &&
event_callback_category_filter_.IsCategoryGroupEnabled(category_group))
enabled_flag |= ENABLED_FOR_EVENT_CALLBACK;
+#if defined(OS_WIN)
+ if (base::trace_event::TraceEventETWExport::isETWExportEnabled())
+ enabled_flag |= ENABLED_FOR_ETW_EXPORT;
+#endif
+
g_category_group_enabled[category_index] = enabled_flag;
}
@@ -1984,6 +1990,15 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
}
}
+#if defined(OS_WIN)
+ // This is done sooner rather than later, to avoid creating the event and
+ // acquiring the lock, which is not needed for ETW as it's already threadsafe.
+ if (*category_group_enabled & ENABLED_FOR_ETW_EXPORT)
+ TraceEventETWExport::AddEvent(phase, category_group_enabled, name, id,
+ num_args, arg_names, arg_types, arg_values,
+ convertable_values);
+#endif // OS_WIN
+
std::string console_message;
if (*category_group_enabled &
(ENABLED_FOR_RECORDING | ENABLED_FOR_MONITORING)) {
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
index 1d00a71..33a85c9 100644
--- a/base/trace_event/trace_event_impl.h
+++ b/base/trace_event/trace_event_impl.h
@@ -26,6 +26,7 @@
// Older style trace macros with explicit id and extra data
// Only these macros result in publishing data to ETW as currently implemented.
+// TODO(georgesak): Update/replace these with new ETW macros.
#define TRACE_EVENT_BEGIN_ETW(name, id, extra) \
base::trace_event::TraceLog::AddTraceEventEtw( \
TRACE_EVENT_PHASE_BEGIN, \
@@ -446,6 +447,8 @@ class BASE_EXPORT TraceLog {
ENABLED_FOR_MONITORING = 1 << 1,
// Category group enabled by SetEventCallbackEnabled().
ENABLED_FOR_EVENT_CALLBACK = 1 << 2,
+ // Category group enabled to export events to ETW.
+ ENABLED_FOR_ETW_EXPORT = 1 << 3
};
static TraceLog* GetInstance();