How to Configure flush_on and flush_every in spdlog: Complete Control Over Log Buffering
Use spdlog::flush_on(level) to set a global minimum log level that triggers immediate sink flushing, and spdlog::flush_every(interval) to start a background thread that periodically flushes all registered loggers at fixed intervals.
The spdlog library provides two distinct mechanisms for controlling when buffered log data is physically written to output sinks. These settings, implemented in the gabime/spdlog repository, allow developers to balance performance (buffering) against durability (immediate disk writes) based on application requirements.
Understanding Flush Mechanisms in spdlog
spdlog manages sink flushing through a central registry pattern. The two primary configuration options operate at different granularities and serve different use cases.
Global Flush Level (flush_on)
The global flush level determines the minimum log severity that automatically triggers a flush after each applicable log record. When configured, any message with a level greater than or equal to the threshold causes an immediate flush of that logger's sinks.
According to the source code in include/spdlog/spdlog.h (lines 81-82), the function spdlog::flush_on() forwards to details::registry::instance().flush_on(log_level), with the implementation residing in include/spdlog/details/registry.h (lines 65-66). The registry stores this threshold in the flush_level_ member variable (defaulting to level::off).
Periodic Background Flushing (flush_every)
The periodic flushing mechanism creates a background thread that calls flush_all() on the registry at specified intervals. This ensures that buffered log entries are written to disk even if no high-severity messages trigger an automatic flush.
As implemented in include/spdlog/spdlog.h (lines 84-87), spdlog::flush_every() delegates to details::registry::instance().flush_every(interval), which instantiates a periodic_worker object stored in registry::periodic_flusher_. This worker executes the lambda [this]() { this->flush_all(); } repeatedly using the specified duration.
Configuring flush_on for Immediate Critical Logging
Set a global flush level to ensure critical messages are immediately persisted without waiting for buffer fills or periodic cycles.
Global Configuration
Apply flush_on to the global registry to affect all loggers:
#include <spdlog/spdlog.h>
#include <spdlog/level.h>
int main() {
// Flush automatically on warnings or higher
spdlog::flush_on(spdlog::level::warn);
spdlog::info("This remains buffered");
spdlog::warn("This triggers immediate flush");
spdlog::error("This also triggers immediate flush");
}
The call routes to registry::flush_on(), which updates the flush_level_ atomic used by all loggers in the global registry.
Per-Logger Configuration
Override the global setting for specific loggers using the logger's member method:
auto file_logger = spdlog::basic_logger_mt("file_logger", "my.log");
file_logger->flush_on(spdlog::level::err); // Only flush on error or critical
This per-logger configuration, defined in include/spdlog/logger.h, allows fine-grained control where some loggers flush only on critical errors while others use the global threshold.
Configuring flush_every for Background Periodic Flushing
Use flush_every when you need guaranteed durability within a specific time window, regardless of message severity.
#include <spdlog/spdlog.h>
#include <chrono>
int main() {
// Flush all registered loggers every 3 seconds
spdlog::flush_every(std::chrono::seconds(3));
spdlog::info("This message may be delayed by up to 3 seconds");
// Background thread automatically flushes sinks
}
Important Implementation Details
The flush_every mechanism creates a periodic background thread through the periodic_worker class defined in include/spdlog/details/periodic_worker.h. This thread:
- Is created on the first call to
flush_every()and joined when the registry is destroyed - Can be reconfigured by subsequent calls, which replace the interval
- Iterates over all registered loggers via
registry::flush_all(), invoking each sink'sflush()method
Both mechanisms are thread-safe. The registry protects modifications using std::mutex (flusher_mutex_ for the periodic worker and logger_map_mutex_ for the logger registry) as implemented in include/spdlog/details/registry.h.
Combining flush_on and flush_every for Production Use
For robust logging in production applications, combine both strategies to ensure critical errors are written immediately while guaranteeing regular data persistence:
spdlog::flush_on(spdlog::level::err); // Immediate flush for errors
spdlog::flush_every(std::chrono::seconds(5)); // Periodic flush every 5 seconds
This configuration ensures that:
- Critical errors trigger immediate disk writes via
flush_on - Standard informational logs are guaranteed to be written within 5 seconds via
flush_every - The background thread handles the periodic flushing without blocking application threads
Summary
spdlog::flush_on(level)sets a global threshold inregistry::flush_level_that triggers immediate sink flushing when log messages meet or exceed the specified severityspdlog::flush_every(interval)starts a backgroundperiodic_workerthread that callsflush_all()on the registry at fixed intervals- Per-logger flush levels can be set via
logger::flush_on()to override global settings - Both mechanisms are thread-safe, using mutex protection in
include/spdlog/details/registry.h - Use
flush_onfor critical error persistence andflush_everyfor guaranteed durability of standard logs
Frequently Asked Questions
What is the difference between flush_on and flush_every?
flush_on triggers flushing immediately after writing a log message that meets the level threshold, affecting only that specific log operation. flush_every creates a background thread that flushes all sinks periodically regardless of content, ensuring data is written within a specific time window even if no high-level logs occur.
Can I set different flush levels for different loggers?
Yes. While spdlog::flush_on() sets the global default in the registry, individual loggers expose a flush_on() member method. As implemented in include/spdlog/logger.h, this allows you to configure sensitive loggers to flush on warnings while keeping verbose debug loggers buffered until periodic flushes occur.
Is flush_every safe to use with single-threaded loggers?
You should only use flush_every when all registered loggers are thread-safe (e.g., created with *_mt variants). The background thread calls flush_all(), which iterates through all loggers and may invoke sink operations concurrently with application threads. For single-threaded (*_st) loggers, use explicit logger->flush() calls instead.
How do I stop the periodic flusher?
The periodic flusher thread runs until the registry is destroyed. Call spdlog::shutdown() or allow the registry singleton to be destroyed at program exit. This joins the periodic_worker thread cleanly. You cannot stop the flusher independently while keeping the registry active, though calling flush_every with a new interval replaces the existing periodic worker.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →