User’s API

Reference for the main public Quill API surface.

Use Guides and Recipes for usage patterns and examples. Use this page when you want the main public options, aliases, classes, and sink types.

If you generate Doxygen for a downstream project, you can link quill:: API types through the published tag file:

TAGFILES = https://quillcpp.readthedocs.io/en/latest/quill.tag=https://quillcpp.readthedocs.io/en/latest/

Backend Options

struct BackendOptions

Configuration options for the backend.

This struct defines settings for the backend thread

Public Members

std::string thread_name = "QuillBackend"

The name assigned to the backend, visible during thread naming queries (e.g., pthread_getname_np) or in the debugger.

bool enable_yield_when_idle = false

The backend employs “busy-waiting” by spinning around each frontend thread’s queue. If enabled, the backend will yield when there is no remaining work, potentially reducing the OS scheduler priority for the backend. This option is effective only when sleep_duration is set to 0.

std::chrono::nanoseconds sleep_duration = std::chrono::microseconds{100}

Specifies the duration the backend sleeps if there is no remaining work to process in the queues.

uint32_t transit_event_buffer_initial_capacity = 256

The backend pops all log messages from the frontend queues and buffers them in a local ring buffer queue as transit events. The transit_event_buffer is unbounded, starting with a customizable initial capacity (in items, not bytes) and will reallocate up to transit_events_hard_limit The backend will use a separate transit_event_buffer for each frontend thread. The capacity is rounded up to the next power of two.

size_t transit_events_soft_limit = 8192

The backend gives priority to reading messages from the frontend queues of all the hot threads and temporarily buffers them.

If a frontend threads continuously push messages to the queue (e.g., logging in a loop), no logs can ever be processed.

When the soft limit is reached the backend worker thread will try to process a batch of cached transit events all at once

The frontend queues are emptied on each iteration, so the actual popped messages can be much greater than the transit_events_soft_limit.

Note

This number represents a limit across the messages received from ALL frontend threads.

size_t transit_events_hard_limit = 65'536

The backend gives priority to reading messages from the frontend queues and temporarily buffers them.

If a frontend thread continuously push messages to the queue (e.g., logging in a loop), no logs can ever be processed.

As the backend buffers messages, it can keep buffering indefinitely if the frontend threads keep pushing.

This limit is the maximum size of the backend event buffer. When reached, the backend will stop reading the frontend queues until there is space available in the buffer.

Note

This number represents a limit PER frontend threads.

std::chrono::microseconds log_timestamp_ordering_grace_period = {5}

The backend iterates through all frontend lock-free queues and pops all messages from each queue. It then buffers and logs the message with the lowest timestamp among them.

Each frontend lock-free queue corresponds to a thread, and when multiple frontend threads are pushing logs simultaneously, it is possible to read a timestamp from the last queue in the iteration but miss that timestamp when the first queue was read because it was not available at that time.

When this option is set to a non-zero value, the backend takes a timestamp (now()) before reading the queues. It uses that timestamp to ensure that each log message’s timestamp from the frontend queues is less than or equal to the stored now() timestamp minus the specified grace period, reducing the chance of processing events out of timestamp order.

Messages that fail the above check remain in the lock-free queue. They are checked again in the next iteration. The timestamp check is performed with microsecond precision.

Example scenario:

  1. Frontend thread takes a timestamp at the very start of logging, then becomes delayed (preempted, blocked, processing slowly, etc.) before pushing to the queue.

  2. Backend thread takes timestamp now() and subtracts the grace period, reads queues up to the adjusted now(), and writes the logs.

  3. Frontend thread wakes up and pushes the message with its already-recorded timestamp to the queue.

  4. Backend thread reads and writes the delayed timestamp, resulting in an out-of-order log.

Setting this option to a non-zero value causes a minor delay in reading messages from the lock-free queues and protects timestamp ordering within the configured grace window. It does not guarantee ordering if a frontend thread records a timestamp and is delayed longer than the grace period before publishing the event to its queue.

Setting log_timestamp_ordering_grace_period to zero disables this grace-period delay.

  • 0μs: Fastest processing, may process messages out of timestamp order

  • 1-5μs: Good default - minimal delay, occasional reordering possible

  • 10-20μs: Better ordering when threads have different queue arrival timing

  • 100μs+: Stricter ordering, but risk of SPSC queue filling up at high throughput logging

This compensates for timing differences in when threads push to their queues, not for timestamp accuracy itself. The backend also assumes timestamps within a single frontend queue are normally non-decreasing; if a wall clock or user-provided clock moves backwards, ensure_monotonic_output_timestamps can correct regular output records.

log_timestamp_ordering_grace_period is the first line of defense: it delays reading newer queue entries so older timestamped events from other frontend threads have time to arrive. ensure_monotonic_output_timestamps is the optional final correction: if an older timestamped regular record still reaches the output stage, it can adjust that record’s sink-visible timestamp instead of letting output time move backwards.

bool ensure_monotonic_output_timestamps = false

Ensures sink-visible timestamps for regular log and metric records do not move backwards.

If a regular log or metric record selected for output has a timestamp lower than the last corrected output timestamp, the backend adjusts it to last_timestamp + 1 nanosecond before formatting, filtering, and writing it to sinks. This is useful when a delayed frontend event escapes the configured grace period or when a clock source moves backwards.

Backtrace records are excluded because they intentionally preserve the timestamp from when the backtrace log was captured, even though they are emitted later. Control events such as flush, logger removal, backtrace setup/flush, and MDC changes are also excluded because they are not written as output records.

This option changes the timestamp displayed in the output for corrected records. It does not affect frontend timestamp capture or the timestamp used to select the next cached event for processing.

This option complements log_timestamp_ordering_grace_period. The grace period keeps eligible queue entries back for a bounded amount of time to preserve original timestamps when possible. This option only applies later, after an event has been selected for output, and only when that event would otherwise move sink-visible time backwards.

bool wait_for_queues_to_empty_before_exit = true

When this option is enabled and the application is terminating, the backend worker thread will not exit until all the frontend queues are empty.

This assumes frontend threads stop logging before backend shutdown begins. A few trailing log statements may still drain successfully, but you should not rely on that behavior. Sustained concurrent logging while Backend::stop() is draining the frontend queues, especially logging in a loop from another thread, can prevent the backend from exiting because the queues may never become empty.

When this option is disabled, the backend will try to read the queues once and then exit. Reading the queues only once means that some log messages can be dropped. This is more likely when log_timestamp_ordering_grace_period is non-zero, because the grace-period cutoff can intentionally leave newer queue entries unread until a later poll.

std::vector<uint16_t> cpu_affinity

Pins the backend to the specified CPUs.

By default, the backend is not pinned to any CPU unless values are specified. It is recommended to pin the backend to shared non-critical CPUs.

Note

On macOS, only the first entry is used because the platform does not expose a per-core affinity API equivalent to Linux/Windows CPU masks.

Note

On Windows, CPU IDs are relative to the backend thread’s current processor group because this option uses SetThreadAffinityMask. Leave this empty and use a custom backend-thread hook if your application needs group-aware affinity.

std::function<void(std::string const&)> error_notifier = {detail::backend_options_default_error_notifier}

The backend may encounter exceptions that cannot be caught within user threads. In such cases, the backend invokes this callback to notify the user.

This function sets up a user error notifier to handle backend errors and notifications, such as when the unbounded queue reallocates or when the bounded queue becomes full.

To disable callback notifications, simply leave the function undefined: std::function<void(std::string const&)> backend_error_notifier = {};

Disabling this callback does not suppress Quill’s fallback formatting-error entries written to sinks. It only disables the callback notifications themselves.

It’s safe to perform logging operations within this function (e.g., LOG_INFO(…)). Calling logger->flush_log(), Backend::stop(), or Frontend::remove_logger_blocking() from the backend thread throws QuillError because the backend cannot wait on itself. If the logger has immediate flush enabled, the implicit flush is silently skipped for backend-thread log calls so generic logging code reused on the backend remains safe.

std::function<void()> backend_worker_on_poll_begin = {}

Optional hook executed by the backend worker thread at the start of each poll iteration. Any exceptions thrown are forwarded to error_notifier. Useful for thread instrumentation (e.g., Tracy). Use a guard if you need a one-time action. The same backend-thread flush behavior as error_notifier applies.

std::function<void()> backend_worker_on_poll_end = {}

Optional hook executed by the backend worker thread at the end of each poll iteration. Any exceptions thrown are forwarded to error_notifier. Useful for thread instrumentation (e.g., Tracy). Use a guard if you need a one-time action. The same backend-thread flush behavior as error_notifier applies.

std::chrono::milliseconds rdtsc_resync_interval = std::chrono::milliseconds{500}

This option is only applicable if at least one frontend is using a Logger with ClockSourceType::Tsc

When the system clock is used, this option can be ignored.

Controls the frequency at which the backend recalculates and syncs the internal RdtscClock with the system time from the system wall clock. The TSC clock can drift slightly over time and is not synchronized with NTP server updates.

Smaller values provide more accurate log timestamps at the cost of additional system clock calls. Changing this value only affects the performance of the backend worker.

std::chrono::milliseconds sink_min_flush_interval = std::chrono::milliseconds{200}

This option specifies the minimum time interval (in milliseconds) before the backend thread flushes the output buffers (flush_sink()) for all sinks in the application.

The backend thread will ensure that no sink is flushed more frequently than this interval. Explicit calls to logger->flush_log() override this interval and trigger an immediate flush.

However, if the backend thread is actively processing messages, flushing may occur less frequently than the specified interval.

Setting this value to 0 disables the feature, causing the backend thread to flush sinks whenever there is no pending work, provided a write to the sink has occurred.

This setting applies globally and affects all sinks in the application.

std::function<bool(char c)> check_printable_char = {detail::backend_options_default_check_printable_char}

