# How daily_file_sink Determines When to Create a New Log File in spdlog

> Learn how daily_file_sink in spdlog creates new log files. Discover its timestamp-based rotation strategy and configurable daily time points for efficient log management.

- Repository: [Gabi Melman/spdlog](https://github.com/gabime/spdlog)
- Tags: internals
- Published: 2026-07-19

---

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

```cpp
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:

```cpp
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_`:

```cpp
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:

1. **Calculate the new filename** using the current date (`FileNameCalc::calc_filename`)
2. **Open the new file**, optionally truncating it based on the constructor flag
3. **Re-compute the next rotation time** for the following day

```cpp
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):

```cpp
// 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:

```cpp
// 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_sink` is time-based, occurring at a configurable hour and minute every day.
- The sink calculates the next rotation time during initialization using `next_rotation_tp_()` in [`include/spdlog/sinks/daily_file_sink.h`](https://github.com/gabime/spdlog/blob/main/include/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`](https://github.com/gabime/spdlog/blob/main/daily_file_sink.h). The default calculator appends the date to the base filename (e.g., `app_2024-01-15.log`).