Bredbandskollen CLI  1.2
Asynchronous network task engine
logger.h
1 // Copyright (c) 2018 IIS (The Internet Foundation in Sweden)
2 // Written by Göran Andersson <initgoran@gmail.com>
3 
4 #pragma once
5 
6 #ifdef _WIN32
7 #ifndef NOMINMAX
8 #define NOMINMAX
9 #endif
10 #ifdef max
11 #undef max
12 #endif
13 #else
14 #include <string.h>
15 #endif
16 
17 #ifndef DEBUG
18 #define DEBUG 0
19 #endif
20 #ifndef TARGET_OS_IPHONE
21 #define TARGET_OS_IPHONE 0
22 #endif
23 
24 #include <iostream>
25 #include <sstream>
26 #include <chrono>
27 #include <thread>
28 
29 #ifdef __ANDROID_API__
30 #include <android/log.h>
31 #endif
32 
34 class DummyStream {
35 public:
37  template<class T>
38  DummyStream &operator<<(T ) { return *this; }
39 #ifdef __ANDROID_API__
40  DummyStream &operator<<(const char *s) {
41  __android_log_print(ANDROID_LOG_VERBOSE, "BBK", "%s", s);
42  return *this; }
43  DummyStream &operator<<(std::string s) {
44  __android_log_print(ANDROID_LOG_VERBOSE, "BBK", "%s", s.c_str());
45  return *this; }
46  DummyStream &operator<<(int i) {
47  __android_log_print(ANDROID_LOG_VERBOSE, "BBK", "%d", i);
48  return *this; }
49  DummyStream &operator<<(double x) {
50  __android_log_print(ANDROID_LOG_VERBOSE, "BBK", "%f", x);
51  return *this; }
52 #endif
54  DummyStream& operator<<(std::ostream &(*)(std::ostream &) ) {
55  return *this;
56  }
57  virtual ~DummyStream();
58 private:
59 };
60 
74 typedef std::chrono::steady_clock::time_point TimePoint;
75 
86 class Logger {
87 public:
90  Logger(std::string label) :
91  _label(label) {
92  // TODO: single initialisation
93  _blackHole.clear(std::istream::eofbit);
94  }
95 
101  static void setLogFile(std::ostream &stream);
102 
104  static void reopenLogFile(const std::string &filename);
105 
111  static void setLogLimit(unsigned int loglines = 0,
112  unsigned int warnlines = 0,
113  unsigned int errlines = 0);
114 
116  static void sayTime(std::ostream &stream);
117 
119  static bool inError() {
120  return in_error;
121  }
122 
131  static std::ostream &err_log(const std::string &label) {
132  if (err_count) {
133  in_error = true;
134  --err_count;
135  *_logFile << "\n" << global_elapsed_ms() << ' ' << label << " *** "
136  << (err_count ? "ERROR ***: " : "LAST ERR ***: ");
137  return *_logFile;
138  } else {
139  return _blackHole;
140  }
141  }
142 
151  static std::ostream &warn_log(const std::string &label) {
152  if (warn_count) {
153  --warn_count;
154  *_logFile << "\n" << global_elapsed_ms() << ' ' << label << " *** "
155  << (warn_count ? "WARNING ***: " : "LAST WARN ***: ");
156  return *_logFile;
157  } else {
158  return _blackHole;
159  }
160  }
161 
170  static std::ostream &log(const std::string &label) {
171  if (log_count) {
172  --log_count;
173  *_logFile << "\n" << global_elapsed_ms() << ' ' << label << ": ";
174  if (!log_count)
175  *_logFile << "LAST LOG: ";
176  return *_logFile;
177  } else {
178  return _blackHole;
179  }
180  }
181 
187  static void flushLogFile() {
188  *_logFile << std::endl;
189  }
190 
192  static void pauseLogging() {
193  _logFile = &_blackHole;
194  }
195 
198  static double secondsSince(const TimePoint &t);
199 
202  static double secondsTo(const TimePoint &t);
203 
206  static int64_t msSince(const TimePoint &t);
207 
210  static int64_t msTo(const TimePoint &t);
211 
213  static bool hasExpired(const TimePoint &t) {
214  return secondsSince(t) >= 0;
215  }
216 
218  static TimePoint timeNow() {
219  return std::chrono::steady_clock::now();
220  }
221 
223  static TimePoint timeAfter(double s) {
224  return timeNow() + std::chrono::microseconds(toUs(s));
225  }
226 
228  static TimePoint timeMax() {
229  return TimePoint::max();
230  }
231 
233  static std::chrono::microseconds toUs(double t) {
234  auto us = static_cast<std::chrono::microseconds::rep>(1e6*t);
235  return std::chrono::microseconds(us);
236  }
237 
239  static std::string dateString(time_t t = 0);
240 
242  static std::string dateString2(time_t t = 0);
243 
248  static std::string createHashKey(unsigned int length = 20);
249 
251  std::string label() const {
252  return _label;
253  }
254 
256  void resetLabel(const std::string &new_label) {
257  _label = new_label;
258  }
259 
260 protected:
261 
262 #if DEBUG
263 #define TASKRUNNER_LOGERR
264 #define TASKRUNNER_LOGWARN
265 #define TASKRUNNER_LOGINFO
266 #define TASKRUNNER_LOGBDG
267 #endif
268 
269 #ifdef TASKRUNNER_LOGERR
278  std::ostream &errno_log() const;
279 
292  std::ostream &err_log() const {
293  return err_log(_label);
294  }
295 #else
296  DummyStream &errno_log() const;
297  static DummyStream &err_log() {
298  return _dummyLog;
299  }
300 #endif
301 
302 #ifdef TASKRUNNER_LOGWARN
311  std::ostream &warn_log() const {
312  return warn_log(_label);
313  }
314 #else
315  static DummyStream &warn_log() {
316  return _dummyLog;
317  }
318 #endif
319 #ifdef TASKRUNNER_LOGINFO
328  std::ostream &log() const {
329  return log(_label);
330  }
331 #else
332  static DummyStream &log() {
333  return _dummyLog;
334  }
335 #endif
336 #ifdef TASKRUNNER_LOGDBG
345  std::ostream &dbg_log() const {
346  *_logFile << "\n" << global_elapsed_ms() << ' ' << _label << ": ";
347  return *_logFile;
348  }
349 #else
350  static DummyStream &dbg_log() {
351  return _dummyLog;
352  }
353 #endif
354 private:
355  static int64_t global_elapsed_ms() {
356  return msSince(global_start_time);
357  }
358  std::string _label;
359 
360 #ifdef USE_THREADS
361  thread_local
362 #endif
363  static bool in_error;
364 #ifdef USE_THREADS
365  thread_local
366 #endif
367  static TimePoint global_start_time;
368 #ifdef USE_THREADS
369  thread_local
370 #endif
371  static std::ostream *_logFile;
372 #ifdef USE_THREADS
373  thread_local
374 #endif
375  static std::ostringstream _blackHole;
376 #ifdef USE_THREADS
377  thread_local
378 #endif
379  static unsigned int log_count, warn_count, err_count,
380  log_count_saved, warn_count_saved, err_count_saved;
381  static DummyStream _dummyLog;
382 };
This class is used to optionally disable logging operations at compile time.
Definition: logger.h:34
DummyStream & operator<<(T)
Do nothing, emulating the << stream operator.
Definition: logger.h:38
DummyStream & operator<<(std::ostream &(*)(std::ostream &))
Do nothing, emulating the << stream operator.
Definition: logger.h:54
A simple logger. All classes that want to write to the global log file should inherit from this class...
Definition: logger.h:86
std::string label() const
Return the object's log label.
Definition: logger.h:251
static int64_t msTo(const TimePoint &t)
Definition: logger.cpp:34
static bool inError()
Return true if any error has been logged (globally since start)
Definition: logger.h:119
static void setLogLimit(unsigned int loglines=0, unsigned int warnlines=0, unsigned int errlines=0)
Set max number of lines of info/warn/err log.
Definition: logger.cpp:117
static void flushLogFile()
Definition: logger.h:187
static void reopenLogFile(const std::string &filename)
If current log is a file (ofstream), reopen it with new filename:
Definition: logger.cpp:173
static TimePoint timeMax()
Return a very distant time.
Definition: logger.h:228
Logger(std::string label)
Definition: logger.h:90
static bool hasExpired(const TimePoint &t)
Return true if current time is after the given TimePoint.
Definition: logger.h:213
static int64_t msSince(const TimePoint &t)
Definition: logger.cpp:28
std::ostream & errno_log() const
Write a line of error log after a failed system call has set the global errno to a non-zero value.
Definition: logger.cpp:143
static std::string dateString2(time_t t=0)
Return local time, formatted as Sat, 14 Oct 2023 09:38:47.
Definition: logger.cpp:50
static TimePoint timeNow()
Return current time.
Definition: logger.h:218
static std::string createHashKey(unsigned int length=20)
Return a random string.
Definition: logger.cpp:60
static TimePoint timeAfter(double s)
Return current time plus s seconds.
Definition: logger.h:223
std::ostream & log() const
Write a line of info log.
Definition: logger.h:328
static void pauseLogging()
Disable all log output until next call to Logger::setLogFile.
Definition: logger.h:192
std::ostream & dbg_log() const
Write a line of debug log.
Definition: logger.h:345
static std::string dateString(time_t t=0)
Return local time, formatted as 2023-10-14T09:38:47+0200.
Definition: logger.cpp:40
static double secondsTo(const TimePoint &t)
Definition: logger.cpp:22
static void setLogFile(std::ostream &stream)
Set global log destination.
Definition: logger.cpp:166
void resetLabel(const std::string &new_label)
Modify the object's log label.
Definition: logger.h:256
static std::chrono::microseconds toUs(double t)
Convert s (seconds) to std::chrono::microseconds.
Definition: logger.h:233
std::ostream & warn_log() const
Write a line of warning log.
Definition: logger.h:311
static void sayTime(std::ostream &stream)
Write current local time to the given stream.
Definition: logger.cpp:131
static std::ostream & log(const std::string &label)
Write a line of info log.
Definition: logger.h:170
static std::ostream & warn_log(const std::string &label)
Write a line of warning log.
Definition: logger.h:151
static std::ostream & err_log(const std::string &label)
Write a line of error log.
Definition: logger.h:131
std::ostream & err_log() const
Write a line of error log.
Definition: logger.h:292
static double secondsSince(const TimePoint &t)
Definition: logger.cpp:16
Measure elapsed time during execution, for example by timer events.