This option enables a check that verifies the log message contains only printable characters before forwarding it to the sinks. This adds an extra layer of safety by filtering out non-printable characters from the log file. Any non-printable characters are converted to their equivalent hex value.

The check applies only when at least one argument in a log statement is of type string.

You can customize this callback to define your own range of printable characters if needed.

To disable this check, you can provide: std::function<bool(char c)> check_printable_char = {}

std::array<std::string, LogLevelCount> log_level_descriptions = {"TRACE_L3", "TRACE_L2", "TRACE_L1", "DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "CRITICAL", "BACKTRACE", "NONE"}

Holds descriptive names for various log levels used in logging operations. The indices correspond to LogLevel enum values defined elsewhere in the codebase. These names provide human-readable identifiers for each log level.

std::array<std::string, LogLevelCount> log_level_short_codes = {"T3", "T2", "T1", "D", "I", "N", "W", "E", "C", "BT", "_"}

Short codes or identifiers for each log level.

Provides short codes representing each log level for compact identification and usage. The indices correspond to LogLevel enum values defined elsewhere in the codebase.

std::string mdc_format_pattern = " [{}: {}, ]"

Format string used when rendering PatternFormatter’s %(mdc).

The string must contain exactly two “{}” placeholders. The text is split into four parts:

  • prefix: everything before the first “{}”

  • key-value separator: between the first and second “{}”

  • field separator: between the second “{}” and the last character

  • suffix: the last character

For example, the default “ [{}: {}, ]” renders: “ [request_id: 42, user: alice]”

When no MDC is set, %(mdc) expands to an empty string.

Invalid patterns are rejected with QuillError during backend initialization.

bool check_backend_singleton_instance = true

Enables a runtime check to detect multiple instances of the backend singleton.

When mixing shared and static libraries, linkage issues can lead to multiple instances of the backend singleton. This may result in multiple backend worker threads running simultaneously, causing unexpected behavior or crashes.

This issue commonly occurs on Windows when Quill is compiled as a static library and linked into both a shared library and the main executable, creating separate instances. While using Quill as a static library is generally recommended, in such cases, the preferred approach is to have one shared library own Quill and export/import its shared symbols consistently (for example, define QUILL_DLL_EXPORT while building that DLL and QUILL_DLL_IMPORT in consumers on Windows).

On Windows, this check is implemented using a named mutex, whereas on POSIX systems (Linux, macOS), it uses flock() on a lock file in /tmp. In rare cases, this mechanism may interfere with certain environments or containerized deployments. If necessary, this check can be disabled by setting this option to false.

Setting this option to true enables the check, while setting it to false disables it.

Backend Class

class Backend

Public Static Functions

static inline void start(BackendOptions const &options = BackendOptions{})

Starts the backend thread.

Note

Concurrent calls to start() and stop() from different threads are not supported.

Parameters:
BackendOptions const &options = BackendOptions{}

Backend options to configure the backend behavior.

template<typename TFrontendOptions>
static inline void start(BackendOptions const &backend_options, SignalHandlerOptions const &signal_handler_options)

Starts the backend thread and initialises a signal handler.

Note

Enabling the built-in signal handler overrides the listed process signal handlers.

Note

Concurrent calls to start() and stop() from different threads are not supported.

Note

When using the SignalHandler on Linux/MacOS, ensure that each spawned thread in your application has performed one of the following actions: i) Logged at least once. or ii) Called Frontend::preallocate(). or iii) Blocked signals on that thread to prevent the signal handler from running on it. This requirement is because the built-in signal handler utilizes the frontend queue state to issue log statements and wait for flushing. The queue is constructed on its first use with new(). Failing to meet any of the above criteria means the queue may be first-constructed inside the signal handler, which is not signal-safe. Preallocating or logging once on those threads avoids that first-use allocation, but the built-in handler should still be treated as a best-effort crash-preservation facility rather than a general async-signal-safe logging API.

Note

On Windows, Backend::start() installs structured exception and console control handlers. CRT signal handlers are thread-specific and must be installed explicitly with init_signal_handler<TFrontendOptions>() on each frontend/user thread that needs them, not on the backend worker thread.

Parameters:
BackendOptions const &backend_options

Backend options to configure the backend behavior.

SignalHandlerOptions const &signal_handler_options

SignalHandler options to configure the signal handler behavior.

static inline void stop()

Stops the backend thread.

Note

On POSIX systems, when the built-in signal handler is enabled, this restores the Quill-managed signals to their default dispositions. It does not restore any previously installed user handlers.

Note

Concurrent calls to start() and stop() from different threads are not supported.

Note

This function must not be called from backend-thread callbacks because it joins the backend worker thread.

Note

thread-safe

static inline void notify() noexcept

Notifies the backend thread to wake up. It is possible to use a long backend sleep_duration and then notify the backend to wake up from any frontend thread.

Note

thread-safe

static inline bool is_running() noexcept

Checks if the backend is currently running.

Returns:

True if the backend is running, false otherwise.

static inline uint32_t get_thread_id() noexcept

Retrieves the ID of the backend thread.

Returns:

The ID of the backend thread.

static inline uint64_t convert_rdtsc_to_epoch_time(uint64_t rdtsc_value)

Converts an rdtsc value to epoch time. This function uses the same clock as the backend and can be called from any frontend thread. It is useful when using a logger with ClockSourceType::Tsc and you want to obtain a timestamp synchronized with the log files generated by the backend.

Alternatively you can use the Clock class from backend/Clock.h

Parameters:
uint64_t rdtsc_value

The RDTSC value to convert.

Throws:

QuillError – if the backend TSC configuration is invalid.

Returns:

The epoch time corresponding to the RDTSC value.

static inline ManualBackendWorker *acquire_manual_backend_worker()

This feature is designed for advanced users who need to run the backend worker on their own thread, providing more flexibility at the cost of complexity and potential pitfalls.

This approach is generally not recommended due to the potential for inefficiency and complexity in managing the backend worker outside the provided mechanisms.

Important notes:

  • Do not use this to run the library in a single threaded application. This will lead to inefficiencies. The design of this logging library assumes that the backend worker operates in a separate thread from the frontend threads that issue log statements.

  • The thread running the ManualBackendWorker can log, but it must not use backend-waiting flush paths from that same thread. See ManualBackendWorker for the manual-backend threading contract.

  • The ManualBackendWorker should only be used by a single thread. It is not designed to handle multiple threads calling poll() simultaneously.

  • You must call ManualBackendWorker::shutdown() explicitly from the same thread that called init() before that thread exits. Do not rely on the ManualBackendWorker destructor for shutdown ordering.

  • The built-in signal handler is not set up with ManualBackendWorker. If signal handling is required, you must manually set up the signal handler and block signals from reaching the ManualBackendWorker thread. See the start<FrontendOptions>(BackendOptions, SignalHandlerOptions) implementation for guidance on how to do this.

  • The following options are not supported when using ManualBackendWorker: cpu_affinity, thread_name, sleep_duration, and enable_yield_when_idle.

  • Avoid performing very heavy tasks in your custom thread. Significant delays in calling poll() can lead to the SPSC queues of the frontend threads becoming full. When this happens, the frontend threads may need to allocate additional memory on the hot path.

std::thread backend_worker([]()
  {
    quill::ManualBackendWorker* manual_backend_worker = quill::Backend::acquire_manual_backend_worker();

    quill::BackendOptions backend_options;
    manual_backend_worker->init(backend_options);

    while (running)
    {
      manual_backend_worker->poll();
    }

    manual_backend_worker->shutdown();
  });

BackendTscClock Class

class BackendTscClock

A utility class for accessing the Time Stamp Counter (TSC) clock used by the backend logging thread.

This class provides access to the TSC clock maintained by the backend logging thread, allowing for synchronized timestamp retrieval.

Other threads can obtain timestamps synchronized with the TSC clock of the backend logging thread, ensuring synchronization with log statement timestamps.

If ClockSourceType::Tsc is not used by any Logger, this class reverts to using the system clock for providing a timestamp.

Note

For more accurate timestamps, consider reducing rdtsc_resync_interval in BackendOptions.

Note

All methods of the class are thread-safe.

Public Static Functions

static inline time_point now()

Provides the current synchronized timestamp obtained using the TSC clock maintained by the backend logging thread.

Throws:

QuillError – if the backend TSC configuration is invalid.

Returns:

A wall clock timestamp in nanoseconds since epoch, synchronized with the backend logging thread’s TSC clock.

static inline RdtscVal rdtsc() noexcept

Returns the current value of the TSC timer maintained by the backend logging thread.

Returns:

The current value of the TSC timer.

static inline time_point to_time_point(RdtscVal rdtsc)

Converts a TSC (Time Stamp Counter) value to a wall clock timestamp.

Warning

This function will return 0 if no Logger with a TSC clock source has been used. The TSC clock is initialized by the backend thread when the first log statement is processed, provided that a TSC-based logger is used. If the backend thread has not processed any log statements, the function may return zero.

Parameters:
RdtscVal rdtsc

The TSC counter value

Throws:

QuillError – if the backend TSC configuration is invalid.

Returns:

The time since the Unix epoch, in nanoseconds, corresponding to the given TSC counter value.

class RdtscVal

SignalHandler Options

struct SignalHandlerOptions

Struct to hold options for the signal handler.

Public Members

std::vector<int> catchable_signals = {SIGTERM, SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV}

List of signals that the backend should catch if with_signal_handler is enabled. Enabling the built-in signal handler overrides the process handlers for these signals. On Windows, Backend::start() does not consume this list; pass the desired signals to init_signal_handler<TFrontendOptions>() on each thread that needs CRT signal handling.

uint32_t timeout_seconds = 20u

