Made logger thread-safe and added filters.

This commit is contained in:
Patrick Wuttke
2025-07-14 17:16:24 +02:00
parent ad627b7c70
commit 02e99bbc82
3 changed files with 149 additions and 6 deletions

View File

@@ -6,6 +6,7 @@
#include <cstdint>
#include <format>
#include <mutex>
#include <source_location>
#include <string>
#include <vector>
@@ -104,6 +105,20 @@ public:
MIJIN_DEFINE_CHAR_VERSIONS(LogSink)
template<typename TChar = MIJIN_DEFAULT_CHAR_TYPE>
class BaseLogFilter
{
public:
using char_t = TChar;
using message_t = BaseLogMessage<char_t>;
virtual ~BaseLogFilter() noexcept = default;
virtual bool shouldShow(const message_t& message) MIJIN_NOEXCEPT = 0;
};
MIJIN_DEFINE_CHAR_VERSIONS(LogFilter)
#define LOGGER_COMMON_ARGS(chr_type) template<typename T> typename TAllocator = MIJIN_DEFAULT_ALLOCATOR
template<typename TChar = MIJIN_DEFAULT_CHAR_TYPE, typename TTraits = std::char_traits<TChar>, LOGGER_COMMON_ARGS(TChar)>
class BaseLogger
@@ -114,15 +129,22 @@ public:
using allocator_t = TAllocator<char_t>;
using sink_t = BaseLogSink<char_t>;
using filter_t = BaseLogFilter<char_t>;
using level_t = BaseLogLevel<char_t>;
using channel_t = BaseLogChannel<char_t>;
using message_t = BaseLogMessage<char_t>;
using string_t = std::basic_string<char_t, traits_t, allocator_t>;
private:
std::vector<sink_t*, TAllocator<sink_t*>> mSinks;
struct SinkEntry
{
sink_t* sink;
filter_t* filter;
};
std::vector<SinkEntry, TAllocator<SinkEntry>> mSinks;
mutable std::mutex mMutex;
public:
explicit BaseLogger(TAllocator<sink_t*> allocator = {}) MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v<TAllocator<sink_t*>>)
: mSinks(std::move(allocator))
explicit BaseLogger(TAllocator<void> allocator = {}) MIJIN_NOEXCEPT_IF((std::is_nothrow_constructible_v<TAllocator<SinkEntry>, TAllocator<void>&&>))
: mSinks(TAllocator<SinkEntry>(std::move(allocator)))
{}
BaseLogger(const BaseLogger&) = default;
@@ -135,14 +157,25 @@ public:
void addSink(sink_t& sink)
{
mSinks.push_back(&sink);
std::unique_lock _(mMutex);
mSinks.push_back({&sink, nullptr});
}
void addSink(sink_t& sink, filter_t& filter)
{
std::unique_lock _(mMutex);
mSinks.push_back({&sink, &filter});
}
void postMessage(const message_t& message) const MIJIN_NOEXCEPT
{
for (sink_t* sink: mSinks)
std::unique_lock _(mMutex);
for (const SinkEntry& entry : mSinks)
{
sink->handleMessage(message);
if (entry.filter != nullptr && !entry.filter->shouldShow(message)) {
continue;
}
entry.sink->handleMessage(message);
}
}