class Logger

Class Logger provides a simple but sophisticated logging utility that you can use to create one or more event logs for your program. Each such log contains a chronological sequence of entries that provides a record of the program’s activities.

About the Examples

All examples on this page assume that Logger has been required:

require 'logger'

Synopsis

Create a log with Logger.new:

# Single log file.
logger = Logger.new('t.log')
# Size-based rotated logging: 3 10-megabyte files.
logger = Logger.new('t.log', 3, 10485760)
# Period-based rotated logging: daily (also allowed: 'weekly', 'monthly').
logger = Logger.new('t.log', 'daily')
# Log to an IO stream.
logger = Logger.new($stdout)

Add entries (level, message) with Logger#add:

logger.add(Logger::DEBUG, 'Maximal debugging info')
logger.add(Logger::INFO, 'Non-error information')
logger.add(Logger::WARN, 'Non-error warning')
logger.add(Logger::ERROR, 'Non-fatal error')
logger.add(Logger::FATAL, 'Fatal error')
logger.add(Logger::UNKNOWN, 'Most severe')

Close the log with Logger#close:

logger.close

Entries

You can add entries with method Logger#add:

logger.add(Logger::DEBUG, 'Maximal debugging info')
logger.add(Logger::INFO, 'Non-error information')
logger.add(Logger::WARN, 'Non-error warning')
logger.add(Logger::ERROR, 'Non-fatal error')
logger.add(Logger::FATAL, 'Fatal error')
logger.add(Logger::UNKNOWN, 'Most severe')

These shorthand methods also add entries:

logger.debug('Maximal debugging info')
logger.info('Non-error information')
logger.warn('Non-error warning')
logger.error('Non-fatal error')
logger.fatal('Fatal error')
logger.unknown('Most severe')

When you call any of these methods, the entry may or may not be written to the log, depending on the entry’s severity and on the log level; see Log Level

An entry always has:

And may also have:

Example:

logger = Logger.new($stdout)
logger.add(Logger::INFO, 'My message.', 'mung')
# => I, [2022-05-07T17:21:46.536234 #20536]  INFO -- mung: My message.

The default format for an entry is:

"%s, [%s #%d] %5s -- %s: %s\n"

where the values to be formatted are:

You can use a different entry format by:

Severity

The severity of a log entry has two effects:

Timestamp

The timestamp for a log entry is generated automatically when the entry is created.

The logged timestamp is formatted by method Time#strftime using this format string:

'%Y-%m-%dT%H:%M:%S.%6N'

Example:

logger = Logger.new($stdout)
logger.add(Logger::INFO)
# => I, [2022-05-07T17:04:32.318331 #20536]  INFO -- : nil

You can set a different format using method datetime_format=.

Message

The message is an optional argument to an entry method:

logger = Logger.new($stdout)
logger.add(Logger::INFO, 'My message')
# => I, [2022-05-07T18:15:37.647581 #20536]  INFO -- : My message

For the default entry formatter, Logger::Formatter, the message object may be:

Note: Logger::Formatter does not escape or sanitize the message passed to it. Developers should be aware that malicious data (user input) may be in the message, and should explicitly escape untrusted data.

You can use a custom formatter to escape message data; see the example at formatter=.

Program Name

The program name is an optional argument to an entry method:

logger = Logger.new($stdout)
logger.add(Logger::INFO, 'My message', 'mung')
# => I, [2022-05-07T18:17:38.084716 #20536]  INFO -- mung: My message

The default program name for a new logger may be set in the call to Logger.new via optional keyword argument progname:

logger = Logger.new('t.log', progname: 'mung')

The default program name for an existing logger may be set by a call to method progname=:

logger.progname = 'mung'

The current program name may be retrieved with method progname:

logger.progname # => "mung"

Log Level

The log level setting determines whether an entry is actually written to the log, based on the entry’s severity.

These are the defined severities (least severe to most severe):

logger = Logger.new($stdout)
logger.add(Logger::DEBUG, 'Maximal debugging info')
# => D, [2022-05-07T17:57:41.776220 #20536] DEBUG -- : Maximal debugging info
logger.add(Logger::INFO, 'Non-error information')
# => I, [2022-05-07T17:59:14.349167 #20536]  INFO -- : Non-error information
logger.add(Logger::WARN, 'Non-error warning')
# => W, [2022-05-07T18:00:45.337538 #20536]  WARN -- : Non-error warning
logger.add(Logger::ERROR, 'Non-fatal error')
# => E, [2022-05-07T18:02:41.592912 #20536] ERROR -- : Non-fatal error
logger.add(Logger::FATAL, 'Fatal error')
# => F, [2022-05-07T18:05:24.703931 #20536] FATAL -- : Fatal error
logger.add(Logger::UNKNOWN, 'Most severe')
# => A, [2022-05-07T18:07:54.657491 #20536]   ANY -- : Most severe

The default initial level setting is Logger::DEBUG, the lowest level, which means that all entries are to be written, regardless of severity:

logger = Logger.new($stdout)
logger.level # => 0
logger.add(0, "My message")
# => D, [2022-05-11T15:10:59.773668 #20536] DEBUG -- : My message

You can specify a different setting in a new logger using keyword argument level with an appropriate value:

logger = Logger.new($stdout, level: Logger::ERROR)
logger = Logger.new($stdout, level: 'error')
logger = Logger.new($stdout, level: :error)
logger.level # => 3

With this level, entries with severity Logger::ERROR and higher are written, while those with lower severities are not written:

logger = Logger.new($stdout, level: Logger::ERROR)
logger.add(3)
# => E, [2022-05-11T15:17:20.933362 #20536] ERROR -- : nil
logger.add(2) # Silent.

You can set the log level for an existing logger with method level=:

logger.level = Logger::ERROR

These shorthand methods also set the level:

logger.debug! # => 0
logger.info!  # => 1
logger.warn!  # => 2
logger.error! # => 3
logger.fatal! # => 4

You can retrieve the log level with method level.

logger.level = Logger::ERROR
logger.level # => 3

These methods return whether a given level is to be written:

logger.level = Logger::ERROR
logger.debug? # => false
logger.info?  # => false
logger.warn?  # => false
logger.error? # => true
logger.fatal? # => true

Log File Rotation

By default, a log file is a single file that grows indefinitely (until explicitly closed); there is no file rotation.

To keep log files to a manageable size, you can use log file rotation, which uses multiple log files:

Size-Based Rotation

For size-based log file rotation, call Logger.new with:

Examples:

logger = Logger.new('t.log', 3)           # Three 1-megabyte files.
logger = Logger.new('t.log', 5, 10485760) # Five 10-megabyte files.

For these examples, suppose:

logger = Logger.new('t.log', 3)

Logging begins in the new log file, t.log; the log file is “full” and ready for rotation when a new entry would cause its size to exceed shift_size.

The first time t.log is full:

The second time t.log is full:

Each subsequent time that t.log is full, the log files are rotated:

Periodic Rotation

For periodic rotation, call Logger.new with:

Examples:

logger = Logger.new('t.log', 'daily')   # Rotate log files daily.
logger = Logger.new('t.log', 'weekly')  # Rotate log files weekly.
logger = Logger.new('t.log', 'monthly') # Rotate log files monthly.

Example:

logger = Logger.new('t.log', 'daily')

When the given period expires:

The default format for the suffix is '%Y%m%d', which produces a suffix similar to the one above. You can set a different format using create-time option shift_period_suffix; see details and suggestions at Time#strftime.