logger.cpp
2.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*
* Simple stream-based logger for C++11.
*
* Adapted from
* http://vilipetek.com/2014/04/17/thread-safe-simple-logger-in-c11/
*/
#include "utils/logger.hpp"
#include <iostream>
#include <iomanip>
// needed for MSVC
#ifdef WIN32
#define localtime_r(_Time, _Tm) localtime_s(_Tm, _Time)
#endif // localtime_r
namespace redox {
namespace log {
// Convert date and time info from tm to a character string
// in format "YYYY-mm-DD HH:MM:SS" and send it to a stream
std::ostream &operator<<(std::ostream &stream, const tm *tm) {
// I had to muck around this section since GCC 4.8.1 did not implement std::put_time
// return stream << std::put_time(tm, "%Y-%m-%d %H:%M:%S");
return stream << 1900 + tm->tm_year << '-' <<
std::setfill('0') << std::setw(2) << tm->tm_mon + 1 << '.'
<< std::setfill('0') << std::setw(2) << tm->tm_mday << ' '
<< std::setfill('0') << std::setw(2) << tm->tm_hour << ':'
<< std::setfill('0') << std::setw(2) << tm->tm_min << ':'
<< std::setfill('0') << std::setw(2) << tm->tm_sec;
}
// --------------------
// Logstream
// --------------------
Logstream::Logstream(Logger &logger, Level loglevel) :
m_logger(logger), m_loglevel(loglevel) {
}
Logstream::Logstream(const Logstream &ls) :
m_logger(ls.m_logger), m_loglevel(ls.m_loglevel) {
// As of GCC 8.4.1 basic_stream is still lacking a copy constructor
// (part of C++11 specification)
//
// GCC compiler expects the copy constructor even thought because of
// RVO this constructor is never used
}
Logstream::~Logstream() {
if(m_logger.level() <= m_loglevel)
m_logger.log(m_loglevel, this->str());
}
// --------------------
// Logger
// --------------------
Logger::Logger(std::string filename, Level loglevel) :
m_file(filename, std::fstream::out | std::fstream::app | std::fstream::ate),
m_stream(m_file), m_loglevel(loglevel) {}
Logger::Logger(std::ostream &outfile, Level loglevel) :
m_stream(outfile), m_loglevel(loglevel) {}
Logger::~Logger() {
m_stream.flush();
}
const tm *Logger::getLocalTime() {
auto in_time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
localtime_r(&in_time_t, &m_time);
return &m_time;
}
void Logger::log(Level l, std::string oMessage) {
const static char *LevelStr[] = {
"[Trace] ", "[Debug] ", "[Info] ", "[Warning]", "[Error] ", "[Fatal] "
};
m_lock.lock();
m_stream << '(' << getLocalTime() << ") "
<< LevelStr[l] << "\t"
<< oMessage << std::endl;
m_lock.unlock();
}
} // End namespace
} // End namespace