logging_win.cc 4.2 KB

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