Cogs.Core
StructuredLogger.cpp
1#include "StructuredLogger.h"
2#include "LogManager.h"
3
4#include <cstdio>
5#include <cstring>
6#include <chrono>
7
8namespace
9{
10 void writeStrWithoutNewlines(const char* str, FILE* stream) {
11 const char* start = str;
12 const char* end = str;
13
14 while (*end) {
15 if (*end == '\n' || *end == '\r') {
16 if (end > start) {
17 std::fwrite(start, 1, end - start, stream);
18 }
19 std::fputc(' ', stream);
20 start = end + 1;
21 }
22 end++;
23 }
24
25 if (end > start) {
26 std::fwrite(start, 1, end - start, stream);
27 }
28 }
29}
31{
32 static StructuredLogger i;
33
34 return i;
35}
36
37void Cogs::Logging::StructuredLogger::consumeMessage(const char* source, Category category, uint32_t /*errorNumber*/, const char* message, const char* filename, int lineNumber)
38{
39 thread_local static char buffer[500] = {};
40 constexpr const char categoryNames[] = { 'T', 'D', 'I', 'W', 'E', 'F' };
41
42 const char level = categoryNames[static_cast<int>(category)];
43
44 // Get current timestamp in ISO 8601 format with milliseconds
45 auto now = std::chrono::system_clock::now();
46 auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
47 auto now_c = std::chrono::system_clock::to_time_t(now);
48 std::tm now_tm = *std::gmtime(&now_c);
49
50 char timestamp[25];
51 std::strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", &now_tm);
52 std::snprintf(timestamp + 19, 6, ".%03dZ", static_cast<int>(now_ms.count()));
53
54 int n = 0;
55 if(outputFilenames && filename && filename[0] != '\0') {
56 n = std::snprintf(buffer, sizeof(buffer) - 1, "%c %s (%s:%d) [%s] ", level, timestamp, filename, lineNumber, source);
57 }
58 else {
59 n = std::snprintf(buffer, sizeof(buffer) - 1, "%c %s [%s] ", level, timestamp, source);
60 }
61
62 // Guard against overflow if very long prefix generated. Format error < 0 not probable.
63 n = std::max(n, 0);
64 n = std::min(n, int(sizeof(buffer)));
65
66 LockGuard lock(mutex);
67
68 std::fwrite(buffer, 1, n, stderr);
69 writeStrWithoutNewlines(message, stderr);
70 std::fputc('\n', stderr);
71
72 if(category >= Category::Error) {
73 std::fflush(stderr);
74 }
75}
static StructuredLogger & instance()
Retrieve the global StructuredLogger instance.
Category
Logging categories used to filter log messages.
Definition: LogManager.h:31