logging_win.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
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" 6#include "base/singleton.h" 7#include <initguid.h> // NOLINT 8 9namespace { 10 11typedef StaticMemorySingletonTraits<logging::LogEventProvider> 12 LogEventSingletonTraits; 13Singleton<logging::LogEventProvider, LogEventSingletonTraits> log_provider; 14 15} // namespace 16 17namespace logging { 18 19DEFINE_GUID(kLogEventId, 20 0x7fe69228, 0x633e, 0x4f06, 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7); 21 22LogEventProvider::LogEventProvider() : old_log_level_(LOG_NONE) { 23} 24 25bool LogEventProvider::LogMessage(int severity, const std::string& message) { 26 EtwEventLevel level = TRACE_LEVEL_NONE; 27 28 // Convert the log severity to the most appropriate ETW trace level. 29 switch (severity) { 30 case LOG_INFO: 31 level = TRACE_LEVEL_INFORMATION; 32 break; 33 case LOG_WARNING: 34 level = TRACE_LEVEL_WARNING; 35 break; 36 case LOG_ERROR: 37 case LOG_ERROR_REPORT: 38 level = TRACE_LEVEL_ERROR; 39 break; 40 case LOG_FATAL: 41 level = TRACE_LEVEL_FATAL; 42 break; 43 }; 44 45 // Bail if we're not logging, not at that level, 46 // or if we're post-atexit handling. 47 LogEventProvider* provider = log_provider.get(); 48 if (provider == NULL || level > provider->enable_level()) 49 return false; 50 51 // And now log the event, with stack trace if one is 52 // requested per our enable flags. 53 if (provider->enable_flags() & ENABLE_STACK_TRACE_CAPTURE) { 54 const size_t kMaxBacktraceDepth = 32; 55 void* backtrace[kMaxBacktraceDepth]; 56 DWORD depth = CaptureStackBackTrace(2, kMaxBacktraceDepth, backtrace, NULL); 57 EtwMofEvent<3> event(kLogEventId, LOG_MESSAGE_WITH_STACKTRACE, level); 58 59 event.SetField(0, sizeof(depth), &depth); 60 event.SetField(1, sizeof(backtrace[0]) * depth, &backtrace); 61 event.SetField(2, message.length() + 1, message.c_str()); 62 63 provider->Log(event.get()); 64 } else { 65 EtwMofEvent<1> event(kLogEventId, LOG_MESSAGE, level); 66 event.SetField(0, message.length() + 1, message.c_str()); 67 provider->Log(event.get()); 68 } 69 70 // Don't increase verbosity in other log destinations. 71 if (severity >= provider->old_log_level_) 72 return true; 73 74 return false; 75} 76 77void LogEventProvider::Initialize(const GUID& provider_name) { 78 LogEventProvider* provider = log_provider.get(); 79 80 provider->set_provider_name(provider_name); 81 provider->Register(); 82 83 // Register our message handler with logging. 84 SetLogMessageHandler(LogMessage); 85} 86 87void LogEventProvider::Uninitialize() { 88 log_provider.get()->Unregister(); 89} 90 91void LogEventProvider::OnEventsEnabled() { 92 // Grab the old log level so we can restore it later. 93 old_log_level_ = GetMinLogLevel(); 94 95 // Convert the new trace level to a logging severity 96 // and enable logging at that level. 97 EtwEventLevel level = enable_level(); 98 switch (level) { 99 case TRACE_LEVEL_NONE: 100 case TRACE_LEVEL_FATAL: 101 SetMinLogLevel(LOG_FATAL); 102 break; 103 case TRACE_LEVEL_ERROR: 104 SetMinLogLevel(LOG_ERROR); 105 break; 106 case TRACE_LEVEL_WARNING: 107 SetMinLogLevel(LOG_WARNING); 108 break; 109 case TRACE_LEVEL_INFORMATION: 110 case TRACE_LEVEL_VERBOSE: 111 SetMinLogLevel(LOG_INFO); 112 break; 113 } 114} 115 116void LogEventProvider::OnEventsDisabled() { 117 // Restore the old log level. 118 SetMinLogLevel(old_log_level_); 119} 120 121} // namespace logging 122