PCB Environment: /home/chr/devel/PhD/Environment/pub/PCBEnv/pcbenv/cxx/Log.hpp Source File

PCB Environment 2

Loading...
Searching...
No Matches
Log.hpp
1
2#ifndef GYM_PCB_LOG_H
3#define GYM_PCB_LOG_H
4
5#include <iomanip>
6#include <chrono>
7#include <fstream>
8#include <sstream>
9#include <set>
10#include <string>
11#include <thread>
12
13enum class LogLevel
14{
15 ERROR = 0,
16 WARNING = 1,
17 NOTICE = 2,
18 INFO = 3,
19 DEBUG = 4,
20 TRACE = 5,
21 COUNT = 6
22};
23
24#ifndef GYM_PCB_MAX_LOG_LEVEL
25#define GYM_PCB_MAX_LOG_LEVEL 3
26#endif
27#ifndef GYM_PCB_LOG_SHOW_THREAD
28#define GYM_PCB_LOG_SHOW_THREAD 0
29#endif
30#ifndef GYM_PCB_LOG_FORMAT_TIME
31#define GYM_PCB_LOG_FORMAT_TIME 1
32#endif
33
34#define _PCB_GYM_LOG_IF(v, func, args...) if (int(v) <= GYM_PCB_MAX_LOG_LEVEL && Logger::get().visible(v)) { std::stringstream ___ss; ___ss << args; Logger::get().func(___ss.str()); }
35
36#define ERROR(args...) do { _PCB_GYM_LOG_IF(LogLevel::ERROR, Error, args) } while (0)
37#define WARN(args...) do { _PCB_GYM_LOG_IF(LogLevel::WARNING, Warn, args) } while (0)
38#define INFO(args...) do { _PCB_GYM_LOG_IF(LogLevel::INFO, Info, args) } while (0)
39#define NOTICE(args...) do { _PCB_GYM_LOG_IF(LogLevel::NOTICE, Notice, args) } while (0)
40#define DEBUG(args...) do { _PCB_GYM_LOG_IF(LogLevel::DEBUG, Debug, args) } while (0)
41#define TRACE(args...) do { _PCB_GYM_LOG_IF(LogLevel::TRACE, Trace, args) } while (0)
42
43#define RETURN_ERROR(rv, args...) do { ERROR(args); return rv; } while (0)
44
45 class LogFile
46{
47public:
48 constexpr static const std::size_t MaxSize = 32ull << 20;
49public:
50 std::ostream& stream() { return *mStream; }
51 const std::string& getPath() const { return mPath; }
52 void setPath(const std::string_view);
53 void redirect(LogFile&);
54 bool isOwner() const { return mOwner == this; }
55 LogFile *owner() const { return mOwner; }
56 void ownFile();
57 void updateOwner();
58private:
59 std::ostream *mStream{0};
60 std::string mPath;
61 std::ofstream mFile;
62 LogFile *mOwner{0};
63private:
64 void open(const std::string_view path);
65 void shut(const std::string_view path = "cerr");
66 void truncate(const std::string_view path);
67};
68
69 class Logger
70{
71public:
72 constexpr static const uint NumLevels = uint(LogLevel::COUNT);
73 Logger();
74 ~Logger();
75
76 static Logger& get() { return sDefault; }
77
78 void Error (const std::string &s) { emit(LogLevel::ERROR, " EE ", s); }
79 void Warn (const std::string &s) { emit(LogLevel::WARNING, " WW ", s); }
80 void Info (const std::string &s) { emit(LogLevel::INFO, " II ", s); }
81 void Notice(const std::string &s) { emit(LogLevel::NOTICE, " NN ", s); }
82 void Debug (const std::string &s) { emit(LogLevel::DEBUG, " DD ", s); }
83 void Trace (const std::string &s) { emit(LogLevel::TRACE, " TT ", s); }
84
85 bool visible(LogLevel v) const { return mLevel >= v; }
86
87 void setLevel(const std::string&);
88 void setDefaultLevel(const std::string&);
89 void setLevel(LogLevel);
90 void setPrefix(const std::string&);
91 void setTarget(LogLevel, const std::string &path);
92
93 int indent(int n);
94
95 static char levelChar(LogLevel);
96 static LogLevel level(const std::string_view name);
97 static std::string nowString();
98 static std::string formatDurationUS(uint64_t us);
99 static std::string formatMask(uint32_t);
100
101private:
102 static const char sLevelChars[NumLevels];
103 static Logger sDefault;
104
105private:
106 LogLevel mLevel{LogLevel::INFO};
107 std::string mPrefix;
108 LogFile mFiles[NumLevels];
109 int mIndent{0};
110
111 void emit(LogLevel, const char *pfx, const std::string&);
112};
113
114inline char Logger::levelChar(LogLevel l)
115{
116 assert(uint(l) < NumLevels);
117 return sLevelChars[uint(l)];
118}
119
120inline int Logger::indent(int n)
121{
122 mIndent = std::max(0, mIndent + n);
123 mPrefix = std::string(mIndent, ' ');
124 return mIndent;
125}
126
127inline void Logger::setLevel(const std::string &name)
128{
129 mLevel = level(name);
130}
131inline void Logger::setLevel(LogLevel v)
132{
133 mLevel = v;
134}
135
136inline void Logger::setPrefix(const std::string &s)
137{
138 mPrefix = s;
139 indent(0);
140}
141
142inline void Logger::emit(LogLevel l, const char *pfx, const std::string &s)
143{
144 auto &os = mFiles[uint(l)].stream();
145 if (GYM_PCB_LOG_SHOW_THREAD)
146 os << '<' << std::this_thread::get_id() << "> ";
147 os << nowString() << pfx << mPrefix << s << std::endl;
148}
149
150#endif // GYM_PCB_LOG_H
LogFile
Definition Log.hpp:46