1// Copyright (c) 2013 The Chromium OS 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
5#ifndef CHROMIUMOS_WIDE_PROFILING_MYBASE_BASE_LOGGING_H_
6#define CHROMIUMOS_WIDE_PROFILING_MYBASE_BASE_LOGGING_H_
7
8#include <errno.h>   // for errno
9#include <string.h>  // for strerror
10
11#include <iostream>
12#include <sstream>
13#include <string>
14
15#include "base/macros.h"
16
17// Emulate Chrome-like logging.
18
19// LogLevel is an enumeration that holds the log levels like libbase does.
20enum LogLevel {
21  INFO,
22  WARNING,
23  ERROR,
24  FATAL,
25};
26
27namespace logging {
28
29// Sets the log level. Anything at or above this level will be written to the
30// log file/displayed to the user (if applicable). Anything below this level
31// will be silently ignored. The log level defaults to 0 (everything is logged
32// up to level INFO) if this function is not called.
33// Note that log messages for VLOG(x) are logged at level -x, so setting
34// the min log level to negative values enables verbose logging.
35void SetMinLogLevel(int level);
36
37// Gets the current log level.
38int GetMinLogLevel();
39
40// Gets the VLOG verbosity level.
41int GetVlogVerbosity();
42
43// Generic logging class that emulates logging from libbase. Do not use this
44// class directly.
45class LogBase {
46 public:
47  virtual ~LogBase() {}
48
49  template <class T>
50  LogBase& operator<<(const T& x) {
51    ss_ << x;
52    return *this;
53  }
54
55 protected:
56  LogBase(const std::string label, const char* file, int line) {
57    ss_ << "[" << label << ":" << file << ":" << line << "] ";
58  }
59
60  // Accumulates the contents to be printed.
61  std::ostringstream ss_;
62};
63
64// For general logging.
65class Log : public LogBase {
66 public:
67  Log(LogLevel level, const char* level_str, const char* file, int line)
68      : LogBase(level_str, file, line) {
69    level_ = level;
70  }
71
72  ~Log() {
73    if (level_ >= GetMinLogLevel()) std::cerr << ss_.str() << std::endl;
74    if (level_ >= FATAL) exit(EXIT_FAILURE);
75  }
76
77 protected:
78  LogLevel level_;
79};
80
81// Like LOG but appends errno's string description to the logging.
82class PLog : public Log {
83 public:
84  PLog(LogLevel level, const char* level_str, const char* file, int line)
85      : Log(level, level_str, file, line) {}
86
87  ~PLog() {
88    if (level_ >= GetMinLogLevel())
89      std::cerr << ss_.str() << ": " << strerror(errnum_) << std::endl;
90  }
91
92 private:
93  // Cached error value, in case errno changes during this object's lifetime.
94  int errnum_;
95};
96
97// Like LOG but conditional upon the logging verbosity level.
98class VLog : public LogBase {
99 public:
100  VLog(int vlog_level, const char* file, int line)
101      : LogBase(std::string("VLOG(") + std::to_string(vlog_level) + ")", file,
102                line),
103        vlog_level_(vlog_level) {}
104
105  ~VLog() {
106    if (vlog_level_ <= GetVlogVerbosity()) std::cerr << ss_.str() << std::endl;
107  }
108
109 private:
110  // Logging verbosity level. The logging will be printed if this value is less
111  // than or equal to GetVlogVerbosity().
112  int vlog_level_;
113};
114
115}  // namespace logging
116
117// These macros are for LOG() and related logging commands.
118#define LOG(level) logging::Log(level, #level, __FILE__, __LINE__)
119#define PLOG(level) logging::PLog(level, #level, __FILE__, __LINE__)
120#define VLOG(level) logging::VLog(level, __FILE__, __LINE__)
121
122// Some macros from libbase that we use.
123#define CHECK(x) \
124  if (!(x)) LOG(FATAL) << #x
125#define CHECK_GT(x, y) \
126  if (!(x > y)) LOG(FATAL) << #x << " > " << #y << "failed"
127#define CHECK_GE(x, y) \
128  if (!(x >= y)) LOG(FATAL) << #x << " >= " << #y << "failed"
129#define CHECK_LE(x, y) \
130  if (!(x <= y)) LOG(FATAL) << #x << " <= " << #y << "failed"
131#define CHECK_NE(x, y) \
132  if (!(x != y)) LOG(FATAL) << #x << " != " << #y << "failed"
133#define CHECK_EQ(x, y) \
134  if (!(x == y)) LOG(FATAL) << #x << " == " << #y << "failed"
135#define DLOG(x) LOG(x)
136#define DVLOG(x) VLOG(x)
137#define DCHECK(x) CHECK(x)
138
139#endif  // CHROMIUMOS_WIDE_PROFILING_MYBASE_BASE_LOGGING_H_
140