Home | History | Annotate | Download | only in base
      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