Rotate log files in Ruby

Configure size or time-based Logger rotation, understand retention limits, and test collection across file changes.

Best practices
Illustration of monitoring and troubleshooting application behavior

Ruby's Logger can rotate a file by size or by a daily, weekly, or monthly period. Choose one owner for rotation, then verify how the application and collector behave when a file changes.

Rotate by time

require 'logger'

logger = Logger.new('application.log', 'daily')
logger.info('Application started')

Use 'weekly' or 'monthly' instead of 'daily' for those periods. Rotation is checked when logging writes occur; Logger is not a scheduler that wakes up at midnight to rotate an idle file.

Period-based rotation creates dated files without applying the integer retention count used by size-based rotation. Set a deliberate cleanup policy for those archives rather than assuming old files will disappear automatically.

Rotate by size

require 'logger'

logger = Logger.new('application.log', 10, 100 * 1024 * 1024)
logger.info('Using size-based rotation')

The integer rotation count bounds the file set, and the size argument is a byte threshold: here, 100 MiB. It is not a strict per-file maximum; a record can take the file beyond the threshold before the next rotation check. 100.megabytes requires ActiveSupport and is not available in plain Ruby.

Formatting and severity remain independent of rotation:

logger.formatter = proc do |severity, time, progname, message|
  "#{time.strftime('%Y-%m-%d %H:%M:%S %z')} [#{severity}] #{message}\n"
end
logger.level = Logger::INFO

Use an external rotation tool deliberately

On systems using logrotate, a configuration might be:

/var/log/myapp/application.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}

With copytruncate, the application keeps its open file descriptor, but records written between copying and truncating can be lost. It is not a general fix for concurrent writers. Renaming the file and asking the application to reopen it can avoid that particular race, provided the application supports a reliable reopen mechanism.

Do not let Logger and logrotate independently rename the same active file. For multiple processes, consider stdout collection or separate files per process instead of relying on simultaneous rotation of one shared file.

Verify ingestion and retention

With DataKit file collection, write uniquely numbered records before and after rotation. Check for gaps and duplicates, then repeat with a collector restart. Coordinate local retention with how long collection can be unavailable.

In Rails, configure config.logger if choosing application-managed rotation, preserving any tagging and formatting your application needs. Container deployments often send logs to stdout and delegate rotation to the runtime's logging system.

References: Ruby Logger and logrotate's copytruncate behavior.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting