Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
endif()
option(LOGIT_FORCE_ASYNC_OFF "Force disable async logging" OFF)
option(LOGIT_USE_MPSC_RING "Enable lock-free TaskExecutor queue" ON)
option(LOGIT_ENABLE_DROP_OLDEST_SLOWPATH "Enable TaskExecutor DropOldest slow-path" ON)

if(NOT DEFINED CMAKE_CXX_STANDARD)
if(LOGIT_WITH_OTLP OR LOGIT_WITH_PROMETHEUS_SERVER OR LOGIT_WITH_MDBX)
Expand Down Expand Up @@ -63,10 +62,6 @@ if(LOGIT_USE_MPSC_RING)
target_compile_definitions(log-it-cpp INTERFACE LOGIT_USE_MPSC_RING=1)
endif()

if(LOGIT_ENABLE_DROP_OLDEST_SLOWPATH)
target_compile_definitions(log-it-cpp INTERFACE LOGIT_ENABLE_DROP_OLDEST_SLOWPATH=1)
endif()

if(LOGIT_EMSCRIPTEN)
set(LOGIT_WITH_SYSLOG OFF CACHE BOOL "" FORCE)
set(LOGIT_WITH_WIN_EVENT_LOG OFF CACHE BOOL "" FORCE)
Expand Down
8 changes: 6 additions & 2 deletions include/logit_cpp/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ For subsystem-specific work, also read the nearest guide:
normally consumed through `<logit.hpp>` or the relevant module umbrella.
- Preserve the existing public names, overloads, macro expansion contracts,
and feature guards. Add new API only with a focused test and documentation.
- Keep headers self-contained: include every standard type used directly and
do not depend on include order or transitive headers.
- Keep the supported public umbrellas (`logit.hpp`, `utils.hpp`,
`formatter.hpp`, `loggers.hpp`) self-contained.
- Leaf headers follow the aggregate-first/NHR contract and may rely on
prerequisites prepared by their nearest umbrella. Do not add standalone
include contracts to leaf headers unless explicitly required by the public
API and covered by a focused test.
- A `noexcept` declaration is a contract. Do not perform allocation, invoke a
user callback, or execute code that may throw in a `noexcept` function.
Signal/crash handlers are the explicit exception and must stay async-signal
Expand Down
3 changes: 2 additions & 1 deletion include/logit_cpp/logit/detail/QueuePolicy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ namespace logit { namespace detail {
/// \brief Queue overflow handling policy used by TaskExecutor and SingleThreadExecutor.
enum class QueuePolicy {
DropNewest, ///< Reject the incoming task when the queue is full.
DropOldest, ///< Drop the oldest queued task.
DropOldest, ///< Drop-oldest policy; MPSC mode rejects the incoming task
///< to preserve the ordering of already accepted work.
Block ///< Producers wait until capacity is available.
};

Expand Down
6 changes: 3 additions & 3 deletions include/logit_cpp/logit/log_macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2928,16 +2928,16 @@ static_assert(LOGIT_LEVEL_FATAL == static_cast<int>(logit::LogLevel::LOG_LVL_FAT
logit::detail::TaskExecutor::get_instance().set_max_queue_size(size)

/// \brief Queue policy for dropping the newest task when the queue is full.
#define LOGIT_QUEUE_DROP_NEWEST logit::detail::QueuePolicy::DropNewest
#define LOGIT_QUEUE_DROP_NEWEST logit::QueuePolicy::DropNewest

/// \brief Queue policy for dropping the oldest task when the queue is full.
#define LOGIT_QUEUE_DROP_OLDEST logit::detail::QueuePolicy::DropOldest
#define LOGIT_QUEUE_DROP_OLDEST logit::QueuePolicy::DropOldest

/// \brief Backward-compatible alias for dropping the newest task.
#define LOGIT_QUEUE_DROP LOGIT_QUEUE_DROP_NEWEST

/// \brief Queue policy for blocking when the queue is full.
#define LOGIT_QUEUE_BLOCK logit::detail::QueuePolicy::Block
#define LOGIT_QUEUE_BLOCK logit::QueuePolicy::Block

/// \brief Sets the behavior when the queue is full.
/// \param mode LOGIT_QUEUE_DROP_NEWEST, LOGIT_QUEUE_DROP_OLDEST or LOGIT_QUEUE_BLOCK.
Expand Down
8 changes: 8 additions & 0 deletions include/logit_cpp/logit/loggers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
#include "utils.hpp"
#include "detail/TaskExecutor.hpp"
#include "detail/SingleThreadExecutor.hpp"

namespace logit {

/// \brief Public queue overflow handling policy.
using QueuePolicy = detail::QueuePolicy;

} // namespace logit

#ifndef __EMSCRIPTEN__
#include "detail/CompressionWorker.hpp"
#endif
Expand Down
8 changes: 4 additions & 4 deletions include/logit_cpp/logit/loggers/ConsoleLogger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ namespace logit {
#endif
bool use_dedicated_executor = false; ///< Use a dedicated executor instead of the global TaskExecutor; native builds create one worker thread per logger.
std::size_t queue_capacity = 0; ///< Maximum queue size for the dedicated executor (0 = unlimited).
detail::QueuePolicy queue_policy = detail::QueuePolicy::Block; ///< Overflow policy for the dedicated executor.
QueuePolicy queue_policy = QueuePolicy::Block; ///< Overflow policy for the dedicated executor.
/// \brief Optional level-based stream routing.
/// \details When non-empty, the first matching route (inclusive range
/// `[min_level, max_level]`) wins. Falls back to the primary stream when
Expand Down Expand Up @@ -140,7 +140,7 @@ namespace logit {
bool async,
bool use_dedicated_executor,
std::size_t queue_capacity = 0,
detail::QueuePolicy queue_policy = detail::QueuePolicy::Block)
QueuePolicy queue_policy = QueuePolicy::Block)
: ConsoleLogger(make_config(
async,
use_dedicated_executor,
Expand All @@ -153,7 +153,7 @@ namespace logit {
bool async,
bool use_dedicated_executor,
std::size_t queue_capacity = 0,
detail::QueuePolicy queue_policy = detail::QueuePolicy::Block)
QueuePolicy queue_policy = QueuePolicy::Block)
: ConsoleLogger(stream, make_config(
async,
use_dedicated_executor,
Expand Down Expand Up @@ -429,7 +429,7 @@ namespace logit {
bool async,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy) {
QueuePolicy queue_policy) {
Config config;
config.async = async;
config.use_dedicated_executor = use_dedicated_executor;
Expand Down
10 changes: 5 additions & 5 deletions include/logit_cpp/logit/loggers/EventLogLogger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace logit {
bool async; ///< Use TaskExecutor when true.
bool use_dedicated_executor = false; ///< Use a dedicated executor instead of the global TaskExecutor; native builds create one worker thread per logger.
std::size_t queue_capacity = 0; ///< Maximum queue size for the dedicated executor (0 = unlimited).
detail::QueuePolicy queue_policy = detail::QueuePolicy::Block; ///< Overflow policy for the dedicated executor.
QueuePolicy queue_policy = QueuePolicy::Block; ///< Overflow policy for the dedicated executor.
/// \brief Initialize configuration.
/// \param s Source name.
/// \param a Run asynchronously.
Expand Down Expand Up @@ -66,7 +66,7 @@ namespace logit {
bool async,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy)
QueuePolicy queue_policy)
: EventLogLogger(make_config(
source,
async,
Expand Down Expand Up @@ -164,7 +164,7 @@ namespace logit {
bool async,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy) {
QueuePolicy queue_policy) {
Config config(source, async);
config.use_dedicated_executor = use_dedicated_executor;
config.queue_capacity = queue_capacity;
Expand All @@ -184,7 +184,7 @@ namespace logit {
bool async; ///< Unused flag.
bool use_dedicated_executor = false; ///< Unused flag.
std::size_t queue_capacity = 0; ///< Unused.
detail::QueuePolicy queue_policy = detail::QueuePolicy::Block; ///< Unused.
QueuePolicy queue_policy = QueuePolicy::Block; ///< Unused.
Config(const wchar_t* s = L"", bool a = false) : source(s), async(a) {}
};

Expand All @@ -202,7 +202,7 @@ namespace logit {

/// \brief Construct with parameters and ignored dedicated executor options.
EventLogLogger(const wchar_t* source, bool async, bool use_dedicated_executor,
std::size_t queue_capacity, detail::QueuePolicy queue_policy) {
std::size_t queue_capacity, QueuePolicy queue_policy) {
(void)source; (void)async; (void)use_dedicated_executor;
(void)queue_capacity; (void)queue_policy;
}
Expand Down
16 changes: 8 additions & 8 deletions include/logit_cpp/logit/loggers/FileLogger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ namespace logit {
uint32_t seq_width = 3;
bool use_dedicated_executor = false;
std::size_t queue_capacity = 0;
detail::QueuePolicy queue_policy = detail::QueuePolicy::Block;
QueuePolicy queue_policy = QueuePolicy::Block;
};

FileLogger() { warn(); }
FileLogger(const Config&) { warn(); }
FileLogger(const std::string&, const bool& = true, const int& = 30,
const uint64_t& = 0, const uint32_t& = 0) { warn(); }
FileLogger(const std::string&, const bool&, const int&, bool, std::size_t,
detail::QueuePolicy) { warn(); }
QueuePolicy) { warn(); }
FileLogger(const std::string&, const bool&, const int&, uint64_t, uint32_t,
bool, std::size_t, detail::QueuePolicy) { warn(); }
bool, std::size_t, QueuePolicy) { warn(); }

void log(const LogRecord&, const std::string&) override { warn(); }
std::string get_string_param(const LoggerParam&) const override { return {}; }
Expand Down Expand Up @@ -106,7 +106,7 @@ namespace logit {
uint32_t seq_width = 3; ///< Width of sequence index.
bool use_dedicated_executor = false; ///< Use a dedicated executor instead of the global TaskExecutor; native builds create one worker thread per logger.
std::size_t queue_capacity = 0; ///< Maximum queue size for the dedicated executor (0 = unlimited).
detail::QueuePolicy queue_policy = detail::QueuePolicy::Block; ///< Overflow policy for the dedicated executor.
QueuePolicy queue_policy = QueuePolicy::Block; ///< Overflow policy for the dedicated executor.
};

/// \brief Default constructor that uses default configuration.
Expand Down Expand Up @@ -146,7 +146,7 @@ namespace logit {
const int& auto_delete_days,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy)
QueuePolicy queue_policy)
: FileLogger(make_config(
directory,
async,
Expand Down Expand Up @@ -181,7 +181,7 @@ namespace logit {
uint32_t max_rotated_files,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy)
QueuePolicy queue_policy)
: FileLogger(make_config(
directory,
async,
Expand Down Expand Up @@ -255,7 +255,7 @@ namespace logit {
/// changes async mode or executor ownership. If no dedicated executor exists,
/// only the stored config fields are updated for future reference.
bool set_queue_config(std::size_t queue_capacity,
detail::QueuePolicy queue_policy) {
QueuePolicy queue_policy) {
std::lock_guard<std::mutex> lifecycle_lock(m_lifecycle_mutex);

if (m_shutdown.load(std::memory_order_acquire)) {
Expand Down Expand Up @@ -563,7 +563,7 @@ namespace logit {
uint32_t max_rotated_files,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy) {
QueuePolicy queue_policy) {
Config config;
config.directory = directory;
config.async = async;
Expand Down
10 changes: 5 additions & 5 deletions include/logit_cpp/logit/loggers/SyslogLogger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace logit {
bool async; ///< Use TaskExecutor when true.
bool use_dedicated_executor = false; ///< Use a dedicated executor instead of the global TaskExecutor; native builds create one worker thread per logger.
std::size_t queue_capacity = 0; ///< Maximum queue size for the dedicated executor (0 = unlimited).
detail::QueuePolicy queue_policy = detail::QueuePolicy::Block; ///< Overflow policy for the dedicated executor.
QueuePolicy queue_policy = QueuePolicy::Block; ///< Overflow policy for the dedicated executor.
/// \brief Initialize configuration.
/// \param i Identifier string.
/// \param f Facility code.
Expand Down Expand Up @@ -71,7 +71,7 @@ namespace logit {
bool async,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy)
QueuePolicy queue_policy)
: SyslogLogger(make_config(
ident,
facility,
Expand Down Expand Up @@ -163,7 +163,7 @@ namespace logit {
bool async,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy) {
QueuePolicy queue_policy) {
Config config(ident, facility, async);
config.use_dedicated_executor = use_dedicated_executor;
config.queue_capacity = queue_capacity;
Expand All @@ -184,7 +184,7 @@ namespace logit {
bool async; ///< Unused flag.
bool use_dedicated_executor = false; ///< Unused flag.
std::size_t queue_capacity = 0; ///< Unused.
detail::QueuePolicy queue_policy = detail::QueuePolicy::Block; ///< Unused.
QueuePolicy queue_policy = QueuePolicy::Block; ///< Unused.
Config(const char* i="", int f=0, bool a=false) : ident(i), facility(f), async(a) {}
};

Expand All @@ -203,7 +203,7 @@ namespace logit {

/// \brief Construct with parameters and ignored dedicated executor options.
SyslogLogger(const char* ident, int facility, bool async, bool use_dedicated_executor,
std::size_t queue_capacity, detail::QueuePolicy queue_policy) {
std::size_t queue_capacity, QueuePolicy queue_policy) {
(void)ident; (void)facility; (void)async; (void)use_dedicated_executor;
(void)queue_capacity; (void)queue_policy;
}
Expand Down
12 changes: 6 additions & 6 deletions include/logit_cpp/logit/loggers/UniqueFileLogger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ namespace logit {
size_t hash_length = 8;
bool use_dedicated_executor = false;
std::size_t queue_capacity = 0;
detail::QueuePolicy queue_policy = detail::QueuePolicy::Block;
QueuePolicy queue_policy = QueuePolicy::Block;
};

UniqueFileLogger() { warn(); }
UniqueFileLogger(const Config&) { warn(); }
UniqueFileLogger(const std::string&, bool = true, int = 30, size_t = 8) { warn(); }
UniqueFileLogger(const std::string&, bool, int, size_t, bool, std::size_t,
detail::QueuePolicy) { warn(); }
QueuePolicy) { warn(); }

void log(const LogRecord&, const std::string&) override { warn(); }
std::string get_string_param(const LoggerParam&) const override { return {}; }
Expand Down Expand Up @@ -88,7 +88,7 @@ namespace logit {
size_t hash_length = 8; ///< Length of the hash used in filenames.
bool use_dedicated_executor = false; ///< Use a dedicated executor instead of the global TaskExecutor; native builds create one worker thread per logger.
std::size_t queue_capacity = 0; ///< Maximum queue size for the dedicated executor (0 = unlimited).
detail::QueuePolicy queue_policy = detail::QueuePolicy::Block; ///< Overflow policy for the dedicated executor.
QueuePolicy queue_policy = QueuePolicy::Block; ///< Overflow policy for the dedicated executor.
};

/// \brief Default constructor that uses default configuration.
Expand Down Expand Up @@ -132,7 +132,7 @@ namespace logit {
size_t hash_length,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy)
QueuePolicy queue_policy)
: UniqueFileLogger(make_config(
directory,
async,
Expand Down Expand Up @@ -199,7 +199,7 @@ namespace logit {
/// changes async mode or executor ownership. If no dedicated executor exists,
/// only the stored config fields are updated for future reference.
bool set_queue_config(std::size_t queue_capacity,
detail::QueuePolicy queue_policy) {
QueuePolicy queue_policy) {
std::lock_guard<std::mutex> lifecycle_lock(m_lifecycle_mutex);

if (m_shutdown.load(std::memory_order_acquire)) {
Expand Down Expand Up @@ -478,7 +478,7 @@ namespace logit {
size_t hash_length,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy) {
QueuePolicy queue_policy) {
Config config;
config.directory = directory;
config.async = async;
Expand Down
10 changes: 5 additions & 5 deletions include/logit_cpp/logit/loggers/WindowsDebugLogger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ namespace logit {
: async(async_value)
, use_dedicated_executor(false)
, queue_capacity(0)
, queue_policy(detail::QueuePolicy::Block) {}
, queue_policy(QueuePolicy::Block) {}

bool async; ///< Flag indicating whether logging should be asynchronous.
bool use_dedicated_executor; ///< Use a dedicated executor instead of the global TaskExecutor; native builds create one worker thread per logger.
std::size_t queue_capacity; ///< Maximum queue size for the dedicated executor (0 = unlimited).
detail::QueuePolicy queue_policy; ///< Overflow policy for the dedicated executor.
QueuePolicy queue_policy; ///< Overflow policy for the dedicated executor.
};

/// \brief Default constructor that uses default configuration.
Expand All @@ -72,7 +72,7 @@ namespace logit {
bool async,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy)
QueuePolicy queue_policy)
: WindowsDebugLogger(make_config(
async,
use_dedicated_executor,
Expand Down Expand Up @@ -126,7 +126,7 @@ namespace logit {
/// changes async mode or executor ownership. If no dedicated executor exists,
/// only the stored config fields are updated for future reference.
bool set_queue_config(std::size_t queue_capacity,
detail::QueuePolicy queue_policy) {
QueuePolicy queue_policy) {
std::lock_guard<std::mutex> lifecycle_lock(m_lifecycle_mutex);

if (m_shutdown.load(std::memory_order_acquire)) {
Expand Down Expand Up @@ -256,7 +256,7 @@ namespace logit {
bool async,
bool use_dedicated_executor,
std::size_t queue_capacity,
detail::QueuePolicy queue_policy) {
QueuePolicy queue_policy) {
Config config(async);
config.use_dedicated_executor = use_dedicated_executor;
config.queue_capacity = queue_capacity;
Expand Down
3 changes: 2 additions & 1 deletion tests/include_loggers_nhr_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
#include <logit/loggers/ConsoleLogger.hpp>

int main() {
const logit::QueuePolicy policy = logit::QueuePolicy::Block;
logit::ConsoleLogger logger(false);
logger.set_log_level(logit::LogLevel::LOG_LVL_WARN);
logger.wait();
return 0;
return policy == logit::QueuePolicy::Block ? 0 : 1;
}
Loading