// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/logging_win.h"
#include "base/memory/singleton.h"
#include <initguid.h>  // NOLINT

namespace logging {

using base::win::EtwEventLevel;
using base::win::EtwMofEvent;

DEFINE_GUID(kLogEventId,
    0x7fe69228, 0x633e, 0x4f06, 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7);

LogEventProvider::LogEventProvider() : old_log_level_(LOG_NONE) {
}

LogEventProvider* LogEventProvider::GetInstance() {
  return base::Singleton<LogEventProvider, base::StaticMemorySingletonTraits<
                                               LogEventProvider>>::get();
}

bool LogEventProvider::LogMessage(logging::LogSeverity severity,
    const char* file, int line, size_t message_start,
    const std::string& message) {
  EtwEventLevel level = TRACE_LEVEL_NONE;

  // Convert the log severity to the most appropriate ETW trace level.
  if (severity >= 0) {
    switch (severity) {
      case LOGGING_INFO:
        level = TRACE_LEVEL_INFORMATION;
        break;
      case LOGGING_WARNING:
        level = TRACE_LEVEL_WARNING;
        break;
      case LOGGING_ERROR:
        level = TRACE_LEVEL_ERROR;
        break;
      case LOGGING_FATAL:
        level = TRACE_LEVEL_FATAL;
        break;
    }
  } else {  // severity < 0 is VLOG verbosity levels.
    level = static_cast<EtwEventLevel>(TRACE_LEVEL_INFORMATION - severity);
  }

  // Bail if we're not logging, not at that level,
  // or if we're post-atexit handling.
  LogEventProvider* provider = LogEventProvider::GetInstance();
  if (provider == NULL || level > provider->enable_level())
    return false;

  // And now log the event.
  if (provider->enable_flags() & ENABLE_LOG_MESSAGE_ONLY) {
    EtwMofEvent<1> event(kLogEventId, LOG_MESSAGE, level);
    event.SetField(0, message.length() + 1 - message_start,
        message.c_str() + message_start);

    provider->Log(event.get());
  } else {
    const size_t kMaxBacktraceDepth = 32;
    void* backtrace[kMaxBacktraceDepth];
    DWORD depth = 0;

    // Capture a stack trace if one is requested.
    // requested per our enable flags.
    if (provider->enable_flags() & ENABLE_STACK_TRACE_CAPTURE)
      depth = CaptureStackBackTrace(2, kMaxBacktraceDepth, backtrace, NULL);

    EtwMofEvent<5> event(kLogEventId, LOG_MESSAGE_FULL, level);
    if (file == NULL)
      file = "";

    // Add the stack trace.
    event.SetField(0, sizeof(depth), &depth);
    event.SetField(1, sizeof(backtrace[0]) * depth, &backtrace);
    // The line.
    event.SetField(2, sizeof(line), &line);
    // The file.
    event.SetField(3, strlen(file) + 1, file);
    // And finally the message.
    event.SetField(4, message.length() + 1 - message_start,
        message.c_str() + message_start);

    provider->Log(event.get());
  }

  // Don't increase verbosity in other log destinations.
  if (severity < provider->old_log_level_)
    return true;

  return false;
}

void LogEventProvider::Initialize(const GUID& provider_name) {
  LogEventProvider* provider = LogEventProvider::GetInstance();

  provider->set_provider_name(provider_name);
  provider->Register();

  // Register our message handler with logging.
  SetLogMessageHandler(LogMessage);
}

void LogEventProvider::Uninitialize() {
  LogEventProvider::GetInstance()->Unregister();
}

void LogEventProvider::OnEventsEnabled() {
  // Grab the old log level so we can restore it later.
  old_log_level_ = GetMinLogLevel();

  // Convert the new trace level to a logging severity
  // and enable logging at that level.
  EtwEventLevel level = enable_level();
  if (level == TRACE_LEVEL_NONE || level == TRACE_LEVEL_FATAL) {
    SetMinLogLevel(LOGGING_FATAL);
  } else if (level == TRACE_LEVEL_ERROR) {
    SetMinLogLevel(LOGGING_ERROR);
  } else if (level == TRACE_LEVEL_WARNING) {
    SetMinLogLevel(LOGGING_WARNING);
  } else if (level == TRACE_LEVEL_INFORMATION) {
    SetMinLogLevel(LOGGING_INFO);
  } else if (level >= TRACE_LEVEL_VERBOSE) {
    // Above INFO, we enable verbose levels with negative severities.
    SetMinLogLevel(TRACE_LEVEL_INFORMATION - level);
  }
}

void LogEventProvider::OnEventsDisabled() {
  // Restore the old log level.
  SetMinLogLevel(old_log_level_);
}

}  // namespace logging
