C++程序  |  140行  |  3.88 KB

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

#ifndef CHROMIUMOS_WIDE_PROFILING_MYBASE_BASE_LOGGING_H_
#define CHROMIUMOS_WIDE_PROFILING_MYBASE_BASE_LOGGING_H_

#include <errno.h>   // for errno
#include <string.h>  // for strerror

#include <iostream>  
#include <sstream>
#include <string>

#include "base/macros.h"

// Emulate Chrome-like logging.

// LogLevel is an enumeration that holds the log levels like libbase does.
enum LogLevel {
  INFO,
  WARNING,
  ERROR,
  FATAL,
};

namespace logging {

// Sets the log level. Anything at or above this level will be written to the
// log file/displayed to the user (if applicable). Anything below this level
// will be silently ignored. The log level defaults to 0 (everything is logged
// up to level INFO) if this function is not called.
// Note that log messages for VLOG(x) are logged at level -x, so setting
// the min log level to negative values enables verbose logging.
void SetMinLogLevel(int level);

// Gets the current log level.
int GetMinLogLevel();

// Gets the VLOG verbosity level.
int GetVlogVerbosity();

// Generic logging class that emulates logging from libbase. Do not use this
// class directly.
class LogBase {
 public:
  virtual ~LogBase() {}

  template <class T>
  LogBase& operator<<(const T& x) {
    ss_ << x;
    return *this;
  }

 protected:
  LogBase(const std::string label, const char* file, int line) {
    ss_ << "[" << label << ":" << file << ":" << line << "] ";
  }

  // Accumulates the contents to be printed.
  std::ostringstream ss_;
};

// For general logging.
class Log : public LogBase {
 public:
  Log(LogLevel level, const char* level_str, const char* file, int line)
      : LogBase(level_str, file, line) {
    level_ = level;
  }

  ~Log() {
    if (level_ >= GetMinLogLevel()) std::cerr << ss_.str() << std::endl;
    if (level_ >= FATAL) exit(EXIT_FAILURE);
  }

 protected:
  LogLevel level_;
};

// Like LOG but appends errno's string description to the logging.
class PLog : public Log {
 public:
  PLog(LogLevel level, const char* level_str, const char* file, int line)
      : Log(level, level_str, file, line) {}

  ~PLog() {
    if (level_ >= GetMinLogLevel())
      std::cerr << ss_.str() << ": " << strerror(errnum_) << std::endl;
  }

 private:
  // Cached error value, in case errno changes during this object's lifetime.
  int errnum_;
};

// Like LOG but conditional upon the logging verbosity level.
class VLog : public LogBase {
 public:
  VLog(int vlog_level, const char* file, int line)
      : LogBase(std::string("VLOG(") + std::to_string(vlog_level) + ")", file,
                line),
        vlog_level_(vlog_level) {}

  ~VLog() {
    if (vlog_level_ <= GetVlogVerbosity()) std::cerr << ss_.str() << std::endl;
  }

 private:
  // Logging verbosity level. The logging will be printed if this value is less
  // than or equal to GetVlogVerbosity().
  int vlog_level_;
};

}  // namespace logging

// These macros are for LOG() and related logging commands.
#define LOG(level) logging::Log(level, #level, __FILE__, __LINE__)
#define PLOG(level) logging::PLog(level, #level, __FILE__, __LINE__)
#define VLOG(level) logging::VLog(level, __FILE__, __LINE__)

// Some macros from libbase that we use.
#define CHECK(x) \
  if (!(x)) LOG(FATAL) << #x
#define CHECK_GT(x, y) \
  if (!(x > y)) LOG(FATAL) << #x << " > " << #y << "failed"
#define CHECK_GE(x, y) \
  if (!(x >= y)) LOG(FATAL) << #x << " >= " << #y << "failed"
#define CHECK_LE(x, y) \
  if (!(x <= y)) LOG(FATAL) << #x << " <= " << #y << "failed"
#define CHECK_NE(x, y) \
  if (!(x != y)) LOG(FATAL) << #x << " != " << #y << "failed"
#define CHECK_EQ(x, y) \
  if (!(x == y)) LOG(FATAL) << #x << " == " << #y << "failed"
#define DLOG(x) LOG(x)
#define DVLOG(x) VLOG(x)
#define DCHECK(x) CHECK(x)

#endif  // CHROMIUMOS_WIDE_PROFILING_MYBASE_BASE_LOGGING_H_