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 |
index e61a7b29645992d0e160d3d25cd91e2bc5fb58f9..00cc8c2e244dcb6d1e8e21f125da509f18664fec 100644 |
--- a/base/trace_event/trace_event_etw_export_win.cc |
+++ b/base/trace_event/trace_event_etw_export_win.cc |
@@ -9,6 +9,7 @@ |
#include "base/memory/singleton.h" |
#include "base/strings/string_tokenizer.h" |
#include "base/strings/utf_string_conversions.h" |
+#include "base/threading/platform_thread.h" |
#include "base/trace_event/trace_event.h" |
#include "base/trace_event/trace_event_impl.h" |
@@ -90,6 +91,30 @@ 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; |
+ |
+// This object will be created by each process. It's a background (low-priority) |
+// thread that will monitor the ETW keyword for any changes. |
+class ETWKeywordUpdateThread : public base::PlatformThread::Delegate { |
+ public: |
+ ETWKeywordUpdateThread() {} |
+ ~ETWKeywordUpdateThread() override {} |
+ |
+ // Implementation of PlatformThread::Delegate: |
+ void ThreadMain() override { |
+ base::PlatformThread::SetName("ETW Keyword Update Thread"); |
+ base::TimeDelta sleep_time = |
+ base::TimeDelta::FromMilliseconds(kUpdateTimerDelayMs); |
+ while (1) { |
+ base::PlatformThread::Sleep(sleep_time); |
+ base::trace_event::TraceEventETWExport::UpdateETWKeyword(); |
+ } |
+ } |
+ |
+ private: |
+ // Time between checks for ETW keyword changes (in milliseconds). |
+ unsigned int kUpdateTimerDelayMs = 1000; |
+}; |
+ |
} // namespace |
// Redirector function for EventRegister. Called by macros in |
@@ -143,8 +168,6 @@ TraceEventETWExport::TraceEventETWExport() |
// Register the ETW provider. If registration fails then the event logging |
// calls will fail (on XP this call will do nothing). |
EventRegisterChrome(); |
- |
- UpdateEnabledCategories(); |
} |
} |
@@ -160,19 +183,33 @@ TraceEventETWExport* TraceEventETWExport::GetInstance() { |
// static |
void TraceEventETWExport::EnableETWExport() { |
- if (GetInstance()) |
- GetInstance()->etw_export_enabled_ = true; |
+ auto* instance = GetInstance(); |
+ if (instance && !instance->etw_export_enabled_) { |
+ instance->etw_export_enabled_ = true; |
+ // Sync the enabled categories with ETW by calling UpdateEnabledCategories() |
+ // that checks the keyword. Then create a thread that will call that same |
+ // function periodically, to make sure we stay in sync. |
+ instance->UpdateEnabledCategories(); |
+ if (instance->keyword_update_thread_handle_.is_null()) { |
+ instance->keyword_update_thread_.reset(new ETWKeywordUpdateThread); |
+ PlatformThread::CreateWithPriority( |
+ 0, instance->keyword_update_thread_.get(), |
+ &instance->keyword_update_thread_handle_, ThreadPriority::BACKGROUND); |
+ } |
+ } |
} |
// static |
void TraceEventETWExport::DisableETWExport() { |
- if (GetInstance()) |
- GetInstance()->etw_export_enabled_ = false; |
+ auto* instance = GetInstance(); |
+ if (instance && instance->etw_export_enabled_) |
+ instance->etw_export_enabled_ = false; |
} |
// static |
bool TraceEventETWExport::IsETWExportEnabled() { |
- return (GetInstance() && GetInstance()->etw_export_enabled_); |
+ auto* instance = GetInstance(); |
+ return (instance && instance->etw_export_enabled_); |
} |
// static |
@@ -187,8 +224,8 @@ 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()->etw_export_enabled_ || |
- !EventEnabledChromeEvent()) |
+ auto* instance = GetInstance(); |
+ if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent()) |
return; |
const char* phase_string = nullptr; |
@@ -294,8 +331,8 @@ void TraceEventETWExport::AddCustomEvent(const char* name, |
const char* arg_value_2, |
const char* arg_name_3, |
const char* arg_value_3) { |
- if (!GetInstance() || !GetInstance()->etw_export_enabled_ || |
- !EventEnabledChromeEvent()) |
+ auto* instance = GetInstance(); |
+ if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent()) |
return; |
EventWriteChromeEvent(name, phase, arg_name_1, arg_value_1, arg_name_2, |
@@ -306,7 +343,7 @@ void TraceEventETWExport::AddCustomEvent(const char* name, |
bool TraceEventETWExport::IsCategoryGroupEnabled( |
const char* category_group_name) { |
DCHECK(category_group_name); |
- auto instance = GetInstance(); |
+ auto* instance = GetInstance(); |
if (instance == nullptr) |
return false; |
@@ -354,6 +391,9 @@ bool TraceEventETWExport::UpdateEnabledCategories() { |
categories_status_[disabled_other_events_group_name] = false; |
} |
+ // Update the categories in TraceLog. |
+ TraceLog::GetInstance()->UpdateETWCategoryGroupEnabledFlags(); |
+ |
return true; |
} |
@@ -376,5 +416,13 @@ bool TraceEventETWExport::IsCategoryEnabled(const char* category_name) const { |
} |
} |
+// static |
+void TraceEventETWExport::UpdateETWKeyword() { |
+ if (!IsETWExportEnabled()) |
+ return; |
+ auto* instance = GetInstance(); |
+ DCHECK(instance); |
+ instance->UpdateEnabledCategories(); |
+} |
} // namespace trace_event |
} // namespace base |