Defines the timeout duration in seconds for the signal handler alarm. It is only available on Linux, as Windows does not support the alarm function. The signal handler sets up an alarm to ensure that the process will terminate if it does not complete within the specified time frame. This is particularly useful to prevent the process from hanging indefinitely in case the signal handler encounters an issue.

std::string logger_name

The name of the logger instance that the signal handler will use to log errors when the application crashes. The logger is accessed by the signal handler and must be created by your application using Frontend::create_or_get_logger(…). If this parameter is left empty, the signal handler will automatically select the first valid logger it finds, excluding any loggers whose names contain substrings specified in excluded_logger_substrings. If a logger name is specified but not found, the signal handler will fall back to the automatic selection behavior described above.

std::vector<std::string> excluded_logger_substrings = {"__csv__"}

List of substrings used to exclude loggers during automatic logger selection. This option is only used when logger_name is empty or when the specified logger is not found. The signal handler will skip any logger whose name contains any of these substrings. This is useful to avoid selecting specialized loggers that write to CSV files, binary files, or other non-standard formats that may not be suitable for crash reporting. Default: {“__csv__”} to exclude CSV loggers.

Frontend Options

struct FrontendOptions

Frontend options are expressed as a traits type.

To override only a subset of options, derive from FrontendOptions and redeclare only the members that change. New members added to FrontendOptions will then be inherited automatically unless the derived type explicitly overrides them.

struct CustomFrontendOptions : FrontendOptions
{
  static constexpr QueueType queue_type = QueueType::BoundedDropping;
  static constexpr size_t initial_queue_capacity = 256u * 1024u;
};

Note

FrontendOptions are intended to be an application-wide choice. Mixing different FrontendImpl<TFrontendOptions> or LoggerImpl<TFrontendOptions> specializations is not a supported configuration. Use one frontend specialization consistently throughout the application.

Public Static Attributes

static QueueType queue_type = QueueType::UnboundedBlocking

Each frontend thread has its own queue, which can be configured with various options:

  • UnboundedBlocking: Starts with initial_queue_capacity and reallocates up to unbounded_queue_max_capacity, then blocks.

  • UnboundedDropping: Starts with initial_queue_capacity and reallocates up to unbounded_queue_max_capacity, then drops log messages.

  • BoundedBlocking: Starts with initial_queue_capacity and never reallocates; blocks when the limit is reached. A single message larger than the fixed queue capacity cannot fit and fails instead of blocking forever.

  • BoundedDropping: Starts with initial_queue_capacity and never reallocates; drops log messages when the limit is reached.

By default, the library uses an UnboundedBlocking queue, which starts with initial_queue_capacity.

static size_t initial_queue_capacity = 128u * 1024u

Initial capacity of the queue.

static uint32_t blocking_queue_retry_interval_ns = 800

Interval for retrying when using BoundedBlocking or UnboundedBlocking. Applicable only when using BoundedBlocking or UnboundedBlocking.

static size_t unbounded_queue_max_capacity = 2ull * 1024u * 1024u * 1024u

Maximum capacity for unbounded queues (UnboundedBlocking, UnboundedDropping). This defines the maximum size to which the queue can grow before blocking or dropping messages.

static HugePagesPolicy huge_pages_policy = HugePagesPolicy::Never

Enables huge pages on the frontend queues to reduce TLB misses. Available only for Linux.

Frontend Class

template<typename TFrontendOptions>
class FrontendImpl

Public Static Functions

static inline void preallocate()

Pre-allocates the thread-local data needed for the current thread.

Although optional, it is recommended to invoke this function during the thread initialization phase before the first log message.

static inline void shrink_thread_local_queue(size_t capacity)

Shrink the thread-local SPSC queue to the specified target capacity.

This function helps manage memory usage by reducing the size of the thread-local queue. In scenarios where a thread pool executes multiple jobs, one job might log a burst of messages that causes the queue to grow significantly. Subsequent jobs may not require such a large capacity, so you can call this function to explicitly shrink the queue to a smaller size.

Note

This function only applies when using the UnboundedQueue configuration. It will have no effect if the BoundedQueue is enabled.

Note

The function will only shrink the queue if the provided target capacity is smaller than the current queue capacity. If the target capacity is greater than or equal to the current capacity, no change is made.

Warning

The Logger object may maintain multiple thread-local queues. This function will only shrink the queue associated with the calling thread, so it is important that the appropriate thread invokes it.

Parameters:
size_t capacity

The desired new capacity for the thread-local SPSC queue.

static inline size_t get_thread_local_queue_capacity() noexcept

Retrieve the current capacity of the thread-local SPSC queue.

This function returns the capacity of the SPSC queue that belongs to the calling thread. It is particularly useful for monitoring how much an UnboundedQueue has grown over time, while for a BoundedQueue, the capacity remains constant.

Note

When using an UnboundedQueue, the function returns the capacity as determined by the producer, reflecting the dynamic growth of the queue. For a BoundedQueue, the returned capacity is fixed.

Note

Since the Logger object can maintain multiple thread-local queues, this function always returns the capacity of the queue associated with the thread that calls it. Ensure that the correct thread is invoking this function to check its own queue.

Returns:

The current capacity of the thread-local SPSC queue.

template<typename TSink, typename ...Args>
static inline std::shared_ptr<Sink> create_sink(std::string const &sink_name, Args&&... args)

Creates a new sink with the specified name.

Parameters:
std::string const &sink_name

The name of the sink.

Args&&... args

The arguments to pass to the sink constructor.

Throws:

QuillError – if a sink with the same name already exists.

Returns:

std::shared_ptr<Sink> A shared pointer to the created sink.

template<typename TSink, typename ...Args>
static inline std::shared_ptr<Sink> create_or_get_sink(std::string const &sink_name, Args&&... args)

Creates a new sink or retrieves an existing one with the specified name.

Note

If a sink with the specified name already exists, the existing sink is returned and the provided constructor arguments are ignored.

Parameters:
std::string const &sink_name

The name of the sink.

Args&&... args

The arguments to pass to the sink constructor.

Returns:

std::shared_ptr<Sink> A shared pointer to the created or retrieved sink.

static inline std::shared_ptr<Sink> get_sink(std::string const &sink_name)

Retrieves an existing sink with the specified name.

Parameters:
std::string const &sink_name

The name of the sink.

Throws:

QuillError – if the sink does not exist.

Returns:

std::shared_ptr<Sink> A shared pointer to the retrieved sink.

static inline MetricMetadata const *create_metric(std::string const &metric_key, std::string const &metric_name, std::vector<MetricLabel> const &labels = {})

Registers a new runtime metric and returns owned metadata for it.

The MetricManager owns the returned MetricMetadata for the process lifetime, so the returned pointer is stable and can be passed directly to QUILL_METRIC / logger->publish_metric(). metric_key is Quill’s unique registration and lookup key for the metric metadata. metric_name must be non-empty but does not need to be unique, so multiple metric keys may reuse the same name when that fits the sink’s export model.

Throws:

QuillError – if metric_key has already been registered.

static inline MetricMetadata const *create_or_get_metric(std::string const &metric_key, std::string const &metric_name, std::vector<MetricLabel> const &labels = {})

Registers a runtime metric or returns the existing MetricMetadata pointer.

metric_key is the unique identifier. metric_name must be non-empty but is not required to be unique.

If a metric with the same metric_key already exists, the existing pointer is returned unchanged and metric_name and labels are ignored. Use create_metric() if you need strict registration by unique key.

static inline MetricMetadata const *get_metric(std::string const &metric_key)

Looks up an existing metric.

Parameters:
std::string const &metric_key

metric key used during creation

Throws:

QuillError – if no metric with the given key has been registered.

Returns:

the stored metric

static inline logger_t *create_logger(std::string const &logger_name, std::shared_ptr<Sink> sink, PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}, ClockSourceType clock_source = ClockSourceType::Tsc, UserClockSource *user_clock = nullptr)

Creates a new logger with the specified name.

Parameters:
std::string const &logger_name

The name of the logger.

std::shared_ptr<Sink> sink

A shared pointer to the sink to associate with the logger.

PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}

Contains the formatting configuration for PatternFormatter

ClockSourceType clock_source = ClockSourceType::Tsc

The clock source for log timestamps.

UserClockSource *user_clock = nullptr

A pointer to a custom user clock.

Throws:

QuillError – if a logger with the same name already exists or is pending removal.

Returns:

Logger* A pointer to the created logger.

static inline logger_t *create_logger(std::string const &logger_name, std::vector<std::shared_ptr<Sink>> sinks, PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}, ClockSourceType clock_source = ClockSourceType::Tsc, UserClockSource *user_clock = nullptr)

Creates a new logger with the specified name and multiple sinks.

Parameters:
std::string const &logger_name

The name of the logger.

std::vector<std::shared_ptr<Sink>> sinks

A vector of shared pointers to sinks to associate with the logger.

PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}

Contains the formatting configuration for PatternFormatter

ClockSourceType clock_source = ClockSourceType::Tsc

The clock source for log timestamps.

UserClockSource *user_clock = nullptr

A pointer to a custom user clock.

Throws:

QuillError – if a logger with the same name already exists or is pending removal.

Returns:

Logger* A pointer to the created logger.

static inline logger_t *create_logger(std::string const &logger_name, std::initializer_list<std::shared_ptr<Sink>> sinks, PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}, ClockSourceType clock_source = ClockSourceType::Tsc, UserClockSource *user_clock = nullptr)

Creates a new logger with the specified name and multiple sinks.

Parameters:
std::string const &logger_name

The name of the logger.

std::initializer_list<std::shared_ptr<Sink>> sinks

An initializer list of shared pointers to sinks to associate with the logger.

PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}

Contains the formatting configuration for PatternFormatter

ClockSourceType clock_source = ClockSourceType::Tsc

The clock source for log timestamps.

UserClockSource *user_clock = nullptr

A pointer to a custom user clock.

Throws:

QuillError – if a logger with the same name already exists or is pending removal.

