diff options
Diffstat (limited to 'source/10-common/Log.cpp')
-rw-r--r-- | source/10-common/Log.cpp | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/source/10-common/Log.cpp b/source/10-common/Log.cpp new file mode 100644 index 0000000..83d81e9 --- /dev/null +++ b/source/10-common/Log.cpp @@ -0,0 +1,116 @@ +#include "Log.hpp" + +#include "Macros.hpp" + +#include <robin_hood.h> +#include <algorithm> +#include <cstdio> + +namespace ProjectBrussel_UNITY_ID { +using namespace Log; + +const char* MapMessageLevelToString(MessageLevel level) { + switch (level) { + using enum MessageLevel; + case Debug: return "DEBUG"; + case Info: return "INFO"; + case Warning: return "WARN"; + case Error: return "ERROR"; + default: UNREACHABLE; + } +} + +void PrintMessage(const Message& msg) { + using namespace std::chrono; + + auto t = system_clock::to_time_t(msg.time); + char timeStr[128]; + strftime(timeStr, sizeof(timeStr), "%H:%M:%S", localtime(&t)); + printf("[%s][%s][%s:%u] %.*s\n", + MapMessageLevelToString(msg.level), + timeStr, + msg.srcLoc.function_name(), + msg.srcLoc.line(), + PRINTF_STRING_VIEW(msg.text)); +} + +MessageBufferId gNextBufferId = 0; +robin_hood::unordered_map<MessageBufferId, MessageBuffer*> gBuffers; +} // namespace ProjectBrussel_UNITY_ID + +namespace Log { +bool gPrintToStdOut = true; +#if BRUSSEL_DEV_ENV +MessageBuffer gDefaultBuffer; +MessageBufferId gDefaultBufferId; +#endif +} // namespace Log + +Log::MessageBufferId Log::RegisterBuffer(MessageBuffer& buffer) { + using namespace ProjectBrussel_UNITY_ID; + + auto id = gNextBufferId++; + gBuffers.try_emplace(id, &buffer); + return id; +} + +void Log::UnregisterBuffer(MessageBufferId id) { + using namespace ProjectBrussel_UNITY_ID; + + gBuffers.erase(id); +} + +Log::MessageBuffer* Log::GetBuffer(MessageBufferId id) { + using namespace ProjectBrussel_UNITY_ID; + + auto iter = gBuffers.find(id); + if (iter != gBuffers.end()) { + return iter->second; + } else { + return nullptr; + } +} + +void Log::DumpRegisteredBuffers() { + using namespace ProjectBrussel_UNITY_ID; + + puts("================ BEGIN LOG BUFFER DUMP ================"); + for (const auto& [id, buffer] : gBuffers) { + printf("Buffer #%d at %p\n", id, buffer); + printf("Buffer size: %zu\n", buffer->messages.capacity()); + bool needsWrapAround = buffer->messages.GetHeadIdx() >= buffer->messages.GetTailIdx(); + if (needsWrapAround) { + printf("Fill size: %zu in [%zu,%zu) and [0,%zu)\n", + buffer->messages.size(), + // First chunk: [begin,end) + buffer->messages.GetHeadIdx(), + buffer->messages.capacity(), + // Second chunk: [0,end) + buffer->messages.GetTailIdx()); + } else { + printf("Fill size: %zu in [%zu,%zu)\n", + buffer->messages.size(), + // [begin,end) + buffer->messages.GetHeadIdx(), + buffer->messages.GetTailIdx()); + } + for (const auto& msg : buffer->messages) { + // Indent log messages in this buffer + printf("\t"); + PrintMessage(msg); + } + } + puts("================ END LOG BUFFER DUMP ================"); +} + +void Log::Add(const Message& msg) { + using namespace ProjectBrussel_UNITY_ID; + + if (gPrintToStdOut) { + PrintMessage(msg); + } + + for (auto& [_, buffer] : gBuffers) { + buffer->messages.push_back(msg); + } +} |