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 10 namespace { 11 12 struct LogEventProviderTraits { 13 // WARNING: User has to deal with get() returning NULL. 14 static logging::LogEventProvider* New() { 15 if (base::subtle::NoBarrier_AtomicExchange(&dead_, 1)) 16 return NULL; 17 logging::LogEventProvider* ptr = 18 reinterpret_cast<logging::LogEventProvider*>(buffer_); 19 // We are protected by a memory barrier. 20 new(ptr) logging::LogEventProvider(); 21 return ptr; 22 } 23 24 static void Delete(logging::LogEventProvider* p) { 25 base::subtle::NoBarrier_Store(&dead_, 1); 26 MemoryBarrier(); 27 p->logging::LogEventProvider::~LogEventProvider(); 28 } 29 30 static const bool kRegisterAtExit = true; 31 32 private: 33 static const size_t kBufferSize = (sizeof(logging::LogEventProvider) + 34 sizeof(intptr_t) - 1) / sizeof(intptr_t); 35 static intptr_t buffer_[kBufferSize]; 36 37 // Signal the object was already deleted, so it is not revived. 38 static base::subtle::Atomic32 dead_; 39 }; 40 41 intptr_t LogEventProviderTraits::buffer_[kBufferSize]; 42 base::subtle::Atomic32 LogEventProviderTraits::dead_ = 0; 43 44 Singleton<logging::LogEventProvider, LogEventProviderTraits> log_provider; 45 46 } // namespace 47 48 namespace logging { 49 50 DEFINE_GUID(kLogEventId, 51 0x7fe69228, 0x633e, 0x4f06, 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7); 52 53 LogEventProvider::LogEventProvider() : old_log_level_(LOG_NONE) { 54 } 55 56 bool LogEventProvider::LogMessage(int severity, const std::string& message) { 57 EtwEventLevel level = TRACE_LEVEL_NONE; 58 59 // Convert the log severity to the most appropriate ETW trace level. 60 switch (severity) { 61 case LOG_INFO: 62 level = TRACE_LEVEL_INFORMATION; 63 break; 64 case LOG_WARNING: 65 level = TRACE_LEVEL_WARNING; 66 break; 67 case LOG_ERROR: 68 case LOG_ERROR_REPORT: 69 level = TRACE_LEVEL_ERROR; 70 break; 71 case LOG_FATAL: 72 level = TRACE_LEVEL_FATAL; 73 break; 74 }; 75 76 // Bail if we're not logging, not at that level, 77 // or if we're post-atexit handling. 78 LogEventProvider* provider = log_provider.get(); 79 if (provider == NULL || level > provider->enable_level()) 80 return false; 81 82 // And now log the event, with stack trace if one is 83 // requested per our enable flags. 84 if (provider->enable_flags() & ENABLE_STACK_TRACE_CAPTURE) { 85 const size_t kMaxBacktraceDepth = 32; 86 void* backtrace[kMaxBacktraceDepth]; 87 DWORD depth = CaptureStackBackTrace(2, kMaxBacktraceDepth, backtrace, NULL); 88 EtwMofEvent<3> event(kLogEventId, LOG_MESSAGE_WITH_STACKTRACE, level); 89 90 event.SetField(0, sizeof(depth), &depth); 91 event.SetField(1, sizeof(backtrace[0]) * depth, &backtrace); 92 event.SetField(2, message.length() + 1, message.c_str()); 93 94 provider->Log(event.get()); 95 } else { 96 EtwMofEvent<1> event(kLogEventId, LOG_MESSAGE, level); 97 event.SetField(0, message.length() + 1, message.c_str()); 98 provider->Log(event.get()); 99 } 100 101 // Don't increase verbosity in other log destinations. 102 if (severity >= provider->old_log_level_) 103 return true; 104 105 return false; 106 } 107 108 void LogEventProvider::Initialize(const GUID& provider_name) { 109 LogEventProvider* provider = log_provider.get(); 110 111 provider->set_provider_name(provider_name); 112 provider->Register(); 113 114 // Register our message handler with logging. 115 SetLogMessageHandler(LogMessage); 116 } 117 118 void LogEventProvider::Uninitialize() { 119 log_provider.get()->Unregister(); 120 } 121 122 void LogEventProvider::OnEventsEnabled() { 123 // Grab the old log level so we can restore it later. 124 old_log_level_ = GetMinLogLevel(); 125 126 // Convert the new trace level to a logging severity 127 // and enable logging at that level. 128 EtwEventLevel level = enable_level(); 129 switch (level) { 130 case TRACE_LEVEL_NONE: 131 case TRACE_LEVEL_FATAL: 132 SetMinLogLevel(LOG_FATAL); 133 break; 134 case TRACE_LEVEL_ERROR: 135 SetMinLogLevel(LOG_ERROR); 136 break; 137 case TRACE_LEVEL_WARNING: 138 SetMinLogLevel(LOG_WARNING); 139 break; 140 case TRACE_LEVEL_INFORMATION: 141 case TRACE_LEVEL_VERBOSE: 142 SetMinLogLevel(LOG_INFO); 143 break; 144 } 145 } 146 147 void LogEventProvider::OnEventsDisabled() { 148 // Restore the old log level. 149 SetMinLogLevel(old_log_level_); 150 } 151 152 } // namespace logging 153