Returns:

Logger* A pointer to the created logger.

static inline logger_t *create_or_get_logger(std::string const &logger_name, std::shared_ptr<Sink> sink, PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}, ClockSourceType clock_source = ClockSourceType::Tsc, UserClockSource *user_clock = nullptr)

Creates a new logger or retrieves an existing one with the specified name.

Note

If a logger with the specified name already exists, the existing logger is returned and the provided sinks, pattern, clock source, and user clock parameters are ignored.

Note

Recreating a logger with the same name while a previous logger is still pending asynchronous removal will throw QuillError. Use remove_logger_blocking() when you need synchronous removal before recreating a logger.

Parameters:
std::string const &logger_name

The name of the logger.

std::shared_ptr<Sink> sink

A shared pointer to the sink to associate with the logger.

PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}

Contains the formatting configuration for PatternFormatter

ClockSourceType clock_source = ClockSourceType::Tsc

The clock source for log timestamps.

UserClockSource *user_clock = nullptr

A pointer to a custom user clock.

Returns:

Logger* A pointer to the created or retrieved logger.

static inline logger_t *create_or_get_logger(std::string const &logger_name, std::vector<std::shared_ptr<Sink>> sinks, PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}, ClockSourceType clock_source = ClockSourceType::Tsc, UserClockSource *user_clock = nullptr)

Creates a new logger or retrieves an existing one with the specified name and multiple sinks.

Note

If a logger with the specified name already exists, the existing logger is returned and the provided sinks, pattern, clock source, and user clock parameters are ignored.

Note

Recreating a logger with the same name while a previous logger is still pending asynchronous removal will throw QuillError. Use remove_logger_blocking() when you need synchronous removal before recreating a logger.

Parameters:
std::string const &logger_name

The name of the logger.

std::vector<std::shared_ptr<Sink>> sinks

A vector of shared pointers to sinks to associate with the logger.

PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}

Contains the formatting configuration for PatternFormatter

ClockSourceType clock_source = ClockSourceType::Tsc

The clock source for log timestamps.

UserClockSource *user_clock = nullptr

A pointer to a custom user clock.

Returns:

Logger* A pointer to the created or retrieved logger.

static inline logger_t *create_or_get_logger(std::string const &logger_name, std::initializer_list<std::shared_ptr<Sink>> sinks, PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}, ClockSourceType clock_source = ClockSourceType::Tsc, UserClockSource *user_clock = nullptr)

Creates a new logger or retrieves an existing one with the specified name and multiple sinks.

Note

If a logger with the specified name already exists, the existing logger is returned and the provided sinks, pattern, clock source, and user clock parameters are ignored.

Note

Recreating a logger with the same name while a previous logger is still pending asynchronous removal will throw QuillError. Use remove_logger_blocking() when you need synchronous removal before recreating a logger.

Parameters:
std::string const &logger_name

The name of the logger.

std::initializer_list<std::shared_ptr<Sink>> sinks

An initializer list of shared pointers to sinks to associate with the logger.

PatternFormatterOptions const &pattern_formatter_options = PatternFormatterOptions{}

Contains the formatting configuration for PatternFormatter

ClockSourceType clock_source = ClockSourceType::Tsc

The clock source for log timestamps.

UserClockSource *user_clock = nullptr

A pointer to a custom user clock.

Returns:

Logger* A pointer to the created or retrieved logger.

static inline logger_t *create_or_get_logger(std::string const &logger_name, detail::LoggerBase *source_logger = nullptr)

Creates a new logger or retrieves an existing one that shares the same options as the specified logger.

This function allows you to create or obtain a logger identified by logger_name. If a logger with the same name already exists, its configuration options will be used. If it does not exist, a new logger will be created with the same options as the provided source_logger.

Note

Recreating a logger with the same name while a previous logger is still pending asynchronous removal will throw QuillError. Use remove_logger_blocking() when you need synchronous removal before recreating a logger.

Parameters:
std::string const &logger_name

The name of the logger to create or retrieve.

detail::LoggerBase *source_logger = nullptr

The logger from which to copy the configuration options.

Returns:

A pointer to the logger instance, either newly created or retrieved.

static inline void remove_logger(detail::LoggerBase *logger)

Asynchronously removes the specified logger.

When a logger is removed, if its underlying sinks are not shared by any other logger, they are destructed, and any associated files are also closed.

A common use case for this function is when you want to close the underlying files that the logger is using.

Since the exact removal timing is unknown, you should not attempt to create a new logger with the same name as the one being removed.

Note

This function is thread-safe. However, removing the same logger (logger_t*) from multiple threads is not allowed. You must ensure that remove_logger is only called by a single thread for a given logger.

Warning

After calling this function, no thread should use this logger.

Parameters:
detail::LoggerBase *logger

A pointer to the logger to remove.

static inline void remove_logger_blocking(logger_t *logger, uint32_t sleep_duration_ns = 100)

Asynchronously removes the specified logger and blocks until removal is complete.

When a logger is removed, any files associated with its sinks are also closed.

A use case for this function is when you want to change the sinks of a logger. You can call this function to remove the logger and then recreate it with new sinks and the same name. However, no other threads should be using the logger after the call to this function.

Note

This function is thread-safe. However, removing the same logger (logger_t*) from multiple threads is not allowed. You must ensure that remove_logger_blocking is only called by a single thread for a given logger.

Note

This function should only be called when the backend worker is running after Backend::start(…).

Note

This function must not be called from backend-thread callbacks because it waits for the backend worker.

Warning

After calling this function, no thread should use this logger.

Parameters:
logger_t *logger

A pointer to the logger to remove.

uint32_t sleep_duration_ns = 100

The duration in nanoseconds to sleep between retries

static inline logger_t *get_logger(std::string const &logger_name)

Retrieves an existing logger with the specified name.

Note

Returns nullptr on miss on purpose so callers can check for a removed logger without catching an exception (e.g., after the async remove_logger() path). get_sink() and get_metric() are stricter and throw — they have no comparable use case for an expected miss.

Parameters:
std::string const &logger_name

The name of the logger.

Returns:

Logger* A pointer to the retrieved logger, or nullptr if not found.

static inline std::vector<logger_t*> get_all_loggers()

Retrieves a map of all registered valid loggers.

Note

If remove_logger() is called from this or another thread, the return value of this function will become invalid.

Returns:

A vector containing all registered loggers.

static inline logger_t *get_valid_logger() noexcept

Returns the first valid logger that is found. This is useful when you do not want to use the std::vector<logger_t*> return value of get_all_loggers.

Returns:

A pointer to the first valid logger, or nullptr if no valid logger is found.

static inline size_t get_number_of_loggers() noexcept

Counts the number of existing loggers, including any invalidated loggers. This function can be useful for verifying if a logger has been removed after calling remove_logger() by the backend, as removal occurs asynchronously.

Returns:

The number of loggers.

Frontend Alias

using Frontend = FrontendImpl<FrontendOptions>

MetricLabel Struct

struct MetricLabel

MetricMetadata Class

class MetricMetadata : public MacroMetadata

MetricMetadata extends MacroMetadata so the existing header-encoding path can carry it in the macro_metadata slot on the SPSC queue. It is marked final because MacroMetadata has no virtual destructor: any future owner of unique_ptr<MacroMetadata> pointing at a MetricMetadata would slice or leak. MetricManager stores unique_ptr<MetricMetadata> directly, so there is no slicing today.

Log Levels

enum class LogLevel : uint8_t

Log level enum.

The TraceL* levels form a trace-only verbosity band:

  • TraceL3 is the most detailed trace level

  • TraceL2 is the middle trace level

  • TraceL1 is the least detailed trace level

Values:

enumerator TraceL3
enumerator TraceL2
enumerator TraceL1
enumerator Debug
enumerator Info
enumerator Notice
enumerator Warning
enumerator Error
enumerator Critical
enumerator Backtrace

This is only used for backtrace logging. Should not be set by the user.

enumerator None

LoggerImpl Class

template<typename TFrontendOptions>
class LoggerImpl : public detail::LoggerBase

Thread safe logger.

Logger must be obtained from create_or_get_logger(), therefore, constructors are private

Public Functions

template<bool enable_immediate_flush, typename ...Args>
inline bool log_statement(MacroMetadata const *macro_metadata, Args&&... fmt_args)

Push a log message to the spsc queue to be logged by the backend thread. One spsc queue per caller thread. This function is enabled only when all arguments are fundamental types. This is the fastest way possible to log

Note

This function is thread-safe.

Parameters:
MacroMetadata const *macro_metadata

metadata of the log message

Args&&... fmt_args

arguments

Returns:

true if the message is written to the queue, false if it is dropped (when a dropping queue is used)

inline bool publish_metric(MetricMetadata const *metric_metadata, double value)

Push a compact metric sample to the spsc queue to be processed by the backend thread. The queue stores only the value. Static metric identity and labels are carried by MetricMetadata via the existing MacroMetadata pointer in the event header.

Metrics never participate in logger immediate-flush behavior; sinks decide their own flush or batching strategy on the backend thread.

Note

This function is thread-safe.

Parameters:
MetricMetadata const *metric_metadata

metadata of the metric event

double value

metric value

Returns:

true if the metric sample is written to the queue, false if it is dropped

template<typename ...Args>
inline void set_mdc(Args&&... args)

Sets or replaces one or more MDC fields for the calling thread.

The supplied fields are propagated asynchronously to the backend thread and then appended to subsequent log messages from the same frontend thread until erased or cleared.

This operation is not on the hot path. If a dropping queue is configured and is temporarily full, this function retries until the control event is queued.

template<typename ...Keys>
inline void erase_mdc(Keys&&... keys)

Erases one or more MDC fields for the calling thread.

Missing keys are ignored. The operation retries until queued when a dropping queue is temporarily full.

