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