User’s API

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::nanoseconds{500}

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

uint32_t transit_event_buffer_initial_capacity = 128

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 must be a power of two.

size_t transit_events_soft_limit = 4096

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 (default: 800), 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 = 32'768

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 = {1}

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, guaranteeing ordering by timestamp.

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, then sleeps 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 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 the messages from the lock-free queues but ensures correct timestamp order.

Setting log_timestamp_ordering_grace_period to zero disables strict timestamp ordering.

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.

However, if there is a thread during application destruction that keeps trying to log indefinitely, the backend will be unable to exit because it keeps popping log messages.

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, especially when strict_log_timestamp_order is set to true.

uint16_t cpu_affinity = (std::numeric_limits<uint16_t>::max)()

Pins the backend to the specified CPU.

By default, the backend is not pinned to any CPU unless a value is specified. It is recommended to pin the backend to a shared non-critical CPU. Use std::numeric_limits<uint16_t>::max() as an undefined value to avoid setting CPU affinity.

std::function<void(std::string const&)> error_notifier = [](std::string const& error_message){std::fprintf(stderr, "%s\n", error_message.data());}

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 notifications, simply leave the function undefined: std::function<void(std::string const&)> backend_error_notifier = {};

It’s safe to perform logging operations within this function (e.g., LOG_INFO(…)), but avoid calling logger->flush_log(). The function is invoked on the backend thread, which should not remain in a waiting state as it waits for itself.

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::function<bool(char c)> check_printable_char = [](char c){ return (c >= ' ' && c <= '~') || (c == '\n'); }

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, 12> log_level_descriptions = {"TRACE_L3", "TRACE_L2", "TRACE_L1", "DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "CRITICAL", "BACKTRACE", "NONE", "DYNAMIC"}

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, 12> log_level_short_codes = {"T3", "T2", "T1", "D", "I", "N", "W", "E", "C", "BT", "_", "DN"}

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.

Backend Class

class Backend

Public Static Functions

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

Starts the backend thread.

Parameters:

optionsBackend 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

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 a lock-free queue to issue log statements and await the log flushing. The queue is constructed on its first use with new(). Failing to meet any of the above criteria means the queue was never used, and it will be constructed inside the signal handler. The new operation is not an async signal-safe function and may lead to potential issues. However, when the queue is already created, no new call is made, and the remaining functions invoked internally by the built-in signal handler are async safe.

Parameters:
  • backend_optionsBackend options to configure the backend behavior.

  • signal_handler_options – SignalHandler options to configure the signal handler behavior. is enabled.

static inline void stop() noexcept

Stops the backend 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) noexcept

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:

rdtsc_value – The RDTSC value to convert.

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 call logger->flush_log(), as this can lead to a deadlock situation.

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

  • 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 (true)
    {
      manual_backend_worker->poll();
    }
  });

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() noexcept

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

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) noexcept

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:

rdtsc – The TSC counter value

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.

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

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 the specified logger is not found, or if this parameter is left empty, the signal handler will default to using the first valid logger it finds.

Frontend Options

struct FrontendOptions

Public Static Attributes

static constexpr 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 2GB, then blocks.

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

  • UnboundedUnlimited: Starts with initial_queue_capacity and reallocates without limit, subsequent queues are reallocated as needed. Never blocks or drops.

  • BoundedBlocking: Starts with initial_queue_capacity and never reallocates; blocks when the limit is reached.

  • 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 constexpr uint32_t initial_queue_capacity = 128 * 1024

Initial capacity of the queue. Used for UnboundedBlocking, UnboundedDropping, and UnboundedUnlimited. Also serves as the capacity for BoundedBlocking and BoundedDropping.

static constexpr uint32_t blocking_queue_retry_interval_ns = 800

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

static constexpr bool huge_pages_enabled = false

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.

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.

Parameters:
  • sink_name – The name of the sink.

  • 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:

sink_name – The name of the sink.

Returns:

std::shared_ptr<Sink> A shared pointer to the retrieved sink, or nullptr if not found.

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.

Parameters:
  • logger_name – The name of the logger.

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

  • pattern_formatter_options – Contains the formatting configuration for PatternFormatter

  • clock_source – The clock source for log timestamps.

  • user_clock – 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.

Parameters:
  • logger_name – The name of the logger.

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

  • pattern_formatter_options – Contains the formatting configuration for PatternFormatter

  • clock_source – The clock source for log timestamps.

  • user_clock – 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.

Parameters:
  • logger_name – The name of the logger.

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

  • pattern_formatter_options – Contains the formatting configuration for PatternFormatter

  • clock_source – The clock source for log timestamps.

  • user_clock – 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.

Parameters:
  • logger_name – The name of the logger to create or retrieve.

  • source_logger – 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, any files associated with its sinks are also closed.

Note

Thread-safe

Parameters:

logger – A pointer to the logger to remove.

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

Retrieves an existing logger with the specified name.

Parameters:

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.

Log Levels

enum class LogLevel : uint8_t