inline void clear_mdc()

Clears all MDC fields for the calling thread.

The operation retries until queued when a dropping queue is temporarily full.

template<bool enable_immediate_flush, typename ...Args>
inline bool log_statement_runtime_metadata(MacroMetadata const *macro_metadata, char const *fmt, char const *file_path, char const *function_name, char const *tags, uint32_t line_number, LogLevel log_level, Args&&... fmt_args)

Push a log message with runtime metadata to the spsc queue to be logged by the backend thread.

Similar to log_statement but allows passing metadata that is only available at runtime.

Note

This function is thread-safe.

Parameters:
MacroMetadata const *macro_metadata

Metadata of the log message

char const *fmt

Format string for the log message

char const *file_path

Source file path where the log statement was called

char const *function_name

Function name where the log statement was called

char const *tags

Optional tags associated with the log message

uint32_t line_number

Line number in the source file

LogLevel log_level

Severity level of the log message

Args&&... fmt_args

Format arguments for the log message

Returns:

true if the message is written to the queue, false if it is dropped (when a dropping queue is used)

inline void init_backtrace(uint32_t max_capacity, LogLevel flush_level = LogLevel::None)

Init a backtrace for this logger. Stores messages logged with LOG_BACKTRACE in a ring buffer and displays them later on demand.

Parameters:
uint32_t max_capacity

The max number of messages to store in the backtrace

LogLevel flush_level = LogLevel::None

If this logger logs any message higher or equal to this severity level, the backtrace will also get flushed. Default level is None meaning the user has to call flush_backtrace explicitly

inline void flush_backtrace()

Dump any stored backtrace messages

inline void flush_log(uint32_t sleep_duration_ns = 100)

Blocks the calling thread until all log messages up to the current timestamp are flushed.

The backend thread will invoke the write operation on all sinks for all loggers up to the point (timestamp) when this function is invoked.

Note

This function should only be called when the backend worker is running after Backend::start(…)

Note

This function will block the calling thread until the flush message is processed by the backend thread. The calling thread can block for up to backend_options.sleep_duration. If you configure a custom long sleep duration on the backend thread, e.g., backend_options.sleep_duration = std::chrono::minutes{1}, then you should ideally avoid calling this function as you can block for long period of times unless you use another thread that calls Backend::notify()

Warning

Do not call this function from the destructor of a static object. This may lead to application crashes if the thread-local ThreadContext is destroyed before the static object invoking flush_log.

Parameters:
uint32_t sleep_duration_ns = 100

The duration in nanoseconds to sleep between retries when the blocking queue is full, and between checks for the flush completion. Default is 100 nanoseconds.

Logger Alias

using Logger = LoggerImpl<FrontendOptions>

PatternFormatter Class

class PatternFormatter

Public Types

enum class TimestampPrecision : uint8_t

Public classes Stores the precision of the timestamp

Values:

enumerator None
enumerator MilliSeconds
enumerator MicroSeconds
enumerator NanoSeconds

Public Functions

inline explicit PatternFormatter(PatternFormatterOptions options)

Main PatternFormatter class Constructor for a PatternFormatter with custom formatting options.

See also

PatternFormatterOptions for detailed information on available options.

Parameters:
PatternFormatterOptions options

The PatternFormatterOptions object containing the formatting configuration.

Throws:

std::invalid_argument – if the format string in options is invalid

PatternFormatterOptions Class

class PatternFormatterOptions

Configuration options for the PatternFormatter.

This class encapsulates the configuration options used to customize the formatting of log messages.

Public Members

std::string format_pattern = {default_format_pattern}

The format pattern for log messages.

This string defines the overall structure of each log message.

It can include various placeholders that will be replaced with actual values when formatting the log message.

%(time) - Human-readable timestamp representing when the log statement was created. %(file_name) - Name of the source file where the logging call was issued. %(full_path) - Full path of the source file where the logging call was issued. %(caller_function) - Name of the function containing the logging call. %(log_level) - Textual representation of the logging level for the message. %(log_level_short_code) - Abbreviated log level name. %(line_number) - Line number in the source file where the logging call was issued. %(logger) - Name of the logger used to log the call. %(message) - The logged message itself. %(thread_id) - ID of the thread in which the logging call was made. %(thread_name) - Name of the thread. Must be set before the first log statement on that thread. %(process_id) - ID of the process in which the logging call was made. %(source_location) - Full source file path and line number as a single string. %(short_source_location) - Shortened source file name and line number as a single string. %(tags) - Additional custom tags appended to the message when _TAGS macros are used. %(mdc) - The backend-formatted MDC block for the calling thread. Empty when no MDC is set. %(named_args) - Key-value pairs appended to the message. Only applicable when the message has named args; remains empty otherwise.

Warning

The same attribute cannot be used twice in the same format pattern.

std::string timestamp_pattern = {"%H:%M:%S.%Qns"}

The format pattern for timestamps.

This string defines how timestamps are formatted in log messages. It follows the strftime() format with additional specifiers:

  • Qms : Milliseconds

  • Qus : Microseconds

  • Qns : Nanoseconds

std::string source_location_path_strip_prefix = {}

Sets a path prefix to be stripped from source location paths.

When set, the last occurrence of this prefix in the source location path is removed:

  • For example, with prefix “/home/user/”, a path like “/home/user/project/test.cpp:5” would be displayed as “project/test.cpp:5”

  • The same also works with a shorter marker such as “project”, which would also produce “test.cpp:5” or “subdir/test.cpp:5” depending on the remaining suffix

  • If empty (default), the full path is shown

This affects only the %(source_location) attribute.

std::string_view (*process_function_name)(char const*)

Function pointer for custom processing of detailed function names for %(caller_function).

This is most useful when QUILL_DETAILED_FUNCTION_NAME is enabled, as it allows custom processing of the detailed function signature provided by the compiler.

Since the format of PRETTY_FUNCTION or equivalent is compiler-specific, this function allows users to implement their own parsing/formatting logic.

The function takes one parameter:

  • The raw function signature string from the compiler (e.g., from PRETTY_FUNCTION)

It should return a string_view representing the processed function name.

If set to nullptr (default), the logger will use the unprocessed function name as provided by the compiler.

Timezone timestamp_timezone = {Timezone::LocalTime}

The timezone to use for timestamps.

Determines whether timestamps are formatted in local time or GMT.

bool add_metadata_to_multi_line_logs = {true}

Whether to add metadata to each line of multi-line log messages.

If true, ensures that metadata (e.g., timestamp, log level) is added to every line of multi-line log entries, maintaining consistency across all log outputs.

bool source_location_remove_relative_paths = {false}

Whether to remove relative path components from source location paths.

If true, relative path components like “../” will be processed and removed from source location paths, simplifying the displayed path.

This affects only the %(source_location) attribute.

char pattern_suffix = {'\n'}

Character to append at the end of each formatted log pattern.

This character is appended to the formatted log message pattern.

  • If set to a character (e.g., ‘

    ’), that character will be appended

  • If set to NO_SUFFIX, no character will be appended

Public Static Attributes

static char NO_SUFFIX = static_cast<char>(-1)

Special value to indicate no pattern suffix should be appended Using -1 cast to char ensures this value is unlikely to conflict with legitimate suffix characters.

Sink Class

class Sink

Base class for sinks

Subclassed by NullSink, PrometheusSink, StreamSink

Public Functions

inline explicit Sink(std::optional<PatternFormatterOptions> override_pattern_formatter_options = std::nullopt)

Constructor Uses the default pattern formatter

virtual ~Sink() = default

Destructor

inline void set_log_level_filter(LogLevel log_level)

Sets a log level filter on the sink.

Note

Thread safe.

Parameters:
LogLevel log_level

The log level severity.

inline LogLevel get_log_level_filter() const noexcept

Returns the current log level filter set on the sink.

Note

Thread safe.

Returns:

The current log level filter.

inline void add_filter(std::unique_ptr<Filter> filter)

Adds a new filter to the sink.

Note

Thread safe.

Parameters:
std::unique_ptr<Filter> filter

Unique pointer to the filter instance.

Filter Class

class Filter

Base filter class. Filters can be added to Sinks

Public Functions

inline explicit Filter(std::string filter_name)

Constructor

Parameters:
std::string filter_name

unique filter name

virtual ~Filter() = default

Destructor

virtual bool filter(MacroMetadata const *log_metadata, uint64_t log_timestamp, std::string_view thread_id, std::string_view thread_name, std::string_view logger_name, LogLevel log_level, std::string_view log_message, std::string_view log_statement) noexcept = 0

Filters a log message.

Parameters:
MacroMetadata const *log_metadata

Pointer to the macro metadata.

uint64_t log_timestamp

Timestamp of the log event.

std::string_view thread_id

ID of the thread.

std::string_view thread_name

Name of the thread.

std::string_view logger_name

Name of the logger.

LogLevel log_level

Log level of the message.

std::string_view log_message

The log message.

std::string_view log_statement

The log statement.

Returns:

true if the log message should be written to the file, false otherwise

inline virtual std::string const &get_filter_name() const noexcept

Gets the name of the filter. Only useful if an existing filter is needed to be looked up

Returns:

the name of the filter

FileSinkConfig Class

class FileSinkConfig

The FileSinkConfig class holds the configuration options for the FileSink

Subclassed by RotatingFileSinkConfig

Public Functions

inline void set_filename_append_option(FilenameAppendOption value, std::string_view append_filename_format_pattern = std::string_view{})

Sets the append type for the file name. Possible append types are: StartDate, StartDateTime or None. When this option is set, the file name will be appended with the start date or date and time timestamp of when the process started.

For example: application.log -> application_20230101.log (StartDate) application.log -> application_20230101_121020.log (StartDateTime)

Parameters:
FilenameAppendOption value

The append type to set. Valid options are None, StartDate, StartDateTime, and StartCustomTimestampFormat.

