gz-cpp-util 1.3
A c++20 library containing various utilities
log.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <vector>
4
6
7#include <iostream>
8#include <string>
9
10#ifdef LOG_MULTITHREAD
11#include <mutex>
12#endif
13
14// the higher level needs to include the lower ones
15#ifdef LOG_LEVEL_0
16#define LOG_LEVEL_1
17#endif
18
19#ifdef LOG_LEVEL_1
20#define LOG_LEVEL_2
21#endif
22
23#ifdef LOG_LEVEL_2
24#define LOG_LEVEL_3
25#endif
26
27namespace gz {
29 constexpr unsigned int LOG_RESERVE_STRING_SIZE = 100;
30 constexpr unsigned int ARG_COUNT_RESERVE_COUNT = 6;
31
32 constexpr unsigned int LOG_TIMESTAMP_CHAR_COUNT = 22;
33 constexpr unsigned int LOG_POSTPREFIX_CHAR_COUNT = 2;
34
35
36 //
37 // COLORS
38 //
40 enum Color {
41 RESET,
42 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE,
43 BO_BLACK, BO_RED, BO_GREEN, BO_YELLOW, BO_BLUE, BO_MAGENTA, BO_CYAN, BO_WHITE,
44 BG_BLACK, BG_RED, BG_GREEN, BG_YELLOW, BG_BLUE, BG_MAGENTA, BG_CYAN, BG_WHITE,
45 LI_RED, LI_GREEN, LI_YELLOW, LI_BLUE, LI_MAGENTA, LI_CYAN, LI_WHITE, LI_BLACK,
46 };
47 extern const char* COLORS[];
48
49
50 //
51 // LOG
52 //
59 template<typename T>
61
67 std::string logfile = "log.log";
69 bool showLog = true;
71 bool storeLog = true;
73 std::string prefix = "";
77 bool showTime = true;
83 unsigned int writeAfterLines = 100;
84 };
85
124class Log {
125 public:
135 Log(std::string logfile="log.log", bool showLog=true, bool storeLog=true, std::string&& prefix="", Color prefixColor=RESET, bool showTime=true, Color timeColor=RESET, bool clearLogfileOnRestart=true, unsigned int writeAfterLines=100);
136
142 Log(LogCreateInfo&& createInfo);
143
144 ~Log();
145
146 //
147 // ACTUAL LOGGING
148 //
152
162 template<Logable... Args>
163 void log(Args&&... args);
164
175 template<Logable... Args>
176 void clog(const std::vector<Color>& colors, Args&&... args);
177
178
179 //
180 // CONVENCIENCE
181 //
185 template<Logable... Args>
186 void operator() (Args&&... args) {
187 log(std::forward<Args>(args)...);
188 }
189
198 template<Logable... Args>
199 void error(Args&&... args) {
200 clog({RED, WHITE}, "Error:", std::forward<Args>(args)...);
201 }
202
211 template<Logable... Args>
212 void warning(Args&&... args) {
213 clog({YELLOW, WHITE}, "Warning:", std::forward<Args>(args)...);
214 }
216
220
223 template<Logable... Args>
224 inline void log0(Args&&... args);
228 template<Logable... Args>
229 inline void log1(Args&&... args);
233 template<Logable... Args>
234 inline void log2(Args&&... args);
238 template<Logable... Args>
239 inline void log3(Args&&... args);
240
244 template<Logable... Args>
245 inline void clog0(const std::vector<Color>& colors, Args&&... args);
249 template<Logable... Args>
250 inline void clog1(const std::vector<Color>& colors, Args&&... args);
254 template<Logable... Args>
255 inline void clog2(const std::vector<Color>& colors, Args&&... args);
259 template<Logable... Args>
260 inline void clog3(const std::vector<Color>& colors, Args&&... args);
262
263 private:
264 // vlog for variadic log
266 template<util::Stringy T, Logable... Args>
267 void vlog(const char* appendChars, T&& t, Args&&... args);
268
270 template<ConvertibleToString T, Logable... Args>
271 void vlog(const char* appendChars, T&& t, Args&&... args) requires (!util::Stringy<T>);
272
274 void vlog(const char* appendChars) {};
275
276 private:
277 void init();
279 std::vector<std::string> logLines;
281 std::vector<std::string::size_type> argsBegin;
283 size_t iter = 0;
290 bool clearLogfileOnRestart;
292 std::string logFile;
293 bool storeLog;
294 void writeLog();
296
297 bool showLog;
298 Color prefixColor;
299 std::string prefix;
300
305 bool showTime;
306 Color timeColor;
308 char time[LOG_TIMESTAMP_CHAR_COUNT];
310 void getTime();
312
313#ifdef LOG_MULTITHREAD
315 static std::mutex mtx;
316#endif
317}; // class Log
318
319
320//
321// DEFINITIONS
322//
323 template<Logable... Args>
324 void Log::log(Args&&... args) {
325#ifdef LOG_MULTITHREAD
326 mtx.lock();
327#endif
328 argsBegin.clear();
329 if (showTime) {
330 getTime();
331 logLines[iter] = time;
332 }
333 else {
334 logLines.clear();
335 }
336 argsBegin.emplace_back(logLines[iter].size());
337 logLines[iter] += prefix;
338
339 vlog(" ", std::forward<Args>(args)...);
340 logLines[iter] += "\n";
341 argsBegin.emplace_back(logLines[iter].size());
342
343 if (showLog) {
344 // time
345 std::cout << COLORS[timeColor] << std::string_view(logLines[iter].begin(), logLines[iter].begin() + argsBegin[0])
346 // prefix
347 << COLORS[prefixColor] << std::string_view(logLines[iter].begin() + argsBegin[0], logLines[iter].begin() + argsBegin[1]) << COLORS[RESET]
348 // message
349 << std::string_view(logLines[iter].begin() + argsBegin[1], logLines[iter].end());
350 }
351 if (++iter >= writeToFileAfterLines) {
352 iter = 0;
353 writeLog();
354 }
355#ifdef LOG_MULTITHREAD
356 mtx.unlock();
357#endif
358 }
359
360
361 template<Logable... Args>
362 void Log::clog(const std::vector<Color>& colors, Args&&... args) {
363#ifdef LOG_MULTITHREAD
364 mtx.lock();
365#endif
366 argsBegin.clear();
367 if (showTime) {
368 getTime();
369 logLines[iter] = std::string(time);
370 }
371 else {
372 logLines.clear();
373 }
374 argsBegin.emplace_back(logLines[iter].size());
375 logLines[iter] += prefix;
376
377 vlog(" ", std::forward<Args>(args)...);
378 logLines[iter] += "\n";
379 argsBegin.emplace_back(logLines[iter].size());
380
381 if (showLog) {
382 // time
383 std::cout << COLORS[timeColor] << std::string_view(logLines[iter].begin(), logLines[iter].begin() + argsBegin[0])
384 // prefix
385 << COLORS[prefixColor] << std::string_view(logLines[iter].begin() + argsBegin[0], logLines[iter].begin() + argsBegin[1]) << COLORS[RESET];
386 // max index where i can be used for colors and i+2 can be used for currentViews
387 size_t maxI = std::min(colors.size(), argsBegin.size() - 2);
388 for (size_t i = 0; i < maxI; i++) {
389 std::cout << COLORS[colors[i]] << std::string_view(logLines[iter].begin() + argsBegin[i+1], logLines[iter].begin() + argsBegin[i+2]);
390 }
391 // log the rest, maxI is now <= argsBegin.size() - 2
392 std::cout << std::string_view(logLines[iter].begin() + argsBegin[maxI+1], logLines[iter].end()) << COLORS[RESET];
393 }
394 if (++iter >= writeToFileAfterLines) {
395 iter = 0;
396 writeLog();
397 }
398#ifdef LOG_MULTITHREAD
399 mtx.unlock();
400#endif
401 };
402
403
404 template<util::Stringy T, Logable... Args>
405 void Log::vlog(const char* appendChars, T&& t, Args&&... args) {
406 argsBegin.emplace_back(logLines[iter].size());
407 logLines[iter] += std::string(t);
408 logLines[iter] += appendChars;
409 vlog(" ", std::forward<Args>(args)...);
410 }
412 template<ConvertibleToString T, Logable... Args>
413 void Log::vlog(const char* appendChars, T&& t, Args&&... args) requires (!util::Stringy<T>) {
414 argsBegin.emplace_back(logLines[iter].size());
415 logLines[iter] += toString(t);
416 logLines[iter] += appendChars;
417 vlog(" ", std::forward<Args>(args)...);
418 }
419
420
421 template<Logable... Args>
422 inline void Log::log0(Args&&... args) {
423#ifdef LOG_LEVEL_0
424 this->log(std::forward<Args>(args)...);
425#endif
426 }
427
428 template<Logable... Args>
429 inline void Log::log1(Args&&... args) {
430#ifdef LOG_LEVEL_1
431 this->log(std::forward<Args>(args)...);
432#endif
433 }
434
435 template<Logable... Args>
436 inline void Log::log2(Args&&... args) {
437#ifdef LOG_LEVEL_2
438 this->log(std::forward<Args>(args)...);
439#endif
440 }
441
442 template<Logable... Args>
443 inline void Log::log3(Args&&... args) {
444#ifdef LOG_LEVEL_3
445 this->log(std::forward<Args>(args)...);
446#endif
447 }
448
449
450 template<Logable... Args>
451 inline void Log::clog0(const std::vector<Color>& colors, Args&&... args) {
452#ifdef LOG_LEVEL_0
453 this->clog(colors, std::forward<Args>(args)...);
454#endif
455 }
456
457 template<Logable... Args>
458 inline void Log::clog1(const std::vector<Color>& colors, Args&&... args) {
459#ifdef LOG_LEVEL_1
460 this->clog(colors, std::forward<Args>(args)...);
461#endif
462 }
463
464 template<Logable... Args>
465 inline void Log::clog2(const std::vector<Color>& colors, Args&&... args) {
466#ifdef LOG_LEVEL_2
467 this->clog(colors, std::forward<Args>(args)...);
468#endif
469 }
470
471 template<Logable... Args>
472 inline void Log::clog3(const std::vector<Color>& colors, Args&&... args) {
473#ifdef LOG_LEVEL_3
474 this->clog(colors, std::forward<Args>(args)...);
475#endif
476 }
477} // namespace gz
478
Manages printing messages to stdout and to logfiles.
Definition: log.hpp:124
std::string logFile
Absolute path to the logfile.
Definition: log.hpp:292
std::vector< std::string > logLines
Where the lines are stored.
Definition: log.hpp:279
void clog1(const std::vector< Color > &colors, Args &&... args)
Enabled with LOG_LEVEL_1 or higher.
Definition: log.hpp:458
void warning(Args &&... args)
Log a warning.
Definition: log.hpp:212
std::vector< std::string::size_type > argsBegin
Used during log: string views into the single substrings in logLines[currentLine].
Definition: log.hpp:281
void clog0(const std::vector< Color > &colors, Args &&... args)
Enabled with LOG_LEVEL_0 or higher.
Definition: log.hpp:451
void clog2(const std::vector< Color > &colors, Args &&... args)
Enabled with LOG_LEVEL_2 or higher.
Definition: log.hpp:465
void log3(Args &&... args)
Enabled with LOG_LEVEL_3 or higher.
Definition: log.hpp:443
void vlog(const char *appendChars)
End for the recursion.
Definition: log.hpp:274
void operator()(Args &&... args)
Logs a message. Overload for convenience, same behavior as log()
Definition: log.hpp:186
void getTime()
Store the current time in yyyy-mm-dd hh:mm:ss format in time member.
Definition: log.cpp:116
void error(Args &&... args)
Log an error.
Definition: log.hpp:199
void log2(Args &&... args)
Enabled with LOG_LEVEL_2 or higher.
Definition: log.hpp:436
void log1(Args &&... args)
Enabled with LOG_LEVEL_1 or higher.
Definition: log.hpp:429
void clog3(const std::vector< Color > &colors, Args &&... args)
Enabled with LOG_LEVEL_3 or higher.
Definition: log.hpp:472
void log(Args &&... args)
Logs a message.
Definition: log.hpp:324
Log(std::string logfile="log.log", bool showLog=true, bool storeLog=true, std::string &&prefix="", Color prefixColor=RESET, bool showTime=true, Color timeColor=RESET, bool clearLogfileOnRestart=true, unsigned int writeAfterLines=100)
Creates a log object, which can print messages to stdout and/or write them to a log file.
Definition: log.cpp:55
unsigned int writeToFileAfterLines
Definition: log.hpp:289
void vlog(const char *appendChars, T &&t, Args &&... args)
Log anything that can be appendend to std::string.
Definition: log.hpp:405
void log0(Args &&... args)
Enabled with LOG_LEVEL_0 or higher.
Definition: log.hpp:422
char time[LOG_TIMESTAMP_CHAR_COUNT]
Stores the current time in yyyy-mm-dd hh:mm:ss format.
Definition: log.hpp:308
void clog(const std::vector< Color > &colors, Args &&... args)
Log a message in a certain color.
Definition: log.hpp:362
size_t iter
The current position in logLines.
Definition: log.hpp:283
Any type where gz::toString(t) exists.
Definition: to_string.hpp:409
Define types that can be logged with Log.
Definition: log.hpp:60
same as std::string, std::string_view or const char*
Definition: to_string.hpp:26
Color
Colors to be used in Log::clog.
Definition: log.hpp:40
constexpr unsigned int LOG_RESERVE_STRING_SIZE
Reserve a string size for each string in logArray. Set to 0 if you do not want to reserve memory for ...
Definition: log.hpp:29
Create info for a Log object.
Definition: log.hpp:65
bool clearLogfileOnRestart
If true, clear the logfile when initializing the log. That means only the log of most recent run is s...
Definition: log.hpp:81
unsigned int writeAfterLines
Actually write the log to the logfile after so many lines. Must be at least 1.
Definition: log.hpp:83
std::string logfile
Absolute or relative path to the logfile.
Definition: log.hpp:67
bool storeLog
Wether to save the messages to the logfile.
Definition: log.hpp:71
bool showTime
Wether to prepend a timestamp to the message.
Definition: log.hpp:77
bool showLog
Wether to print the messages to stdout.
Definition: log.hpp:69
std::string prefix
A prefix that comes between the timestamp and the message. ": " is automatically appended to the pref...
Definition: log.hpp:73
Color prefixColor
The color of the prefix.
Definition: log.hpp:75
Color timeColor
The color of the timestamp.
Definition: log.hpp:79
Contains functions to convert types to string.
std::string toString(const T &s)
Declaration of toString in global namespace, so that concepts can use it.