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
|
#pragma once
#include "RingBuffer.hpp"
#include <fmt/format.h>
#include <chrono>
#include <source_location>
#include <string_view>
// NOTE: we keep this on one line so std::soruce_location reports the correct information
#define GENERIC_LOG(lvl, fmtString, ...) Log::Add(Log::Message{ .level = lvl, .time = std::chrono::system_clock::now(), .srcLoc = std::source_location::current(), .text = fmt::format(fmtString __VA_OPT__(, ) __VA_ARGS__) })
#define LOG_DEBUG(...) GENERIC_LOG(Log::MessageLevel::Debug, __VA_ARGS__)
#define LOG_INFO(...) GENERIC_LOG(Log::MessageLevel::Info, __VA_ARGS__)
#define LOG_WARNING(...) GENERIC_LOG(Log::MessageLevel::Warning, __VA_ARGS__)
#define LOG_ERROR(...) GENERIC_LOG(Log::MessageLevel::Error, __VA_ARGS__)
namespace Log {
enum class MessageLevel {
Debug,
Info,
Warning,
Error,
};
struct Message {
MessageLevel level;
std::chrono::time_point<std::chrono::system_clock> time;
std::source_location srcLoc;
std::string text;
};
/// A mRing buffer of log messages for programmatic inspection at runtime.
struct MessageBuffer {
RingBuffer<Message> messages;
};
/// Unique ID identifying a currently registered MessageBuffer.
using MessageBufferId = int;
MessageBufferId RegisterBuffer(MessageBuffer& buffer);
void UnregisterBuffer(MessageBufferId id);
MessageBuffer* GetBuffer(MessageBufferId id);
void DumpRegisteredBuffers();
extern bool gPrintToStdOut;
#if BRUSSEL_DEV_ENV
// NOTE: initialized in main.cpp
extern MessageBuffer gDefaultBuffer;
extern MessageBufferId gDefaultBufferId;
#endif
// TODO improve this interface: don't copy std::string when there is in fact no MessageBuffer registered
void Add(const Message& msg);
} // namespace Log
|