std::string_view append_filename_format_pattern = std::string_view{}

Specifies a custom strftime format pattern to use for the filename. This parameter is only applicable when FilenameAppendOption::StartCustomTimestampFormat is selected

inline void set_timezone(Timezone time_zone)

Sets the timezone to use for time-based operations e.g. when appending the date to the get_filename or when setting the logging pattern. Valid options for the timezone are ‘LocalTime’ or ‘GmtTime’ The default value is ‘LocalTime’.

Parameters:
Timezone time_zone

The timezone to use for time-based operations.

inline void set_fsync_enabled(bool value)

Sets whether fsync should be performed when flushing. The default value is false.

Note

On macOS, fsync() flushes data to the disk controller’s write cache but does not guarantee write-through to persistent storage.

Parameters:
bool value

True to perform fsync, false otherwise.

inline void set_open_mode(char open_mode)

Sets the open mode for the file.

Parameters:
char open_mode

open mode for the file.

inline void set_open_mode(std::string_view open_mode)

Sets the open mode for the file.

Parameters:
std::string_view open_mode

open mode for the file.

inline void set_write_buffer_size(size_t value)

Sets the user-defined buffer size for fwrite operations.

This function allows you to specify a custom buffer size for fwrite, improving efficiency for file write operations.

To disable custom buffering and revert to the default size, pass a value of 0.

Note

By default, a buffer size of 64 KB is used.

Parameters:
size_t value

Size of the buffer in bytes. If set to 0, the default buffer size will be used.

inline void set_minimum_fsync_interval(std::chrono::milliseconds value)

Sets the minimum interval between fsync calls. This specifies the minimum time between consecutive fsync operations but does not guarantee that fsync will be called exactly at that interval.

For example, if some messages are flushed to the log and fsync is skipped because it was previously called, and no further messages are written to the file, fsync will not be called even if the minimum interval has passed. This is because the previous call was skipped due to the interval, and no new messages necessitate another fsync call.

This feature is intended to mitigate concerns about frequent fsync calls potentially causing disk wear.

Note: This option is only applicable when fsync is enabled. By default, the value is 0, which means that fsync will be called periodically by the backend worker thread when messages are written to the file, irrespective of the interval.

Parameters:
std::chrono::milliseconds value

The minimum interval, in milliseconds, between fsync calls.

inline void set_override_pattern_formatter_options(std::optional<PatternFormatterOptions> const &options)

Sets custom pattern formatter options for this sink.

By default, the logger’s pattern formatter is used to format log messages. This function allows overriding the default formatter with custom options for this specific sink. If a custom formatter is provided, it will be used instead of the logger’s formatter.

Parameters:
std::optional<PatternFormatterOptions> const &options

The custom pattern formatter options to use

inline bool fsync_enabled() const noexcept

Getters

FileSink Class

class FileSink : public StreamSink

Keep the Windows-specific FileSink split isolated under _WIN32. A previous attempt to share a FileSinkBase across all platforms introduced a measurable Linux throughput regression in BENCHMARK_quill_backend_throughput despite equivalent logic. If this is revisited, revalidate Linux performance. FileSink Writes the log messages to a file

Subclassed by RotatingSink< FileSink >, detail::JsonSink< FileSink >

Public Functions

inline virtual void flush_sink() override

Flushes the sink, synchronizing the associated sink with its controlled output sequence.

File Event Types

using FileEventNotifierHandle = FILE*
struct FileEventNotifier

Notifies on file events by calling the appropriate callback.

Note

before_write executes as part of the normal log write path. before_open, after_open, before_close, and after_close execute on the thread performing the file open/close operation. Different callbacks, and different invocations of the same callback, may therefore run on different threads over the sink lifetime. Callbacks must be thread-safe and must not assume a single calling thread.

RotatingSink Class

template<typename TBase>
class RotatingSink : public TBase

The RotatingSink class.

Public Functions

inline RotatingSink(fs::path const &filename, RotatingFileSinkConfig const &config, FileEventNotifier file_event_notifier = FileEventNotifier{}, std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now())

Constructor.

Creates a new instance of the RotatingSink class.

Parameters:
fs::path const &filename

The base file name to be used for logs.

RotatingFileSinkConfig const &config

The sink configuration.

FileEventNotifier file_event_notifier = FileEventNotifier{}

file event notifier

std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now()

start time

inline void write_log(MacroMetadata const *log_metadata, uint64_t log_timestamp, std::string_view thread_id, std::string_view thread_name, std::string const &process_id, std::string_view logger_name, LogLevel log_level, std::string_view log_level_description, std::string_view log_level_short_code, std::vector<std::pair<std::string, std::string>> const *named_args, std::string_view log_message, std::string_view log_statement) override

Writes a formatted log message to the stream.

Parameters:
MacroMetadata const *log_metadata

The metadata of the log message

uint64_t log_timestamp

The timestamp of the log message

std::string_view thread_id

The ID of the thread that generated the log message

std::string_view thread_name

The name of the thread that generated the log message

std::string const &process_id

Process Id

std::string_view logger_name

logger name

LogLevel log_level

Log level of the message.

std::string_view log_level_description

Description of the log level.

std::string_view log_level_short_code

Short code representing the log level.

std::vector<std::pair<std::string, std::string>> const *named_args

Structured key-value pairs associated with the log message

std::string_view log_message

The log message to write

std::string_view log_statement

The full log statement

RotatingFileSinkConfig Class

class RotatingFileSinkConfig : public FileSinkConfig

The configuration options for the RotatingSink.

Public Types

enum class RotationFrequency : uint8_t

The frequency of log file rotation.

Values:

enumerator Disabled
enumerator Daily
enumerator Hourly
enumerator Minutely
enum class RotationNamingScheme : uint8_t

The naming scheme for rotated log files.

Values:

enumerator Index
enumerator Date
enumerator DateAndTime

Public Functions

inline RotatingFileSinkConfig()

Constructs a new RotatingFileSinkConfig object.

inline void set_rotation_max_file_size(size_t value)

Sets the maximum file size for rotation.

Parameters:
size_t value

The maximum file size in bytes per file

inline void set_rotation_frequency_and_interval(char frequency, uint32_t interval)

Sets the frequency and interval of file rotation.

Parameters:
char frequency

The frequency of file rotation (‘M’ for minutes, ‘H’ for hours)

uint32_t interval

The rotation interval

inline void set_rotation_time_daily(std::string const &daily_rotation_time_str)

Sets the time of day for daily log file rotation.

Parameters:
std::string const &daily_rotation_time_str

The time of day for rotation (format: “HH:MM”)

inline void set_max_backup_files(uint32_t value)

Sets the maximum number of log files to keep. When the sink starts in append mode, rotated files left behind by previous runs are also counted towards this limit and the oldest ones are removed on startup, unless set_overwrite_rolled_files() is set to false.

Parameters:
uint32_t value

The maximum number of log files

inline void set_overwrite_rolled_files(bool value)

Sets whether the oldest rolled logs should be overwritten when the maximum backup count is reached. If set to false, the oldest logs will not be overwritten when the maximum backup count is reached, and log file rotation will stop. The default value is true.

Parameters:
bool value

True to overwrite the oldest logs, false otherwise.

inline void set_remove_old_files(bool value)

Sets whether previous rotated log files should be removed on process start up.

Note

This option works only when using the mode=”w” This is useful to avoid conflicting file names when the process restarts and FilenameAppendOption::StartDateTime was not set. The default value is true.

Parameters:
bool value

True to remove old log files, false otherwise.

inline void set_rotation_naming_scheme(RotationNamingScheme value)

Sets the naming scheme for the rotated files. The default value is ‘Index’.

Parameters:
RotationNamingScheme value

The naming scheme to set.

inline void set_rotation_on_creation(bool value)

Sets whether to force rotation on file sink creation/startup. When enabled, if a log file with the same name exists on startup, it will be rotated according to the RotationNamingScheme before starting to write new logs. This allows creating a new log file for every program run. The default value is false.

Parameters:
bool value

True to force rotation on creation, false otherwise.

inline size_t rotation_max_file_size() const noexcept

Getter methods

RotatingFileSink Alias

using RotatingFileSink = RotatingSink<FileSink>

JsonFileSink Class

class JsonFileSink : public detail::JsonSink<FileSink>

JSON File Sink

Subclassed by RotatingSink< JsonFileSink >

RotatingJsonFileSink Alias

using RotatingJsonFileSink = RotatingSink<JsonFileSink>

JsonConsoleSink Class

class JsonConsoleSink : public detail::JsonSink<StreamSink>

JSON Console Sink

StreamSink Class

class StreamSink : public Sink

StreamSink class for handling log messages.

Subclassed by detail::JsonSink< StreamSink >, ConsoleSink, FileSink

Public Functions

inline explicit StreamSink(fs::path stream, FILE *file = nullptr, std::optional<PatternFormatterOptions> const &override_pattern_formatter_options = std::nullopt, FileEventNotifier file_event_notifier = FileEventNotifier{})

Constructor for StreamSink.

Parameters:
fs::path stream

The stream type (stdout, stderr, or file)

std::optional<PatternFormatterOptions> const &override_pattern_formatter_options = std::nullopt

override the logger pattern formatter

FILE *file = nullptr

File pointer for file-based stream

FileEventNotifier file_event_notifier = FileEventNotifier{}

Notifies on file events

Throws:

QuillError – if an invalid parameter is provided

inline virtual void write_log(MacroMetadata const*, uint64_t, std::string_view, std::string_view, std::string const&, std::string_view, LogLevel, std::string_view, std::string_view, std::vector<std::pair<std::string, std::string>> const*, std::string_view, std::string_view log_statement) override

Writes a formatted log message to the stream.

inline virtual void flush_sink() override

Flushes the stream

inline virtual fs::path const &get_filename() const noexcept