Log level enum

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
enumerator Dynamic

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

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 immediate_flush, bool has_dynamic_log_level, typename... Args> inline bool log_statement (QUILL_MAYBE_UNUSED LogLevel dynamic_log_level, 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:
  • dynamic_log_level – dynamic log level

  • macro_metadata – metadata of the log message

  • 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 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 messages and displays them later on demand.

Parameters:
  • max_capacity – The max number of messages to store in the backtrace

  • flush_level – If this loggers 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()

Parameters:

sleep_duration_ns – 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.

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:

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

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. %(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

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

Timezone timestamp_timezone

The timezone to use for timestamps.

Determines whether timestamps are formatted in local time or GMT.

bool add_metadata_to_multi_line_logs

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.

Sink Class

class Sink

Base class for sinks

Subclassed by NullSink, StreamSink

Public Functions

Sink() = default

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:

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:

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:

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:
  • log_metadata – Pointer to the macro metadata.

  • log_timestamp – Timestamp of the log event.

  • thread_id – ID of the thread.

  • thread_name – Name of the thread.

  • logger_name – Name of the logger.

  • log_level – Log level of the message.

  • log_message – The log message.

  • 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 JsonFileSinkConfig, 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:
  • value – The append type to set. Valid options are Date and DateAndTime.

  • append_filename_format_pattern – Specifies a custom strftime format pattern to use for the filename. This parameter is only applicable when FilenameAppendOption::CustomDateTimeFormat 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:

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.

Parameters:

value – True to perform fsync, false otherwise.

inline void set_open_mode(char open_mode)

Sets the open mode for the file. Valid options for the open mode are ‘a’ or ‘w’. The default value is ‘a’.

Parameters:

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:

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:

value – The minimum interval, in milliseconds, between fsync calls.

inline bool fsync_enabled() const noexcept

Getters

FileSink Class

class FileSink : public StreamSink

FileSink Writes the log messages to a file

Subclassed by JsonFileSink, RotatingFileSink

Public Functions

inline explicit FileSink(fs::path const &filename, FileSinkConfig const &config = FileSinkConfig{}, FileEventNotifier file_event_notifier = FileEventNotifier{}, bool do_fopen = true, std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now())

Construct a FileSink object. This constructor will always attempt to open the given file.

Parameters:
  • filename – Path to the file to be opened.

  • config – Configuration for the FileSink.

  • file_event_notifier – Notifies on file events.

  • do_fopen – If false, the file will not be opened.

inline virtual void flush_sink() override

Flushes the stream and optionally fsyncs it.

RotatingFileSinkConfig Class

class RotatingFileSinkConfig : public FileSinkConfig

The configuration options for the RotatingFileSink.

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:

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:
  • frequency – The frequency of file rotation (‘M’ for minutes, ‘H’ for hours)

  • 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:

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.

Parameters:

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:

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 FilenameAppend::DateTime was not set. The default value is true.

Parameters:

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:

value – The naming scheme to set.

inline size_t rotation_max_file_size() const noexcept

Getter methods

RotatingFileSink Class

class RotatingFileSink : public FileSink

The RotatingFileSink class.

Public Functions

inline RotatingFileSink(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 RotatingFileSink class.

Parameters:
  • filename – The base file name to be used for logs.

  • config – The sink configuration.

  • file_event_notifier – file event notifier

  • start_time – start time

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

Writes a formatted log message to the stream.

Parameters:
  • log_metadata – The metadata of the log message

  • log_timestamp – The timestamp of the log message

  • thread_id – The ID of the thread that generated the log message

  • thread_name – The name of the thread that generated the log message

  • process_id – Process Id

  • log_level – Log level of the message.

  • log_level_description – Description of the log level.

  • log_level_short_code – Short code representing the log level.

  • named_args – Structured key-value pairs associated with the log message

  • log_message – The log message to write

  • log_statement – The full log statement

JsonFileSink Class

class JsonFileSink : public FileSink

Public Functions

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, std::string_view) override

Logs a formatted log message to the sink.

Note

Accessor for backend processing.

Parameters:
  • log_metadata – Pointer to the macro metadata.

  • log_timestamp – Timestamp of the log event.

  • thread_id – ID of the thread.

  • thread_name – Name of the thread.

  • process_id – Process Id

  • logger_name – Name of the logger.

  • log_level – Log level of the message.

  • log_level_description – Description of the log level.

  • log_level_short_code – Short code representing the log level.

  • named_args – Vector of key-value pairs of named args

JsonConsoleSink Class

class JsonConsoleSink : public StreamSink

Public Functions

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, std::string_view) override

Logs a formatted log message to the sink.

Note

Accessor for backend processing.

Parameters:
  • log_metadata – Pointer to the macro metadata.

  • log_timestamp – Timestamp of the log event.

  • thread_id – ID of the thread.

  • thread_name – Name of the thread.

  • process_id – Process Id

  • logger_name – Name of the logger.

  • log_level – Log level of the message.

  • log_level_description – Description of the log level.

  • log_level_short_code – Short code representing the log level.

  • named_args – Vector of key-value pairs of named args

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.

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:
  • TCsvSchema – A user-defined struct specifying the CSV schema at compile-time.

  • TFrontendOptions – Custom frontend_t options if they are used application-wide. If no custom frontend_t options are used, then use quill::frontend_tOptions.

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:
  • filename – The name of the CSV file to write to.

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

  • filename_append – Option to append to the filename (None, Date, DateTime).

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

Constructs a CsvWriter object that writes to a specified sink.

Parameters:
  • unique_name – A unique name for this CsvWriter instance.

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

inline CsvWriter(std::string const &unique_name, std::initializer_list<std::shared_ptr<Sink>> sinks)

Constructs a CsvWriter object that writes to multiple sinks.

Parameters:
  • unique_name – A unique name for this CsvWriter instance.

  • sinks – An initializer list of sinks to output the data to.

inline ~CsvWriter()

Destructor for CsvWriter. Flushes the log and removes the logger.

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

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

Parameters:

fields – The fields to append to the CSV row.

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.