How to Create Rotating File Sinks in spdlog: A Complete Guide
To create rotating file sinks in spdlog, use the rotating_file_sink_mt or rotating_file_sink_st templates, or the convenience factory functions spdlog::rotating_logger_mt() and spdlog::rotating_logger_st(), which automatically roll over log files when they reach a specified size limit.
The gabime/spdlog library provides a high-performance, header-only C++ logging framework with built-in support for log rotation. When you create rotating file sinks in spdlog, the library handles automatic file rollover, ensuring that log archives remain manageable while preserving historical data according to configurable retention policies.
How Rotating File Sinks Work in spdlog
The rotating file sink implementation resides in include/spdlog/sinks/rotating_file_sink.h with inline definitions in include/spdlog/sinks/rotating_file_sink-inl.h. The class template spdlog::sinks::rotating_file_sink<Mutex> inherits from base_sink<Mutex> and encapsulates a details::file_helper for low-level file operations.
When a log message arrives, the sink_it_ method formats the message and estimates the resulting file size. If the size would exceed the configured max_size_, the sink flushes the current file and invokes rotate_() before writing the new entry. The rotation algorithm iterates backwards from max_files_ down to 1, renaming each existing file to the next index (e.g., log.1.txt becomes log.2.txt), then opens a fresh file for continued logging.
Creating a Rotating File Logger
Using the Factory Helper (Multi-Threaded)
The simplest way to create a rotating logger is through the spdlog::rotating_logger_mt() factory function defined in include/spdlog/sinks/rotating_file_sink.h.
#include <spdlog/spdlog.h>
#include <spdlog/sinks/rotating_file_sink.h>
int main() {
// Create a logger that rotates after 5 MiB, keeping up to 3 files
auto logger = spdlog::rotating_logger_mt(
"my_logger", // logger name
"logs/app.log", // base filename
5 * 1024 * 1024, // 5 MiB max size per file
3); // keep 3 rotated files
logger->info("Application started");
}
This function internally instantiates rotating_file_sink_mt (the mutex-synchronized variant) through synchronous_factory::create.
Explicit Sink Construction (Single-Threaded)
For single-threaded applications where synchronization overhead is unnecessary, use rotating_file_sink_st with a null_mutex:
#include <spdlog/spdlog.h>
#include <spdlog/sinks/rotating_file_sink.h>
int main() {
using sink_t = spdlog::sinks::rotating_file_sink_st;
auto sink = std::make_shared<sink_t>(
"logs/server.log", // base filename
10 * 1024 * 1024, // 10 MiB max size
5, // keep 5 rotated files
false); // do not rotate on open
auto logger = std::make_shared<spdlog::logger>("server", sink);
spdlog::register_logger(logger);
logger->warn("Server listening on port {}", 8080);
}
Understanding the Rotation Algorithm
The rotation logic in include/spdlog/sinks/rotating_file_sink-inl.h follows a specific naming convention and renaming strategy:
- Filename calculation: The
calc_filename()method generates names likelog.txt,log.1.txt, throughlog.N.txtby splitting the base filename and inserting rotation indices. - Validation: The constructor enforces that
max_sizemust be greater than 0 andmax_filescannot exceed 200,000 (MaxFilesconstant). - Atomic renaming: The
rotate_()method closes the current file, then iterates frommax_files_down to 1, renaming each existing file to the next higher index usingrename_file_(), which removes existing targets before invoking the OS rename primitive.
Thread Safety Considerations
spdlog provides two type aliases for different concurrency requirements:
rotating_file_sink_mt: Usesstd::mutexfor thread-safe access from multiple threads.rotating_file_sink_st: Usesspdlog::details::null_mutex(no-op) for single-threaded scenarios, eliminating synchronization overhead.
Choose the appropriate variant based on your application's threading model to optimize performance.
Manual Rotation and Advanced Usage
You can force immediate rotation programmatically using the rotate_now() method:
logger->flush(); // ensure all data is written
auto sink = std::static_pointer_cast<spdlog::sinks::rotating_file_sink_mt>(logger->sinks()[0]);
sink->rotate_now(); // immediate rotation
This acquires the sink's mutex and invokes the internal rotate_() logic directly, useful for log rotation triggered by external signals or time-based policies.
Summary
- Create rotating file sinks in spdlog using
rotating_logger_mt()/rotating_logger_st()factory functions or direct template instantiation ofrotating_file_sink_mt/st. - The implementation resides in
include/spdlog/sinks/rotating_file_sink.hwith rotation logic in the-inl.hheader. - Configure maximum file size and retention count (up to 200,000 files) via constructor parameters.
- Select
rotating_file_sink_mtfor multi-threaded applications orrotating_file_sink_stfor single-threaded performance. - Use
rotate_now()to trigger manual rotation when needed.
Frequently Asked Questions
What is the maximum number of rotated files supported?
According to the source code in include/spdlog/sinks/rotating_file_sink-inl.h, spdlog enforces a hard limit of 200,000 rotated files (MaxFiles constant). The constructor validates that the max_files parameter is greater than 0 and does not exceed this upper bound.
How does spdlog handle file naming during rotation?
The calc_filename() function in include/spdlog/sinks/rotating_file_sink-inl.h splits the base filename into stem and extension, then inserts the rotation index between them. This produces sequences like app.log, app.1.log, app.2.log, etc., ensuring chronological ordering by index.
Can I force a log rotation manually?
Yes. Obtain a pointer to the sink (casting from logger->sinks()), then call rotate_now(). This method locks the mutex and executes the same rotate_() algorithm used during automatic size-based rotation, closing the current file and cycling archived files immediately.
What is the difference between rotating_file_sink_mt and rotating_file_sink_st?
rotating_file_sink_mt instantiates the template with std::mutex, providing thread-safe logging for concurrent access. rotating_file_sink_st uses null_mutex, which performs no locking and offers better performance for single-threaded contexts where synchronization is unnecessary.
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 →