Returns the name of the file.

Returns:

The name of the file

inline bool is_null() const noexcept

Checks if the stream is null.

Returns:

True if the stream is null, false otherwise

Public Static Functions

static inline void safe_fwrite(void const *ptr, size_t size, size_t count, FILE *stream)

Writes data safely to the stream.

Parameters:
void const *ptr

Pointer to the data to be written

size_t size

Size of each element to be written

size_t count

Number of elements to write

FILE *stream

The stream to write to

ConsoleSinkConfig Class

class ConsoleSinkConfig

Public Functions

inline void set_colours(Colours colours)

Sets custom colours for each log level.

This function allows specifying a custom Colours instance, enabling fine-grained control over the colours used for different log levels in the console output.

Parameters:
Colours colours

The Colours instance to use.

inline void set_colour_mode(ColourMode colour_mode)

Sets the colour mode for console output.

This function determines when colours are applied in the console output. Valid options for the colour mode are:

  • Always: Colours are always enabled.

  • Automatic: Colours are enabled automatically based on the environment (e.g., terminal support).

  • Never: Colours are never enabled.

The default value is ‘Automatic’.

Parameters:
ColourMode colour_mode

The desired colour mode.

inline void set_stream(std::string const &stream)

Sets the output stream for console logging.

This function allows selecting the output stream where log messages should be printed. The valid options are:

  • ”stdout”: Logs are printed to the standard output.

  • ”stderr”: Logs are printed to the standard error.

The default value is “stdout”.

Parameters:
std::string const &stream

The output stream to use.

inline void set_override_pattern_formatter_options(std::optional<PatternFormatterOptions> const &options)

Sets custom pattern formatter options for this sink.

By default, the logger’s pattern formatter is used to format log messages. This function allows overriding the default formatter with custom options for this specific sink. If a custom formatter is provided, it will be used instead of the logger’s formatter.

Parameters:
std::optional<PatternFormatterOptions> const &options

The custom pattern formatter options to use

inline Colours const &colours() const noexcept

Getters

class Colours

Represents console colours

Public Functions

inline void apply_default_colours() noexcept

Sets some default colours for terminal

inline void assign_colour_to_log_level(LogLevel log_level, std::string_view colour) noexcept

Sets a custom colour per log level

Parameters:
LogLevel log_level

the log level

std::string_view colour

the colour

inline bool colours_enabled() const noexcept
Returns:

true if we are in terminal and have also enabled colours

inline std::string_view log_level_colour(LogLevel log_level) const noexcept

The colour for the given log level

Parameters:
LogLevel log_level

the message log level

Returns:

the configured colour for this log level

Public Static Attributes

static std::string_view on_black = {"\033[40m"}

Background colors.

static std::string_view white_bold = {"\033[97m\033[1m"}

Bold colors.

ConsoleSink Class

class ConsoleSink : public StreamSink

Public Functions

inline explicit ConsoleSink(ConsoleSinkConfig const &config = ConsoleSinkConfig{}, FileEventNotifier file_event_notifier = FileEventNotifier{})

Constructor with custom ConsoleColours config.

inline virtual void write_log(MacroMetadata const *log_metadata, uint64_t log_timestamp, std::string_view thread_id, std::string_view thread_name, std::string const &process_id, std::string_view logger_name, LogLevel log_level, std::string_view log_level_description, std::string_view log_level_short_code, std::vector<std::pair<std::string, std::string>> const *named_args, std::string_view log_message, std::string_view log_statement) override

Write a formatted log message to the stream.

Parameters:
MacroMetadata const *log_metadata

log metadata

uint64_t log_timestamp

log timestamp

std::string_view thread_id

thread id

std::string_view thread_name

thread name

std::string const &process_id

Process Id

std::string_view logger_name

logger name

LogLevel log_level

Log level of the message.

std::string_view log_level_description

Description of the log level.

std::string_view log_level_short_code

Short code representing the log level.

std::vector<std::pair<std::string, std::string>> const *named_args

vector of key-value pairs of named args

std::string_view log_message

log message

std::string_view log_statement

log statement

AndroidSinkConfig Class

class AndroidSinkConfig

Holds the configuration options for the AndroidSink.

This configuration class allows you to set various parameters that determine how log messages are mapped and sent to the Android log system.

Public Functions

inline void set_tag(std::string const &tag)

Sets the tag that is prepended to every Android log message. Typically, this is set to the program name.

Parameters:
std::string const &tag

The tag string.

inline void set_format_message(bool format_message)

Enables or disables message formatting. If enabled, the log message will be formatted using the specified PatternFormatter before being sent to the Android log system.

Parameters:
bool format_message

Set to true to format the message; false otherwise.

inline void set_log_level_mapping(std::array<int, LogLevelCount> mapping)

Sets the mapping from quill log levels to Android log levels. This mapping determines which Android log level is used for each quill log level.

Parameters:
std::array<int, LogLevelCount> mapping

An array of LogLevelCount integers representing Android log levels, one per LogLevel value.

inline std::string const &tag() const noexcept

Getters

AndroidSink Class

class AndroidSink : public quill::Sink

A sink that writes log messages to the Android logging system (logcat).

This sink leverages the Android log API to send log messages. It uses the configuration provided via AndroidSinkConfig to determine how the messages are formatted and mapped.

Public Functions

inline explicit AndroidSink(AndroidSinkConfig config = AndroidSinkConfig{})

Constructs an AndroidSink with the given configuration.

Parameters:
AndroidSinkConfig config = AndroidSinkConfig{}

The configuration options for the AndroidSink. Defaults to a default-configured AndroidSinkConfig.

inline void write_log(MacroMetadata const*, uint64_t, std::string_view, std::string_view, std::string const&, std::string_view, LogLevel log_level, std::string_view, std::string_view, std::vector<std::pair<std::string, std::string>> const*, std::string_view log_message, std::string_view log_statement) override

Writes a formatted log message to the Android logging system.

NullSink Class

class NullSink : public Sink

Public Functions

inline virtual void write_log(MacroMetadata const*, uint64_t, std::string_view, std::string_view, std::string const&, std::string_view, LogLevel, std::string_view, std::string_view, std::vector<std::pair<std::string, std::string>> const*, std::string_view, std::string_view) override

Discards the provided log record.

inline virtual void flush_sink() override

Flushes the sink, synchronizing the associated sink with its controlled output sequence.

SyslogSink Class

class SyslogSink : public quill::Sink

A sink that writes log messages to the system logger (syslog).

This sink leverages the syslog API to send log messages. It uses the configuration provided via SyslogSinkConfig to determine how the messages are formatted and mapped.

Note

Syslog uses process-global state. Multiple SyslogSink instances are therefore not independent if they use different identifiers, options, or facilities. Use a single SyslogSink configuration per process.

Public Functions

inline explicit SyslogSink(SyslogSinkConfig config = SyslogSinkConfig{})

Constructs a SyslogSink with the given configuration. This constructor initializes the syslog connection using openlog().

Parameters:
SyslogSinkConfig config = SyslogSinkConfig{}

The configuration options for the SyslogSink. Defaults to a default-configured SyslogSinkConfig.

inline void write_log(MacroMetadata const*, uint64_t, std::string_view, std::string_view, std::string const&, std::string_view, LogLevel log_level, std::string_view, std::string_view, std::vector<std::pair<std::string, std::string>> const*, std::string_view log_message, std::string_view log_statement) override

Writes a formatted log message to the stream.

SyslogSinkConfig Class

class SyslogSinkConfig

Holds the configuration options for the SyslogSink.

When including syslog.h via SyslogSink, the header defines macros such as LOG_INFO and others that conflict with Quill’s LOG_ macros.

To resolve this issue, consider one of the following solutions:

  1. Include SyslogSink in a .cpp file only: Instantiate the SyslogSink in a source file rather than a header file. This ensures that syslog.h is only included in that specific translation unit, avoiding collisions in other files where you want to use the unprefixed Quill LOG_ macros.

  2. Define the preprocessor flag : When this flag is defined, Quill will disable its unprefixed LOG_ macros. Instead, you must use the longer QUILL_LOG_ macros. This approach allows Quill and syslog.h to coexist in the same translation unit.

Alternatively, you can combine both approaches if you include SyslogSink in a .cpp file where you also intend to use the LOG_ macros.

However, the first solution is generally preferable, as it lets you take advantage of the more concise LOG_ macros without additional typing.

This configuration class allows you to set various parameters that determine how log messages are mapped and sent to the syslog.

Note

IMPORTANT: Handling Macro Collisions between syslog.h and Quill

Public Functions

inline void set_identifier(std::string const &identifier)

Sets the identifier that is prepended to every syslog message. Typically, this is set to the program name.

Parameters:
std::string const &identifier

The identifier string.

inline void set_options(int options)

Sets the options to be passed to openlog(). These options control various aspects of syslog behavior.

Parameters:
int options

Integer representing syslog options.

inline void set_facility(int facility)

Sets the facility code for syslog. The facility code indicates the type of program logging the message.

Parameters:
int facility

Integer representing the syslog facility.

inline void set_format_message(bool format_message)

Enables or disables message formatting. If enabled, the log message will be formatted using the specified PatternFormatter before being sent to syslog.

Parameters:
bool format_message

Set to true to format the message; false otherwise.

inline void set_log_level_mapping(std::array<int, LogLevelCount> mapping)

Sets the mapping from quill log levels to syslog levels. This mapping determines which syslog level is used for each quill log level.

Parameters:
std::array<int, LogLevelCount> mapping

An array of LogLevelCount integers representing syslog levels, one per LogLevel value.

inline std::string const &identifier() const noexcept

Getters

SystemdSink Class

class SystemdSink : public quill::Sink

A sink that writes log messages to the system logger (systemd).

This sink leverages the systemd API to send log messages. It uses the configuration provided via SystemdSinkConfig to determine how the messages are formatted and mapped.

