1 // Copyright (c) 2011 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.
5 #include "base/logging_win.h"
6 #include "base/memory/singleton.h"
7 #include <initguid.h> // NOLINT
11 using base::win::EtwEventLevel
;
12 using base::win::EtwMofEvent
;
14 DEFINE_GUID(kLogEventId
,
15 0x7fe69228, 0x633e, 0x4f06, 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7);
17 LogEventProvider::LogEventProvider() : old_log_level_(LOG_NONE
) {
20 LogEventProvider
* LogEventProvider::GetInstance() {
21 return Singleton
<LogEventProvider
,
22 StaticMemorySingletonTraits
<LogEventProvider
> >::get();
25 bool LogEventProvider::LogMessage(logging::LogSeverity severity
,
26 const char* file
, int line
, size_t message_start
,
27 const std::string
& message
) {
28 EtwEventLevel level
= TRACE_LEVEL_NONE
;
30 // Convert the log severity to the most appropriate ETW trace level.
34 level
= TRACE_LEVEL_INFORMATION
;
37 level
= TRACE_LEVEL_WARNING
;
40 level
= TRACE_LEVEL_ERROR
;
43 level
= TRACE_LEVEL_FATAL
;
46 } else { // severity < 0 is VLOG verbosity levels.
47 level
= TRACE_LEVEL_INFORMATION
- severity
;
50 // Bail if we're not logging, not at that level,
51 // or if we're post-atexit handling.
52 LogEventProvider
* provider
= LogEventProvider::GetInstance();
53 if (provider
== NULL
|| level
> provider
->enable_level())
56 // And now log the event.
57 if (provider
->enable_flags() & ENABLE_LOG_MESSAGE_ONLY
) {
58 EtwMofEvent
<1> event(kLogEventId
, LOG_MESSAGE
, level
);
59 event
.SetField(0, message
.length() + 1 - message_start
,
60 message
.c_str() + message_start
);
62 provider
->Log(event
.get());
64 const size_t kMaxBacktraceDepth
= 32;
65 void* backtrace
[kMaxBacktraceDepth
];
68 // Capture a stack trace if one is requested.
69 // requested per our enable flags.
70 if (provider
->enable_flags() & ENABLE_STACK_TRACE_CAPTURE
)
71 depth
= CaptureStackBackTrace(2, kMaxBacktraceDepth
, backtrace
, NULL
);
73 EtwMofEvent
<5> event(kLogEventId
, LOG_MESSAGE_FULL
, level
);
77 // Add the stack trace.
78 event
.SetField(0, sizeof(depth
), &depth
);
79 event
.SetField(1, sizeof(backtrace
[0]) * depth
, &backtrace
);
81 event
.SetField(2, sizeof(line
), &line
);
83 event
.SetField(3, strlen(file
) + 1, file
);
84 // And finally the message.
85 event
.SetField(4, message
.length() + 1 - message_start
,
86 message
.c_str() + message_start
);
88 provider
->Log(event
.get());
91 // Don't increase verbosity in other log destinations.
92 if (severity
< provider
->old_log_level_
)
98 void LogEventProvider::Initialize(const GUID
& provider_name
) {
99 LogEventProvider
* provider
= LogEventProvider::GetInstance();
101 provider
->set_provider_name(provider_name
);
102 provider
->Register();
104 // Register our message handler with logging.
105 SetLogMessageHandler(LogMessage
);
108 void LogEventProvider::Uninitialize() {
109 LogEventProvider::GetInstance()->Unregister();
112 void LogEventProvider::OnEventsEnabled() {
113 // Grab the old log level so we can restore it later.
114 old_log_level_
= GetMinLogLevel();
116 // Convert the new trace level to a logging severity
117 // and enable logging at that level.
118 EtwEventLevel level
= enable_level();
119 if (level
== TRACE_LEVEL_NONE
|| level
== TRACE_LEVEL_FATAL
) {
120 SetMinLogLevel(LOG_FATAL
);
121 } else if (level
== TRACE_LEVEL_ERROR
) {
122 SetMinLogLevel(LOG_ERROR
);
123 } else if (level
== TRACE_LEVEL_WARNING
) {
124 SetMinLogLevel(LOG_WARNING
);
125 } else if (level
== TRACE_LEVEL_INFORMATION
) {
126 SetMinLogLevel(LOG_INFO
);
127 } else if (level
>= TRACE_LEVEL_VERBOSE
) {
128 // Above INFO, we enable verbose levels with negative severities.
129 SetMinLogLevel(TRACE_LEVEL_INFORMATION
- level
);
133 void LogEventProvider::OnEventsDisabled() {
134 // Restore the old log level.
135 SetMinLogLevel(old_log_level_
);
138 } // namespace logging