ModErn Text Analysis
META Enumerates Textual Applications
logger.h
Go to the documentation of this file.
1 
11 #ifndef META_LOGGER_H_
12 #define META_LOGGER_H_
13 
14 #include <chrono>
15 #include <functional>
16 #include <iomanip>
17 #include <iostream>
18 #include <sstream>
19 #include <vector>
20 
21 #include "meta/config.h"
22 
23 namespace meta
24 {
25 
29 namespace logging
30 {
31 
36 class logger
37 {
38  public:
44  enum class severity_level
45  {
46  progress,
47  trace,
48  debug,
49  info,
50  warning,
51  error,
52  fatal
53  };
54 
60  static std::string severity_string(severity_level sev)
61  {
62  switch (sev)
63  {
64  case severity_level::progress:
65  return "progress";
66  case severity_level::trace:
67  return "trace";
68  case severity_level::debug:
69  return "debug";
70  case severity_level::info:
71  return "info";
72  case severity_level::warning:
73  return "warning";
74  case severity_level::error:
75  return "error";
76  case severity_level::fatal:
77  return "fatal";
78  default:
79  return "unknown";
80  }
81  }
82 
87  class log_line
88  {
89  public:
98  log_line(logger& log, severity_level sev, size_t line,
99  const std::string& file)
100  : log_(log), sev_(sev), line_(line), file_(file)
101  {
102  /* nothing */
103  }
104 
113  static log_line& endlg(log_line& logline)
114  {
115  logline.stream_.flush();
116  logline.write_to_sinks();
117  return logline;
118  }
119 
128  {
129  return (*fn)(*this);
130  }
131 
139  template <class T>
140  log_line& operator<<(const T& to_write)
141  {
142  stream_ << to_write;
143  return *this;
144  }
145 
151  {
152  log_.write_to_sinks(*this);
153  }
154 
159  std::string str() const
160  {
161  return stream_.str();
162  }
163 
168  {
169  return sev_;
170  }
171 
175  const std::string& file() const
176  {
177  return file_;
178  }
179 
183  size_t line() const
184  {
185  return line_;
186  }
187 
188  private:
192  std::stringstream stream_;
193 
198 
203 
207  size_t line_;
208 
212  std::string file_;
213  };
214 
218  class sink
219  {
220  public:
224  using formatter_func = std::function<std::string(const log_line&)>;
225 
229  using filter_func = std::function<bool(const log_line&)>;
230 
244  sink(std::ostream& stream,
245  const filter_func& filter = [](const log_line&) { return true; },
246  const formatter_func& formatter = &default_formatter)
247  : stream_(stream), formatter_(formatter), filter_(filter)
248  {
249  /* nothing */
250  }
251 
263  sink(std::ostream& stream, logger::severity_level sev,
264  const formatter_func& formatter = &default_formatter)
265  : stream_(stream),
266  formatter_(formatter),
267  filter_(
268  [sev](const log_line& ll) { return ll.severity() >= sev; })
269  {
270  // nothing
271  }
272 
279  void write(const log_line& line)
280  {
281  if (filter_)
282  if (!filter_(line))
283  return;
284  if (formatter_)
285  stream_ << formatter_(line);
286  else
287  stream_ << line.str();
288  stream_ << std::flush;
289  }
290 
298  static std::string default_formatter(const log_line& line)
299  {
300  namespace sc = std::chrono;
301 
302  auto time = sc::system_clock::now();
303  auto since_epoch = time.time_since_epoch();
304  auto unix_time = sc::duration_cast<sc::seconds>(since_epoch);
305 
306  std::stringstream ss;
307  ss << unix_time.count();
308  ss << ": ";
309 
310  std::stringstream sev;
311  sev << "[" << severity_string(line.severity()) << "]";
312  ss << std::setw(10) << std::left << sev.str();
313 
314  ss << " ";
315  ss << line.str();
316  ss << " ";
317 
318  ss << "(" << line.file() << ":" << line.line() << ")";
319  ss << std::endl;
320  return ss.str();
321  }
322 
323  private:
327  std::ostream& stream_;
328 
333 
338  };
339 
345  void add_sink(const sink& s)
346  {
347  sinks_.push_back(s);
348  }
349 
355  void add_sink(sink&& s)
356  {
357  sinks_.emplace_back(std::move(s));
358  }
359 
365  void write_to_sinks(const log_line& line)
366  {
367  for (sink& s : sinks_)
368  s.write(line);
369  }
370 
371  private:
375  std::vector<sink> sinks_;
376 };
377 
382 {
383  static logger log;
384  return log;
385 }
386 
391 inline void add_sink(const logger::sink& s)
392 {
393  get_logger().add_sink(s);
394 }
395 
400 inline void add_sink(logger::sink&& s)
401 {
402  get_logger().add_sink(std::move(s));
403 }
404 
413  = logging::logger::severity_level::trace)
414 {
415  // separate logging for progress output
416  add_sink({std::cerr,
417  [](const logger::log_line& ll) {
418  return ll.severity() == logger::severity_level::progress;
419  },
420  [](const logger::log_line& ll) { return " " + ll.str(); }});
421 
422  add_sink({std::cerr, sev});
423 }
424 }
425 }
426 
427 #define LOG(sev) \
428  logging::logger::log_line(logging::get_logger(), \
429  logging::logger::severity_level::sev, __LINE__, \
430  __FILE__)
431 #define ENDLG logging::logger::log_line::endlg
432 #define LOG_FUNCTION_START() \
433  LOG(trace) << "entering " << __func__ << "()" << ENDLG
434 #endif
filter_func filter_
The filtering functor.
Definition: logger.h:337
severity_level severity() const
Definition: logger.h:167
log_line(logger &log, severity_level sev, size_t line, const std::string &file)
Constructs a new log line for the given logger.
Definition: logger.h:98
static std::string default_formatter(const log_line &line)
The default formatting function.
Definition: logger.h:298
logger & log_
The logger this log_line is to be written on.
Definition: logger.h:197
logger & get_logger()
Definition: logger.h:381
size_t line_
The line number for this message.
Definition: logger.h:207
std::string str() const
Converts the internal stream to a string.
Definition: logger.h:159
log_line & operator<<(log_line &(*fn)(log_line &))
Overloaded operator<<(), used to determine when a manipulator is sent to the log_line stream...
Definition: logger.h:127
const std::string & file() const
Definition: logger.h:175
void set_cerr_logging(logging::logger::severity_level sev=logging::logger::severity_level::trace)
Sets up default logging to cerr.
Definition: logger.h:412
std::function< bool(const log_line &)> filter_func
Convenience typedef for functions that filter log lines.
Definition: logger.h:229
static std::string severity_string(severity_level sev)
Determines the string form of a given severity_level.
Definition: logger.h:60
severity_level
severity_level: A demarcation of how severe a given message is.
Definition: logger.h:44
std::string file_
The file for this message.
Definition: logger.h:212
void write_to_sinks()
Writes the current log line to all sinks of the logger it was created with.
Definition: logger.h:150
void add_sink(const sink &s)
Adds a sink to the given logger.
Definition: logger.h:345
static log_line & endlg(log_line &logline)
Simulates a std::endl, but for log entries.
Definition: logger.h:113
The ModErn Text Analysis toolkit is a suite of natural language processing, classification, information retrieval, data mining, and other applications of text processing.
Definition: analyzer.h:25
log_line: Represents a single message to be written to all sinks.
Definition: logger.h:87
sink: A wrapper for a stream that a logger should write to.
Definition: logger.h:218
std::ostream & stream_
Internal stream.
Definition: logger.h:327
std::function< std::string(const log_line &)> formatter_func
Convenience typedef for functions that format log lines.
Definition: logger.h:224
severity_level sev_
The severity of this message.
Definition: logger.h:202
formatter_func formatter_
The formatting functor.
Definition: logger.h:332
void write(const log_line &line)
Writes the given log_line to the stream, formatting and filtering it as necessary.
Definition: logger.h:279
sink(std::ostream &stream, logger::severity_level sev, const formatter_func &formatter=&default_formatter)
Creates a new sink on the given stream, filtering out all results that are greater than or equal to t...
Definition: logger.h:263
size_t line() const
Definition: logger.h:183
std::stringstream stream_
Internal stream.
Definition: logger.h:192
log_line & operator<<(const T &to_write)
Generic operator<<().
Definition: logger.h:140
sink(std::ostream &stream, const filter_func &filter=[](const log_line &) { return true;}, const formatter_func &formatter=&default_formatter)
Creates a new sink with the given formatting function and filtering function.
Definition: logger.h:244
logger: Main logging class.
Definition: logger.h:36
std::vector< sink > sinks_
The list of sinks to write to.
Definition: logger.h:375
void add_sink(sink &&s)
Adds a sink to the given logger.
Definition: logger.h:355
void write_to_sinks(const log_line &line)
Writes the given log_line to all sinks.
Definition: logger.h:365