-
Notifications
You must be signed in to change notification settings - Fork 3
File Rotation
This page explains how logme keeps file logs manageable in long-running applications.
There are two related but separate mechanisms:
- per-backend lifecycle policy in
FileBackend; - home directory size monitoring through
DirectorySizeWatchdog.
They solve different problems and can be used together.
FileBackend writes to one active file and can complete that file into an archive when a configured lifecycle boundary is reached. A completed file may then be retained, compressed, or deleted by retention rules.
The normal write path remains focused on appending data. Archive-name scanning, retention cleanup, and compression submission happen on startup cleanup or file-completion paths, not on every log record.
A production-style file backend can look like this:
{
"type": "FileBackend",
"file": "logs/app.log",
"append": true,
"rotation": "daily",
"max-size": "100Mb",
"on-size-limit": "rotate",
"archive": "logs/archive/app.{date}.{index}.log",
"compression": "gz",
"retention": {
"max-files": 14,
"max-age": "30d",
"max-total-size": "2Gb",
"clean-on-start": true
}
}If a configured path is relative, it is resolved relative to the logger home directory.
See also File Backend and Configuration JSON.
max-size limits the active file size. By default, logme keeps the historical behavior: when the limit is exceeded, the active file is truncated rather than archived.
{
"type": "FileBackend",
"file": "logs/app.log",
"max-size": "100Mb",
"on-size-limit": "truncate"
}max-size accepts either a plain byte count or byte-size suffixes documented in Utility Helpers, for example 512Kb, 64Mb, or 1Gb.
To rotate instead of truncating, set on-size-limit to rotate and provide an archive pattern containing {index}:
{
"type": "FileBackend",
"file": "logs/app.log",
"max-size": "100Mb",
"on-size-limit": "rotate",
"archive": "logs/archive/app.{index}.log"
}When the size limit is reached, the active file is closed, moved to the next free archive name, and the active file is opened again. Existing .log and .log.gz archive names are skipped, so runtime collisions and restart recovery do not overwrite older archives.
on-size-limit: "rotate" requires an archive pattern with {index}.
The rotation option accepts:
-
none,off, ordisabled; -
hourly; -
daily; -
weekly; -
monthly.
Example:
{
"type": "FileBackend",
"file": "logs/app.log",
"rotation": "daily",
"archive": "logs/archive/app.{date}.{index}.log"
}The old rotation: "daily" behavior remains supported. If time rotation is disabled, the hot path does not compute time-period boundaries.
Size and time rotation can be used together. Both use the same file-completion path, so archive naming, retention, compression, and counters are handled consistently.
{
"type": "FileBackend",
"file": "logs/app.log",
"rotation": "daily",
"max-size": "100Mb",
"on-size-limit": "rotate",
"archive": "logs/archive/app.{date}.{index}.log"
}Archive patterns can use:
-
{index}— monotonically increasing archive part number for the current pattern/period; -
{date}— date part based on the completion period; -
{datetime}— date-time part based on the completion period.
When a time placeholder and {index} are used together, startup recovery restores the index for the current period. Archives from other periods do not consume the current period index.
Retention rules apply to completed archive files, not to the active file.
{
"type": "FileBackend",
"file": "logs/app.log",
"rotation": "daily",
"archive": "logs/archive/app.{date}.{index}.log",
"retention": {
"max-files": 14,
"max-age": "30d",
"max-total-size": "2Gb",
"clean-on-start": true
}
}Retention fields:
-
retention.max-fileskeeps only the newest matching archive files; -
retention.max-ageremoves matching archives older than the configured interval; -
retention.max-total-sizekeeps matching archive files under the configured total size by deleting older files first; -
retention.clean-on-startruns retention when the backend is configured.
Disabled values:
-
max-files = 0keeps all matching archives; -
max-age = 0disables age-based cleanup; -
max-total-size = 0disables total-size cleanup.
max-parts remains supported as a legacy alias for retention.max-files. If both are specified, they must have the same value.
Retention ignores unrelated files and protects the active file even if its name matches the archive cleanup pattern.
Optional gzip compression is enabled with compression: "gz" or compression: "gzip":
{
"type": "FileBackend",
"file": "logs/app.log",
"rotation": "daily",
"archive": "logs/archive/app.{date}.{index}.log",
"compression": "gz"
}Compression is submitted only for completed archive files. The active file is not compressed.
Gzip support depends on the USE_ZLIB CMake option. If zlib support is not compiled in, compression: "gz" is accepted but has no effect.
Accepted disabled values are none, off, disabled, or an empty string.
When FILE_ENABLE_COUNTERS is enabled, FileBackend::GetCounters() and the [FileBackend] statistics dump include lifecycle counters:
-
SizeLimitCompletionCalls— file completions triggered by size-limit rotation; -
TimeLimitCompletionCalls— file completions triggered by time rotation; -
ArchivedFiles— completed files successfully moved to archive names; -
CompressionSubmitCalls— completed archive files submitted to the compression manager; -
RetentionRuns— retention cleanup passes started by startup cleanup or file completion.
These counters are updated only on lifecycle paths. Normal appends do not run retention, compression, archive scanning, or filesystem cleanup.
File rotation is best-effort. If an archive directory cannot be created or the active file cannot be moved to an archive name, the backend reopens the active file in append mode and keeps logging when possible.
This avoids losing existing active-log content on rotation failure.
DirectorySizeWatchdog works at the logger home-directory level.
It is configured through the home-directory section:
{
"home-directory": {
"path": "logs",
"watch-dog": {
"enable": true,
"max-size": "10GB",
"check-periodicity": "30s",
"file-extension": [".log", ".gz"]
}
}
}The watchdog monitors total directory size and removes old files when the configured limit is exceeded.
This is different from per-backend retention:
-
retention.*applies to archives produced by oneFileBackendarchive pattern; - the watchdog controls total disk usage in the logging directory.
The watchdog consults the file manager before deleting files, so active files used by registered FileBackend instances are not removed.
Use time rotation when log files should naturally split by time period.
Use on-size-limit: "rotate" when large active files should be completed into archives instead of truncated.
Use retention.* when each backend should retain only a bounded archive history.
Use the directory watchdog when total disk usage matters more than the number of archives per backend.
In production, it is common to combine all of them.
logme — flexible runtime logging system
Home · Getting Started · Architecture · Output · Backends · Configuration
GitHub: https://github.com/efmsoft/logme
- Home
- Getting Started
- Why logme?
- Core Concepts
- Logging Macros
- Fatal Handling
- Crash Logging
- glog Compatibility
- C API
- Choosing Logging Macros
- Function tracing
- Trace Points
- Override Scopes
- Advanced Features
- Collapse Logging
- Feature Map
- Overview
- Console Backend
- Debugger Backend
- File Backend
- File Rotation & Retention
- Buffer Backend
- Ring Buffer Backend
- SharedFile Backend
- Callback Backend
- Windows Event Log Backend
- Custom Backends
- Runtime Control
- Configuration
- Configuration JSON
- Control Server
- Environment Control
- Control Policies
- Trace Points
- Message Filtering