15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging_win.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <initguid.h> // NOLINT 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace logging { 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::EtwEventLevel; 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::EtwMofEvent; 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_GUID(kLogEventId, 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0x7fe69228, 0x633e, 0x4f06, 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7); 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LogEventProvider::LogEventProvider() : old_log_level_(LOG_NONE) { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LogEventProvider* LogEventProvider::GetInstance() { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<LogEventProvider, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StaticMemorySingletonTraits<LogEventProvider> >::get(); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LogEventProvider::LogMessage(logging::LogSeverity severity, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* file, int line, size_t message_start, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& message) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventLevel level = TRACE_LEVEL_NONE; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert the log severity to the most appropriate ETW trace level. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (severity >= 0) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (severity) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LOG_INFO: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) level = TRACE_LEVEL_INFORMATION; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LOG_WARNING: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) level = TRACE_LEVEL_WARNING; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LOG_ERROR: 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) level = TRACE_LEVEL_ERROR; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LOG_FATAL: 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) level = TRACE_LEVEL_FATAL; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // severity < 0 is VLOG verbosity levels. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) level = TRACE_LEVEL_INFORMATION - severity; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bail if we're not logging, not at that level, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or if we're post-atexit handling. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogEventProvider* provider = LogEventProvider::GetInstance(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider == NULL || level > provider->enable_level()) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And now log the event. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider->enable_flags() & ENABLE_LOG_MESSAGE_ONLY) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwMofEvent<1> event(kLogEventId, LOG_MESSAGE, level); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.SetField(0, message.length() + 1 - message_start, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message.c_str() + message_start); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->Log(event.get()); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t kMaxBacktraceDepth = 32; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* backtrace[kMaxBacktraceDepth]; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD depth = 0; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Capture a stack trace if one is requested. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // requested per our enable flags. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider->enable_flags() & ENABLE_STACK_TRACE_CAPTURE) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) depth = CaptureStackBackTrace(2, kMaxBacktraceDepth, backtrace, NULL); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwMofEvent<5> event(kLogEventId, LOG_MESSAGE_FULL, level); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file == NULL) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file = ""; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the stack trace. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.SetField(0, sizeof(depth), &depth); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.SetField(1, sizeof(backtrace[0]) * depth, &backtrace); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The line. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.SetField(2, sizeof(line), &line); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The file. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.SetField(3, strlen(file) + 1, file); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And finally the message. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.SetField(4, message.length() + 1 - message_start, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message.c_str() + message_start); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->Log(event.get()); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't increase verbosity in other log destinations. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (severity < provider->old_log_level_) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LogEventProvider::Initialize(const GUID& provider_name) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogEventProvider* provider = LogEventProvider::GetInstance(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->set_provider_name(provider_name); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->Register(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register our message handler with logging. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLogMessageHandler(LogMessage); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LogEventProvider::Uninitialize() { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogEventProvider::GetInstance()->Unregister(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LogEventProvider::OnEventsEnabled() { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Grab the old log level so we can restore it later. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_log_level_ = GetMinLogLevel(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert the new trace level to a logging severity 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and enable logging at that level. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventLevel level = enable_level(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (level == TRACE_LEVEL_NONE || level == TRACE_LEVEL_FATAL) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetMinLogLevel(LOG_FATAL); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (level == TRACE_LEVEL_ERROR) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetMinLogLevel(LOG_ERROR); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (level == TRACE_LEVEL_WARNING) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetMinLogLevel(LOG_WARNING); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (level == TRACE_LEVEL_INFORMATION) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetMinLogLevel(LOG_INFO); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (level >= TRACE_LEVEL_VERBOSE) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Above INFO, we enable verbose levels with negative severities. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetMinLogLevel(TRACE_LEVEL_INFORMATION - level); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LogEventProvider::OnEventsDisabled() { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Restore the old log level. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetMinLogLevel(old_log_level_); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace logging 139