16 template<sbo_poly_assignable_c<base_logger_stream> stream_t>
17 static constexpr
auto logger_stream_filter = [](
const logger::logger_sbo& stream)
19 return stream->is<stream_t>();
24 inline logger::logger() noexcept
30 inline logger::~logger() noexcept
35 template<sbo_poly_assignable_c<base_logger_stream> stream_t>
38 std::unique_lock _(m_StreamsMutex);
39 m_Streams.emplace_back(std::move(stream));
42 template<sbo_poly_assignable_c<base_logger_stream> stream_t>
45 auto it = std::ranges::find_if(m_Streams, details::logger_stream_filter<stream_t>);
46 return it != m_Streams.end() ?
static_cast<stream_t*
>(&it->get()) :
nullptr;
49 template<sbo_poly_assignable_c<base_logger_stream> stream_t>
52 return m_Streams | std::views::filter(details::logger_stream_filter<stream_t>)
53 | std::views::transform(
56 return static_cast<stream_t*
>(&stream.get());
62 return m_StreamsMutex;
65 template<sbo_poly_assignable_c<base_logger_stream> stream_t>
68 std::unique_lock _(m_StreamsMutex);
69 return std::erase_if(m_Streams, details::logger_stream_filter<stream_t>);
79 std::unique_lock _(m_RegisteredCategoriesMutex);
80 m_RegisteredCategories.emplace(svCategoryName, std::move(data));
87 if (eResult == compile_pattern_result::ok)
88 m_sDefaultPattern = std::move(sPattern);
96 std::thread::id threadId,
97 std::chrono::system_clock::time_point messageTime,
99 string_view svFunction,
107 std::shared_lock _(m_RegisteredCategoriesMutex);
108 if (
auto itRegisteredCategory = m_RegisteredCategories.find(
category.
get_name());
109 itRegisteredCategory != m_RegisteredCategories.end())
112 if (data.FormatUserMessage)
114 message = data.FormatUserMessage(std::move(message), m_StringsPool);
119 if (eMessageNecessity != message_necessity_type::not_required)
124 finalLogMessage.sValue,
136 std::shared_lock _(m_StreamsMutex);
137 for (
auto& stream : m_Streams)
139 if (eMessageNecessity != message_necessity_type::one_of_streams_requires
140 || stream->log_unconditionally_required(
149 std::optional<logger_string_pool::item> optStreamLogMessage;
150 if (
const std::optional<string_view> optPattern = stream->get_pattern())
152 optStreamLogMessage = m_StringsPool.
acquire();
154 optStreamLogMessage->sValue,
174 optStreamLogMessage ? optStreamLogMessage->sValue : finalLogMessage.sValue);
176 if (optStreamLogMessage)
177 m_StringsPool.
release(std::move(*optStreamLogMessage));
182 m_StringsPool.
release(std::move(finalLogMessage));
185 m_StringsPool.
release(std::move(message));
190 std::shared_lock _(m_StreamsMutex);
191 for (
auto& stream : m_Streams)
200 std::unique_lock _(m_StreamsMutex);
205 std::unique_lock _(m_RegisteredCategoriesMutex);
206 m_RegisteredCategories.clear();
222 verbosity eVerbosity,
223 std::thread::id threadId,
224 std::chrono::system_clock::time_point messageTime,
226 string_view svFunction,
227 int nLine)
const noexcept
231 std::shared_lock _(m_StreamsMutex);
232 const bool bSomeStreamRequires = std::ranges::any_of(
234 [&
category, eVerbosity, threadId, messageTime, svFile, svFunction, nLine](
const auto& stream)
236 return stream->log_unconditionally_required(
245 if (bSomeStreamRequires)
246 eMessageNecessity |= message_necessity_type::one_of_streams_requires;
250 std::shared_lock _(m_RegisteredCategoriesMutex);
251 if (
auto itRegisteredCategory = m_RegisteredCategories.find(
category.
get_name());
252 itRegisteredCategory != m_RegisteredCategories.end())
255 if (eVerbosity >= data.eRuntimeVerbosity)
256 eMessageNecessity |= message_necessity_type::category_verbosity;
260 if (eVerbosity >= verbosity::log)
261 eMessageNecessity |= message_necessity_type::default_verbosity;
263 return eMessageNecessity;
268 return &m_StringsPool;
A category is a class that identifies a particular piece of code. This code can be located in differe...
constexpr string_view get_name() const noexcept
Get category name.
Wrapper for enumerations to be used as a list of flags.
size_t remove_streams() noexcept
Remove all the streams of the given type.
auto get_streams() noexcept
Get all the streams of the given type.
flags< message_necessity_type > get_message_necessity_type(const category &category, verbosity eVerbosity, std::thread::id threadId, std::chrono::system_clock::time_point messageTime, string_view svFile, string_view svFunction, int nLine) const noexcept
Check if this message will go somewhere.
void add_stream(stream_t stream) noexcept
Add an output stream to the logger.
void register_category(const category &category, category_data data) noexcept
Add custom rules for category.
std::shared_mutex & get_streams_mutex() noexcept
Get streams mutex.
stream_t * get_stream() noexcept
Get the first occurrence of a stream of the given type.
virtual void log_macro(const category &category, verbosity eVerbosity, std::thread::id threadId, std::chrono::system_clock::time_point messageTime, string_view svFile, string_view svFunction, int nLine, logger_string_pool::item message)
Main log function: log to all streams. For macro and internal usage.
virtual void reset() noexcept
Reset logger and clear all streams.
virtual void flush()
Flush all streams.
compile_pattern_result set_default_pattern(string sPattern) noexcept
Compile and set the default pattern for log messages.
Fixed-size atomic string pool.
item acquire()
Acquire a string from the pool.
void release(item item)
Return a string back to the pool.
Small Buffer Object for polymorphic classes.
void format_log_specifiers(string &sStorage, string_view svPattern, const category &category, verbosity eVerbosity, std::thread::id threadId, std::chrono::system_clock::time_point messageTime, string_view svFile, string_view svFunction, int nLine, string_view svMessage)
Format sStorage using qx::logger_specifiers.
compile_pattern_result compile_pattern(basic_string< char_t, traits_t > &sPattern) noexcept
Compile an fmt pattern with named arguments into replacement fields.