PURIFY
Next-generation radio interferometric imaging
logging.h
Go to the documentation of this file.
1 #ifndef PURIFY_LOGGING_H
2 #define PURIFY_LOGGING_H
3 
4 #include "purify/config.h"
5 #include <cstring>
6 #include <exception>
7 #include <map>
8 #include <memory>
9 #include <sstream>
10 #include <string>
11 #include <tuple>
12 
13 namespace purify::logging {
14 
16 class Log {
17  public:
19  enum Level {
20  trace = 0,
21  debug = 10,
22  info = 20,
23  warn = 30,
24  warning = 30,
25  error = 40,
26  critical = 50,
27  always = 50
28  };
29  static const int end_color = -10;
30 
32  using LogMap = std::map<std::string, Log>;
33 
35  using LevelMap = std::map<std::string, int>;
36 
38  using ColorCodes = std::map<int, std::string>;
39 
40  private:
42  thread_local static LogMap existingLogs;
43 
45  thread_local static LevelMap defaultLevels;
46 
48  static bool showTimestamp;
49 
51  static bool showLogLevel;
52 
54  static bool showLoggerName;
55 
57  static bool useShellColors;
58 
59  public:
61  static void setLevel(const std::string& name, int level);
62  static void setLevels(const LevelMap& logLevels);
63 
64  protected:
67 
69  Log(const std::string& name);
70 
72  Log(const std::string& name, int level);
73 
75 
77  static std::string getColorCode(int level);
78 
79  public:
82  static Log& getLog(const std::string& name);
83 
85  int getLevel() const { return _level; }
86 
88  Log& setLevel(int level) {
89  _level = level;
90  return *this;
91  }
92 
94  static Level getLevelFromName(const std::string& level);
95 
97  static std::string getLevelName(int level);
98 
100  std::string getName() const { return _name; }
101 
103  Log& setName(const std::string& name) {
104  _name = name;
105  return *this;
106  }
107 
109  bool isActive(int level) const { return (level >= _level); }
110 
111  private:
113  std::string _name;
114 
116  int _level;
117 
118  protected:
120  void log(int level, const std::string& message);
121 
123  std::string formatMessage(int level, const std::string& message);
124 
125  public:
127  friend std::ostream& operator<<(Log& log, int level);
128 };
129 
131 std::ostream& operator<<(Log& log, int level);
132 
134 inline Log& getLog() { return Log::getLog("purify::"); }
135 
137 inline void set_level(const std::string& level) { getLog().setLevel(Log::getLevelFromName(level)); }
138 
141 template <typename Arg>
142 void applyFormat(std::stringstream& ss, char*& pos, Arg&& arg) {
143  char* delim = strstr(pos, "{}");
144  if (delim != NULL) {
145  ss << std::string(pos, delim - pos) << std::forward<Arg>(arg);
146  pos = delim + 2;
147  } else {
148  throw std::runtime_error("Insufficient placeholders for number of arguments!");
149  }
150 }
151 
153 template <typename... Args>
154 inline std::string mkFormattedString(const char* txt, Args&&... args) {
155  std::string mys = txt;
156  std::stringstream rtn;
157  char* pos = (char*)txt;
158  ((void)applyFormat(rtn, pos, std::forward<Args>(args)), ...);
159  rtn << std::string(pos);
160  return rtn.str();
161 }
162 
163 inline std::string mkFormattedString(const std::string& txt) {
164  return mkFormattedString(txt.data());
165 }
166 
169 
173 #define PURIFY_MSG_LVL(lvl, ...) \
174  do { \
175  if (purify::logging::getLog().isActive(lvl)) { \
176  purify::logging::getLog() << lvl << purify::logging::mkFormattedString(__VA_ARGS__) << '\n'; \
177  } \
178  } while (0)
179 
181 #define PURIFY_LOG_(TYPE, ...) PURIFY_MSG_LVL(purify::logging::Log::TYPE, __VA_ARGS__)
182 
184 
185 } // namespace purify::logging
186 
188 #define PURIFY_CRITICAL(...) PURIFY_LOG_(critical, __VA_ARGS__)
190 #define PURIFY_ERROR(...) PURIFY_LOG_(error, __VA_ARGS__)
192 #define PURIFY_WARN(...) PURIFY_LOG_(warn, __VA_ARGS__)
195 #define PURIFY_INFO(...) PURIFY_LOG_(info, __VA_ARGS__)
197 #define PURIFY_DEBUG(...) PURIFY_LOG_(debug, __VA_ARGS__)
200 #define PURIFY_TRACE(...) PURIFY_LOG_(trace, __VA_ARGS__)
201 
203 #define PURIFY_HIGH_LOG(...) PURIFY_LOG_(critical, __VA_ARGS__)
205 #define PURIFY_MEDIUM_LOG(...) PURIFY_LOG_(info, __VA_ARGS__)
207 #define PURIFY_LOW_LOG(...) PURIFY_LOG_(debug, __VA_ARGS__)
208 
209 #endif
Args({128, 10000, 4, 10}) -> UseManualTime() ->MinTime(10.0) ->MinWarmUpTime(5.0) ->Repetitions(3) ->Unit(benchmark::kMillisecond)
Logging system for controlled & formatted writing to stdout.
Definition: logging.h:16
static std::string getLevelName(int level)
Get the std::string representation of a log level.
Definition: logging.cc:86
std::map< std::string, Log > LogMap
Typedef for a collection of named logs.
Definition: logging.h:32
friend std::ostream & operator<<(Log &log, int level)
The streaming operator can use Log's internals.
Definition: logging.cc:171
Level
Log priority levels.
Definition: logging.h:19
Log & setName(const std::string &name)
Set the name of this logger.
Definition: logging.h:103
static const int end_color
Special "level-like" code to end coloring.
Definition: logging.h:29
Log & setLevel(int level)
Set the priority level of this logger.
Definition: logging.h:88
static Level getLevelFromName(const std::string &level)
Get a log level enum from a string.
Definition: logging.cc:122
static Log & getLog(const std::string &name)
Definition: logging.cc:49
bool isActive(int level) const
Will this log level produce output on this logger at the moment?
Definition: logging.h:109
int getLevel() const
Get the priority level of this logger.
Definition: logging.h:85
static void setLevels(const LevelMap &logLevels)
Definition: logging.cc:42
std::map< std::string, int > LevelMap
Typedef for a collection of named log levels.
Definition: logging.h:35
std::string getName() const
Get the name of this logger.
Definition: logging.h:100
std::map< int, std::string > ColorCodes
Typedef for a collection of shell color codes, accessed by log level.
Definition: logging.h:38
static void setLevel(const std::string &name, int level)
Set the log levels.
Log & getLog()
Access method to default Log object.
Definition: logging.h:134
void applyFormat(std::stringstream &ss, char *&pos, Arg &&arg)
Definition: logging.h:142
void set_level(const std::string &level)
Method to set the logging level of the default Log object.
Definition: logging.h:137
ostream & operator<<(Log &log, int level)
Streaming output to a logger must have a Log::Level/int as its first argument.
Definition: logging.cc:171
std::string mkFormattedString(const char *txt, Args &&... args)
Helper method to construct formatted string.
Definition: logging.h:154