summaryrefslogtreecommitdiffstats
path: root/base/logging_win.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/logging_win.cc')
-rw-r--r--base/logging_win.cc152
1 files changed, 152 insertions, 0 deletions
diff --git a/base/logging_win.cc b/base/logging_win.cc
new file mode 100644
index 0000000..b3702aa
--- /dev/null
+++ b/base/logging_win.cc
@@ -0,0 +1,152 @@
+// Copyright (c) 2009 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/logging_win.h"
+#include "base/atomicops.h"
+#include "base/singleton.h"
+#include <initguid.h> // NOLINT
+
+namespace {
+
+struct LogEventProviderTraits {
+ // WARNING: User has to deal with get() returning NULL.
+ static logging::LogEventProvider* New() {
+ if (base::subtle::NoBarrier_AtomicExchange(&dead_, 1))
+ return NULL;
+ logging::LogEventProvider* ptr =
+ reinterpret_cast<logging::LogEventProvider*>(buffer_);
+ // We are protected by a memory barrier.
+ new (ptr) logging::LogEventProvider();
+ return ptr;
+ }
+
+ static void Delete(logging::LogEventProvider* p) {
+ base::subtle::NoBarrier_Store(&dead_, 1);
+ MemoryBarrier();
+ p->logging::LogEventProvider::~LogEventProvider();
+ }
+
+ static const bool kRegisterAtExit = true;
+
+ private:
+ static const size_t kBufferSize = (sizeof(logging::LogEventProvider) +
+ sizeof(intptr_t) - 1) / sizeof(intptr_t);
+ static intptr_t buffer_[kBufferSize];
+
+ // Signal the object was already deleted, so it is not revived.
+ static base::subtle::Atomic32 dead_;
+};
+
+intptr_t LogEventProviderTraits::buffer_[kBufferSize];
+base::subtle::Atomic32 LogEventProviderTraits::dead_ = 0;
+
+Singleton<logging::LogEventProvider, LogEventProviderTraits> log_provider;
+
+} // namespace
+
+namespace logging {
+
+DEFINE_GUID(kLogEventId,
+ 0x7fe69228, 0x633e, 0x4f06, 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7);
+
+LogEventProvider::LogEventProvider() : old_log_level_(LOG_NONE) {
+}
+
+bool LogEventProvider::LogMessage(int severity, const std::string& message) {
+ EtwEventLevel level = TRACE_LEVEL_NONE;
+
+ // Convert the log severity to the most appropriate ETW trace level.
+ switch (severity) {
+ case LOG_INFO:
+ level = TRACE_LEVEL_INFORMATION;
+ break;
+ case LOG_WARNING:
+ level = TRACE_LEVEL_WARNING;
+ break;
+ case LOG_ERROR:
+ case LOG_ERROR_REPORT:
+ level = TRACE_LEVEL_ERROR;
+ break;
+ case LOG_FATAL:
+ level = TRACE_LEVEL_FATAL;
+ break;
+ };
+
+ // Bail if we're not logging, not at that level,
+ // or if we're post-atexit handling.
+ LogEventProvider* provider = log_provider.get();
+ if (provider == NULL || level > provider->enable_level())
+ return false;
+
+ // And now log the event, with stack trace if one is
+ // requested per our enable flags.
+ if (provider->enable_flags() & ENABLE_STACK_TRACE_CAPTURE) {
+ const size_t kMaxBacktraceDepth = 32;
+ void* backtrace[kMaxBacktraceDepth];
+ DWORD depth = CaptureStackBackTrace(2, kMaxBacktraceDepth, backtrace, NULL);
+ EtwMofEvent<3> event(kLogEventId, LOG_MESSAGE_WITH_STACKTRACE, level);
+
+ event.SetField(0, sizeof(depth), &depth);
+ event.SetField(1, sizeof(backtrace[0]) * depth, &backtrace);
+ event.SetField(2, message.length() + 1, message.c_str());
+
+ provider->Log(event.get());
+ } else {
+ EtwMofEvent<1> event(kLogEventId, LOG_MESSAGE, level);
+ event.SetField(0, message.length() + 1, message.c_str());
+ provider->Log(event.get());
+ }
+
+ // Don't increase verbosity in other log destinations.
+ if (severity >= provider->old_log_level_)
+ return true;
+
+ return false;
+}
+
+void LogEventProvider::Initialize(const GUID& provider_name) {
+ LogEventProvider* provider = log_provider.get();
+
+ provider->set_provider_name(provider_name);
+ provider->Register();
+
+ // Register our message handler with logging.
+ SetLogMessageHandler(LogMessage);
+}
+
+void LogEventProvider::Uninitialize() {
+ log_provider.get()->Unregister();
+}
+
+void LogEventProvider::OnEventsEnabled() {
+ // Grab the old log level so we can restore it later.
+ old_log_level_ = GetMinLogLevel();
+
+ // Convert the new trace level to a logging severity
+ // and enable logging at that level.
+ EtwEventLevel level = enable_level();
+ switch (level) {
+ case TRACE_LEVEL_NONE:
+ case TRACE_LEVEL_FATAL:
+ SetMinLogLevel(LOG_FATAL);
+ break;
+ case TRACE_LEVEL_ERROR:
+ SetMinLogLevel(LOG_ERROR);
+ break;
+ case TRACE_LEVEL_WARNING:
+ SetMinLogLevel(LOG_WARNING);
+ break;
+ case TRACE_LEVEL_INFORMATION:
+ case TRACE_LEVEL_VERBOSE:
+ SetMinLogLevel(LOG_INFO);
+ break;
+ }
+}
+
+void LogEventProvider::OnEventsDisabled() {
+ // Restore the old log level.
+ SetMinLogLevel(old_log_level_);
+}
+
+} // namespace logging