[email protected] | 2b07b841 | 2009-11-25 15:26:34 | [diff] [blame] | 1 | // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "base/logging_win.h" |
[email protected] | 2b07b841 | 2009-11-25 15:26:34 | [diff] [blame] | 6 | #include "base/singleton.h" |
| 7 | #include <initguid.h> // NOLINT |
| 8 | |
| 9 | namespace { |
| 10 | |
[email protected] | 297d0e5 | 2010-05-07 15:24:49 | [diff] [blame] | 11 | typedef StaticMemorySingletonTraits<logging::LogEventProvider> |
| 12 | LogEventSingletonTraits; |
| 13 | Singleton<logging::LogEventProvider, LogEventSingletonTraits> log_provider; |
[email protected] | 2b07b841 | 2009-11-25 15:26:34 | [diff] [blame] | 14 | |
| 15 | } // namespace |
| 16 | |
| 17 | namespace logging { |
| 18 | |
[email protected] | ba50d192 | 2010-11-06 15:39:40 | [diff] [blame^] | 19 | using base::win::EtwEventLevel; |
| 20 | using base::win::EtwMofEvent; |
| 21 | |
[email protected] | 2b07b841 | 2009-11-25 15:26:34 | [diff] [blame] | 22 | DEFINE_GUID(kLogEventId, |
| 23 | 0x7fe69228, 0x633e, 0x4f06, 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7); |
| 24 | |
| 25 | LogEventProvider::LogEventProvider() : old_log_level_(LOG_NONE) { |
| 26 | } |
| 27 | |
[email protected] | 162ac0f | 2010-11-04 15:50:49 | [diff] [blame] | 28 | bool LogEventProvider::LogMessage(logging::LogSeverity severity, |
| 29 | const char* file, int line, size_t message_start, |
| 30 | const std::string& message) { |
[email protected] | 2b07b841 | 2009-11-25 15:26:34 | [diff] [blame] | 31 | EtwEventLevel level = TRACE_LEVEL_NONE; |
| 32 | |
| 33 | // Convert the log severity to the most appropriate ETW trace level. |
[email protected] | 162ac0f | 2010-11-04 15:50:49 | [diff] [blame] | 34 | if (severity >= 0) { |
| 35 | switch (severity) { |
| 36 | case LOG_INFO: |
| 37 | level = TRACE_LEVEL_INFORMATION; |
| 38 | break; |
| 39 | case LOG_WARNING: |
| 40 | level = TRACE_LEVEL_WARNING; |
| 41 | break; |
| 42 | case LOG_ERROR: |
| 43 | case LOG_ERROR_REPORT: |
| 44 | level = TRACE_LEVEL_ERROR; |
| 45 | break; |
| 46 | case LOG_FATAL: |
| 47 | level = TRACE_LEVEL_FATAL; |
| 48 | break; |
| 49 | } |
| 50 | } else { // severity < 0 is VLOG verbosity levels. |
| 51 | level = TRACE_LEVEL_INFORMATION - severity; |
| 52 | } |
[email protected] | 2b07b841 | 2009-11-25 15:26:34 | [diff] [blame] | 53 | |
| 54 | // Bail if we're not logging, not at that level, |
| 55 | // or if we're post-atexit handling. |
| 56 | LogEventProvider* provider = log_provider.get(); |
| 57 | if (provider == NULL || level > provider->enable_level()) |
| 58 | return false; |
| 59 | |
[email protected] | 162ac0f | 2010-11-04 15:50:49 | [diff] [blame] | 60 | // And now log the event. |
| 61 | if (provider->enable_flags() & ENABLE_LOG_MESSAGE_ONLY) { |
| 62 | EtwMofEvent<1> event(kLogEventId, LOG_MESSAGE, level); |
| 63 | event.SetField(0, message.length() + 1 - message_start, |
| 64 | message.c_str() + message_start); |
[email protected] | 2b07b841 | 2009-11-25 15:26:34 | [diff] [blame] | 65 | |
| 66 | provider->Log(event.get()); |
| 67 | } else { |
[email protected] | 162ac0f | 2010-11-04 15:50:49 | [diff] [blame] | 68 | const size_t kMaxBacktraceDepth = 32; |
| 69 | void* backtrace[kMaxBacktraceDepth]; |
| 70 | DWORD depth = 0; |
| 71 | |
| 72 | // Capture a stack trace if one is requested. |
| 73 | // requested per our enable flags. |
| 74 | if (provider->enable_flags() & ENABLE_STACK_TRACE_CAPTURE) |
| 75 | depth = CaptureStackBackTrace(2, kMaxBacktraceDepth, backtrace, NULL); |
| 76 | |
| 77 | EtwMofEvent<5> event(kLogEventId, LOG_MESSAGE_FULL, level); |
| 78 | if (file == NULL) |
| 79 | file = ""; |
| 80 | |
| 81 | // Add the stack trace. |
| 82 | event.SetField(0, sizeof(depth), &depth); |
| 83 | event.SetField(1, sizeof(backtrace[0]) * depth, &backtrace); |
| 84 | // The line. |
| 85 | event.SetField(2, sizeof(line), &line); |
| 86 | // The file. |
| 87 | event.SetField(3, strlen(file) + 1, file); |
| 88 | // And finally the message. |
| 89 | event.SetField(4, message.length() + 1 - message_start, |
| 90 | message.c_str() + message_start); |
| 91 | |
[email protected] | 2b07b841 | 2009-11-25 15:26:34 | [diff] [blame] | 92 | provider->Log(event.get()); |
| 93 | } |
| 94 | |
| 95 | // Don't increase verbosity in other log destinations. |
[email protected] | 162ac0f | 2010-11-04 15:50:49 | [diff] [blame] | 96 | if (severity < provider->old_log_level_) |
[email protected] | 2b07b841 | 2009-11-25 15:26:34 | [diff] [blame] | 97 | return true; |
| 98 | |
| 99 | return false; |
| 100 | } |
| 101 | |
| 102 | void LogEventProvider::Initialize(const GUID& provider_name) { |
| 103 | LogEventProvider* provider = log_provider.get(); |
| 104 | |
| 105 | provider->set_provider_name(provider_name); |
| 106 | provider->Register(); |
| 107 | |
| 108 | // Register our message handler with logging. |
| 109 | SetLogMessageHandler(LogMessage); |
| 110 | } |
| 111 | |
| 112 | void LogEventProvider::Uninitialize() { |
| 113 | log_provider.get()->Unregister(); |
| 114 | } |
| 115 | |
| 116 | void LogEventProvider::OnEventsEnabled() { |
| 117 | // Grab the old log level so we can restore it later. |
| 118 | old_log_level_ = GetMinLogLevel(); |
| 119 | |
| 120 | // Convert the new trace level to a logging severity |
| 121 | // and enable logging at that level. |
| 122 | EtwEventLevel level = enable_level(); |
[email protected] | 162ac0f | 2010-11-04 15:50:49 | [diff] [blame] | 123 | if (level == TRACE_LEVEL_NONE || level == TRACE_LEVEL_FATAL) { |
| 124 | SetMinLogLevel(LOG_FATAL); |
| 125 | } else if (level == TRACE_LEVEL_ERROR) { |
| 126 | SetMinLogLevel(LOG_ERROR); |
| 127 | } else if (level == TRACE_LEVEL_WARNING) { |
| 128 | SetMinLogLevel(LOG_WARNING); |
| 129 | } else if (level == TRACE_LEVEL_INFORMATION) { |
| 130 | SetMinLogLevel(LOG_INFO); |
| 131 | } else if (level >= TRACE_LEVEL_VERBOSE) { |
| 132 | // Above INFO, we enable verbose levels with negative severities. |
| 133 | SetMinLogLevel(TRACE_LEVEL_INFORMATION - level); |
[email protected] | 2b07b841 | 2009-11-25 15:26:34 | [diff] [blame] | 134 | } |
| 135 | } |
| 136 | |
| 137 | void LogEventProvider::OnEventsDisabled() { |
| 138 | // Restore the old log level. |
| 139 | SetMinLogLevel(old_log_level_); |
| 140 | } |
| 141 | |
| 142 | } // namespace logging |