Reason #86 •
March 27th, 2026
Logging with Logger
The logger standard gem provides a straightforward way to add logging to your Ruby applications. It supports multiple log levels and formatting options and can be easily extended with custom log devices and formatters.
Ruby
require "logger"
logger = Logger.new(STDOUT)
logger.level = Logger::INFO
logger.debug "This is a debug message"
# won't be logged since the log level is set to INFO
logger.info "an info message"
# I, [2026-03-23T12:00:00.000000 #12345] INFO -- : an info message
logger.warn "a warning"
# W, [2026-03-23T12:00:00.000000 #12345] WARN -- : a warning
logger.error "an error"
# E, [2026-03-23T12:00:00.000000 #12345] ERROR -- : an error
logger.fatal "a fatal error"
# F, [2026-03-23T12:00:00.000000 #12345] FATAL -- : a fatal error
# We can also pass in the message with a block, which will only be
# evaluated if the log level is high enough:
logger.debug { "won't be evaluated" }
logger.info { "hello from block" }
# I, [2026-03-23T12:00:00.000000 #12345] INFO -- : hello from block
# If we pass both a message and a block, the message is used as
# "program name" and the block is used as the actual log message:
logger.info("MyApp") { "info message" }
# I, [2026-03-23T12:00:00.000000 #12345] INFO -- MyApp: info message
Adding custom formatting is as easy as assigning a proc to the formatter attribute of the logger:
Ruby
# Simple formatter
logger.formatter = proc do |severity, time, _program_name, msg|
"#{time.iso8601} #{severity}: #{msg}\n"
end
logger.info "custom formatting FTW!"
# 2026-03-23T12:00:00Z INFO: custom formatting FTW!
# JSON formatter
require "json"
logger.formatter = proc do |severity, time, program_name, message|
timestamp = time.iso8601
{ severity:, timestamp:, program_name:, message: }.to_json + "\n"
end
logger.info("MyApp") { "hello in JSON" }
# { "severity": "INFO", "timestamp": "2026-03-23T12:00:00Z", ... }
If you're running in some kind of boomer environment and want to log to a file instead of STDOUT, you can either pass a file path to Logger.new or pass an IO object:
Ruby
logger = Logger.new("application.log")
logger.info "This will be logged to application.log"
file = File.open("another.log", "a")
another_logger = Logger.new(file)
another_logger.info "This will be logged to another.log"
History
The Logger class was added to the Ruby standard library in Ruby 1.8.1, released on Christmas Day 2003.