summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/trace_event/trace_event_etw_export_win.cc135
-rw-r--r--base/trace_event/trace_event_etw_export_win.h28
-rw-r--r--base/trace_event/trace_event_impl.cc4
3 files changed, 156 insertions, 11 deletions
diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc
index d199bf5..47e6353 100644
--- a/base/trace_event/trace_event_etw_export_win.cc
+++ b/base/trace_event/trace_event_etw_export_win.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
+#include "base/strings/string_tokenizer.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_impl.h"
@@ -40,6 +41,55 @@ typedef ULONG(__stdcall* tEventUnregister)(REGHANDLE RegHandle);
tEventRegister EventRegisterProc = nullptr;
tEventWrite EventWriteProc = nullptr;
tEventUnregister EventUnregisterProc = nullptr;
+
+// |filtered_event_group_names| contains the event categories that can be
+// exported individually. These categories can be enabled by passing the correct
+// keyword when starting the trace. A keyword is a 64-bit flag and we attribute
+// one bit per category. We can therefore enable a particular category by
+// setting its corresponding bit in the keyword. For events that are not present
+// in |filtered_event_group_names|, we have two bits that control their
+// behaviour. When bit 61 is enabled, any event that is not disabled by default
+// (ie. doesn't start with disabled-by-default-) will be exported. Likewise,
+// when bit 62 is enabled, any event that is disabled by default will be
+// exported.
+//
+// Note that bit 63 (MSB) must always be set, otherwise tracing will be disabled
+// by ETW. Therefore, the keyword will always be greater than
+// 0x8000000000000000.
+//
+// Examples of passing keywords to the provider using xperf:
+// # This exports "benchmark" and "cc" events
+// xperf -start chrome -on Chrome:0x8000000000000009
+//
+// # This exports "gpu", "netlog" and all other events that are not disabled by
+// # default
+// xperf -start chrome -on Chrome:0xA0000000000000A0
+//
+// More info about starting a trace and keyword can be obtained by using the
+// help section of xperf (xperf -help start). Note that xperf documentation
+// refers to keywords as flags and there are two ways to enable them, using
+// group names or the hex representation. We only support the latter. Also, we
+// ignore the level.
+const char* const filtered_event_group_names[] = {
+ "benchmark", // 0x1
+ "blink", // 0x2
+ "browser", // 0x4
+ "cc", // 0x8
+ "evdev", // 0x10
+ "gpu", // 0x20
+ "input", // 0x40
+ "netlog", // 0x80
+ "renderer.scheduler", // 0x100
+ "toplevel", // 0x200
+ "v8", // 0x400
+ "disabled-by-default-cc.debug", // 0x800
+ "disabled-by-default-cc.debug.picture", // 0x1000
+ "disabled-by-default-toplevel.flow"}; // 0x2000
+const char* other_events_group_name = "__OTHER_EVENTS"; // 0x2000000000000000
+const char* disabled_other_events_group_name =
+ "__DISABLED_OTHER_EVENTS"; // 0x4000000000000000
+uint64 other_events_keyword_bit = 1ULL << 61;
+uint64 disabled_other_events_keyword_bit = 1ULL << 62;
} // namespace
// Redirector function for EventRegister. Called by macros in
@@ -77,7 +127,8 @@ ULONG EVNTAPI EventUnregister(REGHANDLE RegHandle) {
namespace base {
namespace trace_event {
-TraceEventETWExport::TraceEventETWExport() : ETWExportEnabled_(false) {
+TraceEventETWExport::TraceEventETWExport()
+ : etw_export_enabled_(false), etw_match_any_keyword_(0ULL) {
// Find Advapi32.dll. This should always succeed.
HMODULE AdvapiDLL = ::LoadLibraryW(L"Advapi32.dll");
if (AdvapiDLL) {
@@ -92,6 +143,8 @@ TraceEventETWExport::TraceEventETWExport() : ETWExportEnabled_(false) {
// Register the ETW provider. If registration fails then the event logging
// calls will fail (on XP this call will do nothing).
EventRegisterChrome();
+
+ UpdateEnabledCategories();
}
}
@@ -108,13 +161,13 @@ TraceEventETWExport* TraceEventETWExport::GetInstance() {
// static
void TraceEventETWExport::EnableETWExport() {
if (GetInstance())
- GetInstance()->ETWExportEnabled_ = true;
+ GetInstance()->etw_export_enabled_ = true;
}
// static
void TraceEventETWExport::DisableETWExport() {
if (GetInstance())
- GetInstance()->ETWExportEnabled_ = false;
+ GetInstance()->etw_export_enabled_ = false;
}
// static
@@ -129,7 +182,7 @@ void TraceEventETWExport::AddEvent(
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() || !GetInstance()->ETWExportEnabled_ ||
+ if (!GetInstance() || !GetInstance()->etw_export_enabled_ ||
!EventEnabledChromeEvent())
return;
@@ -211,7 +264,7 @@ void TraceEventETWExport::AddEvent(
// *total* process CPU time when ETW tracing, and many of the strings
// created exceed WPA's 4094 byte limit and are shown as:
// "Unable to parse data". See crbug.com/488257
- //convertable_values[i]->AppendAsTraceFormat(arg_values_string + i);
+ // convertable_values[i]->AppendAsTraceFormat(arg_values_string + i);
} else {
TraceEvent::TraceValue trace_event;
trace_event.as_uint = arg_values[i];
@@ -236,7 +289,7 @@ void TraceEventETWExport::AddCustomEvent(const char* name,
const char* arg_value_2,
const char* arg_name_3,
const char* arg_value_3) {
- if (!GetInstance() || !GetInstance()->ETWExportEnabled_ ||
+ if (!GetInstance() || !GetInstance()->etw_export_enabled_ ||
!EventEnabledChromeEvent())
return;
@@ -248,5 +301,75 @@ void TraceEventETWExport::Resurrect() {
StaticMemorySingletonTraits<TraceEventETWExport>::Resurrect();
}
+// static
+bool TraceEventETWExport::IsCategoryGroupEnabled(
+ const char* category_group_name) {
+ DCHECK(category_group_name);
+ auto instance = GetInstance();
+ if (instance == nullptr)
+ return false;
+
+ if (!instance->IsETWExportEnabled())
+ return false;
+
+ CStringTokenizer category_group_tokens(
+ category_group_name, category_group_name + strlen(category_group_name),
+ ",");
+ while (category_group_tokens.GetNext()) {
+ std::string category_group_token = category_group_tokens.token();
+ if (instance->IsCategoryEnabled(category_group_token.c_str())) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void TraceEventETWExport::UpdateEnabledCategories() {
+ // If the keyword has changed, update each category.
+ // Chrome_Context.MatchAnyKeyword is set by UIforETW (or other ETW trace
+ // recording tools) using the ETW infrastructure. This value will be set in
+ // all Chrome processes that have registered their ETW provider.
+ if (etw_match_any_keyword_ != CHROME_Context.MatchAnyKeyword) {
+ etw_match_any_keyword_ = CHROME_Context.MatchAnyKeyword;
+ for (int i = 0; i < ARRAYSIZE(filtered_event_group_names); i++) {
+ if (etw_match_any_keyword_ & (1ULL << i)) {
+ categories_status_[filtered_event_group_names[i]] = true;
+ } else {
+ categories_status_[filtered_event_group_names[i]] = false;
+ }
+ }
+ }
+ // Also update the two default categories.
+ if (etw_match_any_keyword_ & other_events_keyword_bit) {
+ categories_status_[other_events_group_name] = true;
+ } else {
+ categories_status_[other_events_group_name] = false;
+ }
+ if (etw_match_any_keyword_ & disabled_other_events_keyword_bit) {
+ categories_status_[disabled_other_events_group_name] = true;
+ } else {
+ categories_status_[disabled_other_events_group_name] = false;
+ }
+}
+
+bool TraceEventETWExport::IsCategoryEnabled(const char* category_name) const {
+ // Try to find the category and return its status if found
+ auto it = categories_status_.find(category_name);
+ if (it != categories_status_.end())
+ return it->second;
+
+ // Otherwise return the corresponding default status by first checking if the
+ // category is disabled by default.
+ if (StringPiece(category_name).starts_with("disabled-by-default")) {
+ DCHECK(categories_status_.find(disabled_other_events_group_name) !=
+ categories_status_.end());
+ return categories_status_.find(disabled_other_events_group_name)->second;
+ } else {
+ DCHECK(categories_status_.find(other_events_group_name) !=
+ categories_status_.end());
+ return categories_status_.find(other_events_group_name)->second;
+ }
+}
+
} // 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
index eefe820..a9b580c 100644
--- a/base/trace_event/trace_event_etw_export_win.h
+++ b/base/trace_event/trace_event_etw_export_win.h
@@ -6,7 +6,10 @@
#ifndef BASE_TRACE_EVENT_TRACE_EVENT_ETW_EXPORT_WIN_H_
#define BASE_TRACE_EVENT_TRACE_EVENT_ETW_EXPORT_WIN_H_
+#include <map>
+
#include "base/base_export.h"
+#include "base/strings/string_piece.h"
#include "base/trace_event/trace_event_impl.h"
// Fwd.
@@ -29,8 +32,8 @@ class BASE_EXPORT TraceEventETWExport {
static void EnableETWExport();
static void DisableETWExport();
- static bool isETWExportEnabled() {
- return (GetInstance() && GetInstance()->ETWExportEnabled_);
+ static bool IsETWExportEnabled() {
+ return (GetInstance() && GetInstance()->etw_match_any_keyword_);
}
// Exports an event to ETW. This is mainly used in
@@ -50,7 +53,7 @@ class BASE_EXPORT TraceEventETWExport {
// 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* phase,
const char* arg_name_1,
const char* arg_value_1,
const char* arg_name_2,
@@ -58,14 +61,31 @@ class BASE_EXPORT TraceEventETWExport {
const char* arg_name_3,
const char* arg_value_3);
+ // Returns true if any category in the group is enabled.
+ static bool IsCategoryGroupEnabled(const char* category_group_name);
+
void Resurrect();
private:
- bool ETWExportEnabled_;
// Ensure only the provider can construct us.
friend struct StaticMemorySingletonTraits<TraceEventETWExport>;
TraceEventETWExport();
+ // Updates the list of enabled categories by consulting the ETW keyword.
+ void UpdateEnabledCategories();
+
+ // Returns true if the category is enabled.
+ bool IsCategoryEnabled(const char* category_name) const;
+
+ // True if ETW is enabled. Allows hiding the exporting behind a flag.
+ bool etw_export_enabled_;
+
+ // Maps category names to their status (enabled/disabled).
+ std::map<base::StringPiece, bool> categories_status_;
+
+ // Local copy of the ETW keyword.
+ uint64 etw_match_any_keyword_;
+
DISALLOW_COPY_AND_ASSIGN(TraceEventETWExport);
};
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index 3925710..1fc2256 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -1381,8 +1381,10 @@ void TraceLog::UpdateCategoryGroupEnabledFlag(size_t category_index) {
event_callback_trace_config_.IsCategoryGroupEnabled(category_group))
enabled_flag |= ENABLED_FOR_EVENT_CALLBACK;
#if defined(OS_WIN)
- if (base::trace_event::TraceEventETWExport::isETWExportEnabled())
+ if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled(
+ category_group)) {
enabled_flag |= ENABLED_FOR_ETW_EXPORT;
+ }
#endif
g_category_group_enabled[category_index] = enabled_flag;