Difference Between daily_file_sink and rotating_file_sink in spdlog: Complete Guide
The daily_file_sink rotates log files based on calendar time (creating a new file each day at a specific hour), while rotating_file_sink rotates based on file size (creating a new file when the current one exceeds a configurable limit).
Both sinks are part of the gabime/spdlog library and provide automatic log file management, but they serve different operational needs. Understanding the difference between daily_file_sink and rotating_file_sink in spdlog ensures you choose the right rotation strategy for your logging requirements.
Rotation Trigger: Time vs. Size
The fundamental distinction lies in what triggers the creation of a new log file.
daily_file_sink uses absolute clock time. According to the implementation in include/spdlog/sinks/daily_file_sink.h, the sink calculates the next rotation point using next_rotation_tp_() (lines 51–62). When the current time passes the configured hour and minute (e.g., 02:30 AM), it closes the current file and opens a new one with the current date appended.
rotating_file_sink monitors file size. In include/spdlog/sinks/rotating_file_sink-inl.h, every call to sink_it_() checks if writing the next log message would exceed max_size_ (lines 13–22). When the threshold is reached, the sink triggers rotate_() to close the current file and create a new one.
Filename Generation and Format
Each sink uses a distinct naming convention that reflects its rotation strategy.
Daily files embed the date in the filename. The daily_filename_calculator (or daily_filename_format_calculator) in daily_file_sink.h (lines 30–38) generates names like app_2024-09-15.log. This makes it trivial to locate logs for a specific calendar date.
Rotated files use numeric indices. The calc_filename() method in rotating_file_sink-inl.h (lines 54–64) appends an index to the base name, producing sequences like app.log, app.1.log, app.2.log. When rotation occurs, existing files are renamed incrementally (e.g., app.1.log becomes app.2.log).
Retention and Cleanup Policies
Both sinks support automatic cleanup through an optional max_files parameter, but the semantics differ based on the rotation trigger.
Daily sink retention keeps the most recent N daily files. The delete_old_() method in daily_file_sink.h (lines 64–82) scans the log directory and removes files older than the configured retention count. This is ideal for compliance policies requiring "last 30 days of logs."
Rotating sink retention maintains a fixed number of backup files. The rotate_() method in rotating_file_sink-inl.h (lines 38–66) ensures that if max_files is 5, you will have app.log (current) plus app.1.log through app.4.log. If a new rotation occurs, the oldest file is deleted before renaming the others.
Thread Safety Variants
Both sinks inherit from base_sink<Mutex> and provide thread-safe and single-threaded variants. You can instantiate either:
daily_logger_mt/rotating_logger_mt: Multithreaded versions using mutex locking (suitable for concurrent logging from multiple threads).daily_logger_st/rotating_logger_st: Single-threaded versions without locking overhead (optimal when only one thread writes to the logger).
Constructor Signatures and Configuration
Understanding the parameter differences helps when configuring your logger:
Daily File Sink:
daily_file_sink(base_filename, hour, minute, truncate = false, max_files = 0, ...)
hourandminute: Specify the rotation time (24-hour format).truncate: If true, overwrites existing files on startup.max_files: Number of daily files to retain (0 = unlimited).
See the constructor implementation in daily_file_sink.h (lines 71–78).
Rotating File Sink:
rotating_file_sink(base_filename, max_size, max_files, rotate_on_open = false, ...)
max_size: Maximum file size in bytes before rotation.max_files: Number of rotated files to keep (not counting the current file).rotate_on_open: If true, rotates immediately when opening the file.
See the constructor in rotating_file_sink-inl.h (lines 25–32).
Practical Code Examples
Daily Rotation at 02:30 AM with 7-Day Retention
#include <spdlog/sinks/daily_file_sink.h>
auto logger = spdlog::daily_logger_mt(
"daily_logger", // logger name
"logs/myapp.log", // base filename
2, 30, // rotate at 02:30
false, // do not truncate existing file
7); // keep 7 most recent daily files
logger->info("Application started");
Size-Based Rotation (5 MiB max, 5 backups)
#include <spdlog/sinks/rotating_file_sink.h>
auto logger = spdlog::rotating_logger_mt(
"rot_logger", // logger name
"logs/myapp.log", // base filename
5 * 1024 * 1024, // 5 MiB max size
5); // keep 5 rotated files
logger->info("Application started");
Single-Threaded Variants
For low-contention scenarios where thread safety is unnecessary, use the _st variants to reduce lock overhead:
// Daily single-threaded
auto daily_st = spdlog::daily_logger_st(
"daily_st", "logs/st_app.log", 0, 0, false, 3);
// Rotating single-threaded
auto rot_st = spdlog::rotating_logger_st(
"rot_st", "logs/st_app.log", 10 * 1024 * 1024, 10);
When to Use Which Sink
Choose daily_file_sink when:
- You need to analyze logs by calendar date (e.g., "show me yesterday's errors").
- Compliance requirements mandate daily log separation.
- Log volume is predictable and you prefer time-based archiving.
Choose rotating_file_sink when:
- Disk space is constrained and you must enforce a hard size limit per file.
- You need to ensure individual log files remain small enough to open in text editors or email.
- You want a predictable number of backup files regardless of how much data is logged.
Summary
daily_file_sinkrotates at a specific time each day (configurable hour/minute) and embeds dates in filenames.rotating_file_sinkrotates when files exceed a size limit (bytes) and uses numeric indices for backups.- Both support
max_filesretention, butdaily_file_sinkdeletes old files by date whilerotating_file_sinkmanages a fixed-size rolling window. - Both offer multithreaded (
*_mt) and single-threaded (*_st) variants implemented indaily_file_sink.handrotating_file_sink-inl.h.
Frequently Asked Questions
Can I use both daily and rotating file sinks simultaneously?
Yes. You can attach multiple sinks to a single logger or create separate loggers. For example, you might use daily_file_sink for audit trails and rotating_file_sink for verbose debug output. Combine them using spdlog::sinks_init_list or the spdlog::logger constructor that accepts a vector of sinks.
Which sink has better performance?
Both sinks inherit from base_sink<Mutex> and have similar overhead for the actual logging operation. However, rotating_file_sink checks file size on every log message (in sink_it_()), while daily_file_sink only checks the current time against the next rotation timestamp. For extremely high-throughput logging (millions of messages per second), daily_file_sink may have marginally lower overhead since it avoids size calculations.
How do I configure the exact rotation time for daily files?
Pass the hour (0–23) and minute (0–59) to the constructor or factory function. For example, to rotate at midnight, use 0, 0. To rotate at 6:45 PM, use 18, 45. The sink uses the local system time by default. If the application is not running at the scheduled rotation time, it will rotate immediately upon the next log message once the time has passed.
What happens when the maximum number of files is reached?
When max_files is exceeded, both sinks automatically delete the oldest file. For rotating_file_sink, this happens during the rotate_() operation where the oldest indexed file is removed before renaming others. For daily_file_sink, the delete_old_() method scans the directory and removes files with older dates once the count exceeds max_files. If max_files is 0 (default), no automatic deletion occurs and files accumulate indefinitely.
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 →