// 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_