Public Functions

inline explicit SystemdSink(SystemdSinkConfig config = SystemdSinkConfig{})

Constructs a SystemdSink with the given configuration. This constructor stores the configuration used when sending log messages to systemd.

Parameters:
SystemdSinkConfig config = SystemdSinkConfig{}

The configuration options for the SystemdSink. Defaults to a default-configured SystemdSinkConfig.

inline void write_log(MacroMetadata const *log_metadata, uint64_t, std::string_view thread_id, std::string_view, std::string const&, std::string_view logger_name, LogLevel log_level, std::string_view, std::string_view, std::vector<std::pair<std::string, std::string>> const*, std::string_view log_message, std::string_view log_statement) override

Writes a formatted log message to the stream.

SystemdSinkConfig Class

class SystemdSinkConfig

Holds the configuration options for the SystemdSink.

When including systemd.h via SystemdSink, the header defines macros such as LOG_INFO and others that conflict with Quill’s LOG_ macros.

To resolve this issue, consider one of the following solutions:

  1. Include SystemdSink in a .cpp file only: Instantiate the SystemdSink in a source file rather than a header file. This ensures that systemd.h is only included in that specific translation unit, avoiding collisions in other files where you want to use the unprefixed Quill LOG_ macros.

  2. Define the preprocessor flag : When this flag is defined, Quill will disable its unprefixed LOG_ macros. Instead, you must use the longer QUILL_LOG_ macros. This approach allows Quill and systemd.h to coexist in the same translation unit.

Alternatively, you can combine both approaches if you include SystemdSink in a .cpp file where you also intend to use the LOG_ macros.

However, the first solution is generally preferable, as it lets you take advantage of the more concise LOG_ macros without additional typing.

This configuration class allows you to set various parameters that determine how log messages are mapped and sent to the systemd.

Note

IMPORTANT: Handling Macro Collisions between systemd.h and Quill

Public Functions

inline void set_identifier(std::string const &identifier)

Sets the identifier that is prepended to every systemd message. Typically, this is set to the program name.

Parameters:
std::string const &identifier

The identifier string.

inline void set_format_message(bool format_message)

Enables or disables message formatting. If enabled, the log message will be formatted using the specified PatternFormatter before being sent to systemd.

Parameters:
bool format_message

Set to true to format the message; false otherwise.

inline void set_log_level_mapping(std::array<int, LogLevelCount> mapping)

Sets the mapping from quill log levels to systemd levels. This mapping determines which systemd level is used for each quill log level.

Parameters:
std::array<int, LogLevelCount> mapping

An array of LogLevelCount integers representing systemd levels, one per LogLevel value.

inline std::string const &identifier() const noexcept

Getters

PrometheusSink Class

Optional sink for exporting Quill metric samples through prometheus-cpp.

class PrometheusSink : public Sink

Optional sink that forwards Quill metric samples to a prometheus-cpp registry.

Only translation units including this header require prometheus-cpp headers and linking against prometheus-cpp::core and prometheus-cpp::pull. Quill itself does not depend on prometheus-cpp.

PrometheusSink::ExposerConfiguration Struct

struct ExposerConfiguration

PrometheusSink::Options Struct

struct Options

PrometheusSink::SummaryQuantile Struct

struct SummaryQuantile

A single quantile target for a summary metric.

quantile is the target rank in [0, 1] (e.g. 0.5 for the median, 0.99 for p99). error is the allowed absolute error around that rank used by the CKMS streaming algorithm: smaller error produces more accurate quantiles but uses more memory and CPU.

Common defaults: {0.5, 0.05}, {0.9, 0.01}, {0.99, 0.001} — these mirror what prometheus-cpp and the official Prometheus client libraries suggest, and match the typical cost/accuracy trade-off (looser error at the median, tighter at the tails).

PrometheusSink::GaugeUpdateMode Enum

enum class PrometheusSink::GaugeUpdateMode

Controls how a gauge applies the sample value it receives.

  • Set: replace the gauge with the sample value (the value is the current reading).

  • Add: increment the gauge by the sample value (the value is a delta; pass a negative sample to subtract).

  • Sub: decrement the gauge by the sample value (the value is a positive magnitude to remove; equivalent to Add with a negated sample).

Values:

enumerator Add
enumerator Set
enumerator Sub

ManualBackendWorker Class

class ManualBackendWorker

This class can be used when you want to run the backend worker on your own thread.

Threading contract:

  • The thread running ManualBackendWorker may log.

  • That same thread must not use any path that waits for the backend to flush its own queue. In particular, it must not call logger->flush_log() or Frontend::remove_logger_blocking(). If a logger has immediate flush enabled, the implicit flush is skipped for log calls from this thread.

  • The thread that calls init() must also call shutdown() explicitly before it exits. Do not rely on the destructor to perform shutdown for you.

Public Functions

inline void init(BackendOptions options)

Initializes the ManualBackendWorker with the specified backend options.

This function must be called before any other functions in this class. It configures the backend worker for manual operation, disabling certain options that are incompatible with manual control.

Parameters:
BackendOptions options

The BackendOptions to configure the backend worker.

inline void shutdown()

Flushes remaining frontend queues and marks the manual backend worker as stopped.

This function must be called from the same thread that called init() and performs the same shutdown work that the automatic backend thread executes during stop(). Call this explicitly before the manual backend thread exits. Do not rely on the destructor to do this for you.

inline void poll_one()

Polls all thread-local SPSC queues and caches the log statements, processing and writing the log statement with the minimum timestamp to the corresponding output sinks.

This function should be called periodically by the thread to process and dispatch log entries. It assumes that the init() function has been called first to properly configure the backend worker.

inline void poll()

Continuously polls the backend worker until all queues are empty.

This function keeps polling until all frontend queues and cached transit events are processed.

inline void poll(std::chrono::microseconds timeout)

This function behaves like poll() but will stop polling if the specified timeout duration is reached before all queues are emptied. This can be useful when you want to limit the time spent processing log statements.

CsvWriter Class

template<typename TCsvSchema, typename TFrontendOptions>
class CsvWriter

A CSV writer class for asynchronous logging of CSV files.

This class facilitates the asynchronous logging of CSV files, where formatting and I/O operations are handled by the backend worker thread.

Call close() before Backend::stop() when deterministic logger removal and file closure are required. The destructor performs best-effort asynchronous cleanup and does not block.

The TCsvSchema struct should define the CSV header and format, for example:

struct OrderCsvSchema
{
  static constexpr char const* header = "order_id,symbol,quantity,price,side";
  static constexpr char const* format = "{},{},{},{:.2f},{}";
};
Template Parameters:
typename TCsvSchema

A user-defined struct specifying the CSV schema at compile-time.

typename TFrontendOptions

Custom frontend options if they are used application-wide. If no custom frontend options are used, then use quill::FrontendOptions.

Public Functions

inline explicit CsvWriter(std::string const &filename, char open_mode = 'w', FilenameAppendOption filename_append = FilenameAppendOption::None)

Constructs a CsvWriter object that writes to a file.

Parameters:
std::string const &filename

The name of the CSV file to write to.

char open_mode = 'w'

The mode in which to open the file (‘w’ for write, ‘a’ for append).

FilenameAppendOption filename_append = FilenameAppendOption::None

Option to append to the filename (None, StartDate, StartDateTime).

inline CsvWriter(std::string const &filename, FileSinkConfig sink_config, bool should_write_header = true)

Constructs a CsvWriter object that writes to a file.

Parameters:
std::string const &filename

The name of the CSV file to write to.

FileSinkConfig sink_config

Configuration settings for the file sink.

bool should_write_header = true

Whether to write the header at the beginning of the CSV file.

inline CsvWriter(std::string const &filename, RotatingFileSinkConfig sink_config, bool should_write_header = true)

Constructs a CsvWriter object that writes to a rotating file.

Parameters:
std::string const &filename

The name of the CSV file to write to.

RotatingFileSinkConfig sink_config

Configuration settings for the file sink.

bool should_write_header = true

Whether to write the header at the beginning of the CSV file.

inline CsvWriter(std::string const &unique_name, std::shared_ptr<Sink> sink, bool should_write_header = true)

Constructs a CsvWriter object that writes to a specified sink.

Parameters:
std::string const &unique_name

A unique name for this CsvWriter instance.

std::shared_ptr<Sink> sink

The sink to output the data to (e.g., a ConsoleSink or a user-defined Sink).

bool should_write_header = true

Whether to write the header at the beginning of the CSV file.

inline CsvWriter(std::string const &unique_name, std::vector<std::shared_ptr<Sink>> sinks, bool should_write_header = true)

Constructs a CsvWriter object that writes to multiple sinks.

Parameters:
std::string const &unique_name

A unique name for this CsvWriter instance.

std::vector<std::shared_ptr<Sink>> sinks

A list of sinks to output the data to.

bool should_write_header = true

Whether to write the header at the beginning of the CSV file.

inline ~CsvWriter()

Destructor for CsvWriter.

The destructor performs best-effort asynchronous cleanup. Call close() before Backend::stop() when deterministic logger removal and file closure are required.

template<typename ...Args>
inline void append_row(Args&&... fields)

Appends a row to the CSV file. This function is also thread safe.

Parameters:
Args&&... fields

The fields to append to the CSV row.

inline void write_header()

Writes the csv header

inline void write_header(FileEventNotifierHandle file)

Writes the csv header to the specified file

Parameters:
FileEventNotifierHandle file

file to write

inline void close()

Removes the logger synchronously and closes the underlying file sink before returning.

After calling close(), this CsvWriter instance must no longer be used.

Note

This function must only be used while the backend worker is running.

inline void flush()

Flushes the log to ensure all data is written to the file. This method will block the caller thread until the file is flushed, ensuring that all data are flushed to the file.