How daily_file_sink Determines When to Create a New Log File in spdlog
The daily_file_sink creates a new log file whenever an incoming message's timestamp reaches or exceeds a pre-calculated daily rotation time point, which is computed based on a configurable hour and minute.
spdlog::sinks::daily_file_sink is a header-only logging sink that handles automatic log rotation on a daily schedule. Unlike size-based rotation, this sink rotates files at a specific time of day, ensuring one log file per calendar day (or per configured interval). According to the spdlog source code, the rotation logic relies on comparing incoming message timestamps against a stored future time point that represents the next scheduled rotation.
Initialization and Rotation Time Calculation
When a daily_file_sink is constructed, it immediately calculates when the first rotation should occur. The constructor stores the user-provided rotation hour (rotation_h_) and minute (rotation_m_), opens the initial file based on the current date, and sets the rotation_tp_ member:
rotation_tp_ = next_rotation_tp_(); // Lines 93-94 in daily_file_sink.h
Computing the Next Rotation Point
The private method next_rotation_tp_() determines the exact moment of the next rotation by building a tm structure for today at the configured hour and minute. If that time has already passed today, it adds 24 hours to ensure the rotation always points to the next occurrence:
date.tm_hour = rotation_h_;
date.tm_min = rotation_m_;
date.tm_sec = 0;
// Lines 154-162
if (rotation_time > now) {
return rotation_time;
}
return {rotation_time + std::chrono::hours(24)};
This ensures that rotation_tp_ always holds a time point in the future, making the comparison logic straightforward.
The Rotation Check During Logging
Every log message processed by the sink triggers the rotation check inside the sink_it_ method. This is where the actual decision to create a new file happens.
Comparing Message Timestamps
The sink compares the message's timestamp against the stored rotation_tp_:
auto time = msg.time;
bool should_rotate = time >= rotation_tp_; // Lines 1008-1009
If the message timestamp is greater than or equal to the rotation time point, should_rotate becomes true, signaling that the current day's file is complete and a new one must be started.
File Creation and Rotation Reset
When rotation is triggered, the sink performs three critical operations in sequence:
- Calculate the new filename using the current date (
FileNameCalc::calc_filename) - Open the new file, optionally truncating it based on the constructor flag
- Re-compute the next rotation time for the following day
const auto new_filename = FileNameCalc::calc_filename(base_filename_, now_tm(time));
file_helper_.open(new_filename, truncate_);
rotation_tp_ = next_rotation_tp_(); // Lines 1010-1012
This atomic sequence ensures uninterrupted logging while maintaining the daily rotation schedule.
Practical Usage Examples
Configure your logger to rotate at midnight using the default hour (00:00):
// Example 1 – Simple daily rotation at midnight
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/app.log");
// Rotates each day at 00:00 (default hour/minute)
For custom rotation schedules, specify the exact hour and minute, and optionally limit the number of archived files:
// Example 2 – Rotate each day at 14:30, keep only the last 7 files
auto logger = spdlog::daily_logger_mt(
"daily_logger",
"logs/app.log",
14, // rotation hour
30, // rotation minute
false, // do not truncate existing file
7); // keep up to 7 past files
Summary
- Log rotation in
daily_file_sinkis time-based, occurring at a configurable hour and minute every day. - The sink calculates the next rotation time during initialization using
next_rotation_tp_()ininclude/spdlog/sinks/daily_file_sink.h. - Each log message triggers a timestamp comparison (
msg.time >= rotation_tp_) to determine if rotation is needed. - When rotation occurs, the sink generates a new filename based on the current date, opens the file, and recalculates the next rotation point.
- This mechanism ensures exactly one file per rotation period while the application runs continuously.
Frequently Asked Questions
How does daily_file_sink handle time zones?
The daily_file_sink uses the system's local time via std::localtime when calculating rotation points. It does not explicitly handle time zone conversions, so the rotation occurs based on the local system time where the application runs.
What happens if no log messages arrive at the rotation time?
The sink only checks rotation when processing a log message. If no messages arrive until well past the rotation time, the next message will trigger the rotation check, compare against the stale rotation_tp_, immediately trigger rotation, and then update to the next day's rotation time.
Can I use daily_file_sink with sub-day rotation intervals?
No, daily_file_sink is specifically designed for daily rotation. For sub-day intervals (hourly, every minute), use spdlog::sinks::rotating_file_sink for size-based rotation, or implement a custom sink inheriting from daily_file_sink with modified time calculation logic.
Where does the filename calculation happen when creating a new file?
The filename calculation occurs through the FileNameCalc template parameter's calc_filename static method, which is invoked in sink_it_ at lines 1010-1011 of daily_file_sink.h. The default calculator appends the date to the base filename (e.g., app_2024-01-15.log).
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 →