Class: Lumberjack::Logger

Inherits:
Logger
  • Object
show all
Includes:
ContextLogger
Defined in:
lib/lumberjack/logger.rb

Overview

Lumberjack::Logger is a thread-safe, feature-rich logging implementation that extends Ruby’s standard library Logger class with advanced capabilities for structured logging.

Key features include:

  • Structured logging with attributes (key-value pairs) attached to log entries

  • Context isolation for scoping logging behavior to specific code blocks

  • Flexible output devices supporting files, streams, and custom destinations

  • Customizable formatters for messages and attributes

The Logger maintains full API compatibility with Ruby’s standard Logger while adding powerful extensions for modern logging needs.

Log entries are written to a logging Device if their severity meets or exceeds the log level. Each log entry records the log message and severity along with the time it was logged, the program name, process id, and an optional hash of attributes. Messages are converted to strings using a Formatter associated with the logger.

Examples:

Basic usage

logger = Lumberjack::Logger.new(STDOUT)
logger.info("Starting processing")
logger.debug("Processing options #{options.inspect}")
logger.fatal("OMG the application is on fire!")

Structured logging with attributes

logger = Lumberjack::Logger.new("/var/log/app.log")
logger.tag(request_id: "abc123") do
  logger.info("User logged in", user_id: 123, ip: "192.168.1.1")
  logger.info("Processing request")  # Will include request_id: "abc123"
end

Log rotation

# Keep 10 files, rotate when each reaches 10MB
logger = Lumberjack::Logger.new("/var/log/app.log", 10, 10 * 1024 * 1024)

Using different devices

logger = Lumberjack::Logger.new("logs/application.log")  # Log to file
logger = Lumberjack::Logger.new(STDOUT, template: "{{severity}} - {{message}}")  # Log to a stream with a template
logger = Lumberjack::Logger.new(:test)  # Log to an in memory buffer for testing
logger = Lumberjack::Logger.new(another_logger) # Proxy logs to another logger
logger = Lumberjack::Logger.new(MyDevice.new)  # Log to a custom Lumberjack::Device

Logging to multiple devices with an array

logger = Lumberjack::Logger.new(["/var/log/app.log", [:stdout, {template: "{{message}}"}]])

See Also:

Direct Known Subclasses

ForkedLogger

Constant Summary

Constants included from ContextLogger

ContextLogger::LEADING_OR_TRAILING_WHITESPACE, ContextLogger::TRACE

Instance Method Summary collapse

Methods included from ContextLogger

#<<, #add, #append_to, #attribute_value, #attributes, #clear_attributes, #context, #debug, #debug!, #debug?, #default_severity, #default_severity=, #ensure_context, #error, #error!, #error?, #fatal, #fatal!, #fatal?, #fork, #in_context?, included, #info, #info!, #info?, #level, #level=, #progname, #progname=, #tag, #tag!, #tag_all_contexts, #trace, #trace!, #trace?, #unknown, #untag, #untag!, #warn, #warn!, #warn?, #with_level, #with_progname

Constructor Details

#initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG, progname: nil, formatter: nil, datetime_format: nil, binmode: false, shift_period_suffix: "%Y%m%d", **kwargs) ⇒ Lumberjack::Logger

Create a new logger to log to a Device.

The device argument can be in any one of several formats:

  • A symbol for a device name (e.g. :null, :test). You can call Lumberjack::DeviceRegistry.registered_devices for a list.

  • A stream

  • A file path string or Pathname

  • A Lumberjack::Device object

  • An object with a write method will be wrapped in a Device::Writer

  • An array of any of the above will open a Multi device that will send output to all devices.

Parameters:

  • logdev (Lumberjack::Device, IO, Symbol, String, Pathname)

    The device to log to. If this is a symbol, the device will be looked up from the DeviceRegistry. If it is a string or a Pathname, the logs will be sent to the corresponding file path.

  • shift_age (Integer, String, Symbol) (defaults to: 0)

    If this is an integer greater than zero, then log files will be rolled when they get to the size specified in shift_size and the number of files to keep will be determined by this value. Otherwise it will be interpreted as a date rolling value and must be one of “daily”, “weekly”, or “monthly”. This parameter has no effect unless the device parameter is a file path or file stream. This can also be specified with the :roll keyword argument.

  • shift_size (Integer) (defaults to: 1048576)

    The size in bytes of the log files before rolling them. This can be passed as a string with a unit suffix of K, M, or G (e.g. “10M” for 10 megabytes). This can also be specified with the :max_size keyword argument.

  • level (Integer, Symbol, String) (defaults to: DEBUG)

    The logging level below which messages will be ignored.

  • progname (String) (defaults to: nil)

    The name of the program that will be recorded with each log entry.

  • formatter (Lumberjack::EntryFormatter, Lumberjack::Formatter, ::Logger::Formatter, :default, #call) (defaults to: nil)

    The formatter to use for outputting messages to the log. If this is a Lumberjack::EntryFormatter or a Lumberjack::Formatter, it will be used to format structured log entries. You can also pass the value :default to use the default message formatter which formats non-primitive objects with inspect and includes the backtrace in exceptions.

    For compatibility with the standard library Logger when writing to a stream, you can also pass in a ::Logger::Formatter object or a callable object that takes exactly 4 arguments (severity, time, progname, msg).

  • datetime_format (String) (defaults to: nil)

    The format to use for log timestamps.

  • binmode (Boolean) (defaults to: false)

    Whether to open the log file in binary mode.

  • shift_period_suffix (String) (defaults to: "%Y%m%d")

    The suffix to use for the shifted log file names.

  • kwargs (Hash)

    Additional device-specific options. These will be passed through when creating a device from the logdev argument.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/lumberjack/logger.rb', line 94

def initialize(logdev, shift_age = 0, shift_size = 1048576,
  level: DEBUG, progname: nil, formatter: nil, datetime_format: nil,
  binmode: false, shift_period_suffix: "%Y%m%d", **kwargs)
  init_context_locals!

  if shift_age.is_a?(Hash)
    Lumberjack::Utils.deprecated("Logger.new(options)", "Passing a Hash as the second argument to Logger.new is deprecated and will be removed in version 2.1; use keyword arguments instead.")
    options = shift_age
    level = options[:level] if options.include?(:level)
    progname = options[:progname] if options.include?(:progname)
    formatter = options[:formatter] if options.include?(:formatter)
    datetime_format = options[:datetime_format] if options.include?(:datetime_format)
    kwargs = options.merge(kwargs)
  end

  self.isolation_level = kwargs.delete(:isolation_level) || Lumberjack.isolation_level

  # Include standard args that affect devices with the optional kwargs which may
  # contain device specific options.
  device_options = kwargs.merge(shift_age: shift_age, shift_size: size_with_units(shift_size), binmode: binmode, shift_period_suffix: shift_period_suffix)
  device_options[:standard_logger_formatter] = formatter if standard_logger_formatter?(formatter)

  if device_options.include?(:roll)
    Utils.deprecated("Logger.options(:roll)", "Lumberjack::Logger :roll option is deprecated and will be removed in version 2.1; use the shift_age argument instead.")
    device_options[:shift_age] = device_options.delete(:roll) unless shift_age != 0
  end

  if device_options.include?(:max_size)
    Utils.deprecated("Logger.options(:max_size)", "Lumberjack::Logger :max_size option is deprecated and will be removed in version 2.1; use the shift_size argument instead.")
    device_options[:shift_age] = 10 if shift_age == 0
    device_options[:shift_size] = device_options.delete(:max_size)
  end

  message_formatter = nil
  if device_options.include?(:message_formatter)
    Utils.deprecated("Logger.options(:message_formatter)", "Lumberjack::Logger :message_formatter option is deprecated and will be removed in version 2.1; use the formatter argument instead to specify an EntryFormatter.")
    message_formatter = device_options.delete(:message_formatter)
  end

  attribute_formatter = nil
  if device_options.include?(:tag_formatter)
    Utils.deprecated("Logger.options(:tag_formatter)", "Lumberjack::Logger :tag_formatter option is deprecated and will be removed in version 2.1; use the formatter argument instead to specify an EntryFormatter.")
    attribute_formatter = device_options.delete(:tag_formatter)
  end

  @logdev = Device.open_device(logdev, device_options)

  @context = Context.new
  self.level = level || DEBUG
  self.progname = progname

  self.formatter = build_entry_formatter(formatter, message_formatter, attribute_formatter)
  self.datetime_format = datetime_format if datetime_format

  @closed = false
end

Instance Method Details

#add_entry(severity, message, progname = nil, attributes = nil) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Add an entry to the log.

Parameters:

  • severity (Integer, Symbol, String)

    The severity of the message.

  • message (Object)

    The message to log.

  • progname (String) (defaults to: nil)

    The name of the program that is logging the message.

  • attributes (Hash) (defaults to: nil)

    The attributes to add to the log entry.



399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/lumberjack/logger.rb', line 399

def add_entry(severity, message, progname = nil, attributes = nil)
  return false unless device

  # Prevent infinite recursion if logging is attempted from within a logging call.
  if current_context_locals&.logging
    log_to_stderr(severity, message)
    return false
  end

  severity = Severity.label_to_level(severity) unless severity.is_a?(Integer)

  new_context_locals do |locals|
    locals.logging = true # protection from infinite loops

    time = Time.now
    progname ||= self.progname
    attributes = nil unless attributes.is_a?(Hash)
    attributes = merge_attributes(merge_all_attributes, attributes)
    message, attributes = formatter.format(message, attributes) if formatter

    entry = Lumberjack::LogEntry.new(time, severity, message, progname, Process.pid, attributes)

    write_to_device(entry)
  end

  true
end

#attribute_formatterLumberjack::AttributeFormatter

Get the attribute formatter used to format log entry attributes.

Returns:



210
211
212
# File 'lib/lumberjack/logger.rb', line 210

def attribute_formatter
  formatter.attribute_formatter
end

#attribute_formatter=(value) ⇒ void

This method returns an undefined value.

Set the attribute formatter used to format log entry attributes.

Parameters:



218
219
220
# File 'lib/lumberjack/logger.rb', line 218

def attribute_formatter=(value)
  formatter.attribute_formatter = value
end

#closevoid

This method returns an undefined value.

Close the logging device.



247
248
249
250
251
# File 'lib/lumberjack/logger.rb', line 247

def close
  flush
  device.close if device.respond_to?(:close)
  @closed = true
end

#closed?Boolean

Returns true if the logging device is closed.

Returns:

  • (Boolean)

    true if the logging device is closed.



256
257
258
259
260
# File 'lib/lumberjack/logger.rb', line 256

def closed?
  return true if @closed

  device.respond_to?(:closed?) && device.closed?
end

#datetime_formatString?

Get the timestamp format on the device if it has one.

Returns:

  • (String, nil)

    The timestamp format or nil if the device doesn’t support it.



178
179
180
# File 'lib/lumberjack/logger.rb', line 178

def datetime_format
  device.datetime_format if device.respond_to?(:datetime_format)
end

#datetime_format=(format) ⇒ void

This method returns an undefined value.

Set the timestamp format on the device if it is supported.

Parameters:

  • format (String)

    The timestamp format.



186
187
188
189
190
# File 'lib/lumberjack/logger.rb', line 186

def datetime_format=(format)
  if device.respond_to?(:datetime_format=)
    device.datetime_format = format
  end
end

#deviceLumberjack::Device

Get the logging device that is used to write log entries.

Returns:



154
155
156
# File 'lib/lumberjack/logger.rb', line 154

def device
  @logdev
end

#device=(device) ⇒ void

This method returns an undefined value.

Set the logging device to a new device.

Parameters:



162
163
164
# File 'lib/lumberjack/logger.rb', line 162

def device=(device)
  @logdev = Device.open_device(device, {})
end

#flushvoid

This method returns an undefined value.

Flush the logging device. Messages are not guaranteed to be written until this method is called.



239
240
241
242
# File 'lib/lumberjack/logger.rb', line 239

def flush
  device.flush
  nil
end

#formatter=(value) ⇒ void

This method returns an undefined value.

Set the formatter used for log entries. This can be an EntryFormatter, a standard Logger::Formatter, or any callable object that formats log entries.

Parameters:



171
172
173
# File 'lib/lumberjack/logger.rb', line 171

def formatter=(value)
  @formatter = build_entry_formatter(value, nil, nil)
end

#in_tag_context?Boolean

Deprecated.

Use context? instead

Returns:

  • (Boolean)


324
325
326
327
328
# File 'lib/lumberjack/logger.rb', line 324

def in_tag_context?
  Utils.deprecated("Logger#in_tag_context?", "Lumberjack::Logger#in_tag_context? is deprecated and will be removed in version 2.1; use in_context? instead.") do
    context?
  end
end

#inspectString

Return a human-readable representation of the logger showing its key configuration.

Returns:

  • (String)

    A string representation of the logger.



430
431
432
433
# File 'lib/lumberjack/logger.rb', line 430

def inspect
  formatted_object_id = object_id.to_s(16).rjust(16, "0")
  "#<Lumberjack::Logger:0x#{formatted_object_id} level:#{Severity.level_to_label(level)} device:#{device.class.name} progname:#{progname.inspect} attributes:#{attributes.inspect}>"
end

#log_at(level, &block) ⇒ Object

Deprecated.

This implementation is deprecated. Install the lumberjack_rails gem for full support.

Alias for with_level for compatibility with ActiveSupport loggers. This functionality has been moved to the lumberjack_rails gem.



372
373
374
375
376
377
# File 'lib/lumberjack/logger.rb', line 372

def log_at(level, &block)
  deprecation_message = "Install the lumberjack_rails gem for full support of the log_at method."
  Utils.deprecated("Logger#log_at", deprecation_message) do
    with_level(level, &block)
  end
end

#message_formatterLumberjack::Formatter

Get the message formatter used to format log messages.

Returns:



195
196
197
# File 'lib/lumberjack/logger.rb', line 195

def message_formatter
  formatter.message_formatter
end

#message_formatter=(value) ⇒ void

This method returns an undefined value.

Set the message formatter used to format log messages.

Parameters:



203
204
205
# File 'lib/lumberjack/logger.rb', line 203

def message_formatter=(value)
  formatter.message_formatter = value
end

#remove_tag(*tag_names) ⇒ void

Deprecated.

Use untag or untag! instead.

This method returns an undefined value.

Remove a tag from the current context block. If this is called inside a context block, the attributes will only be removed for the duration of that block. Otherwise they will be removed from the global attributes.

Parameters:

  • tag_names (Array<String, Symbol>)

    The attributes to remove.



337
338
339
340
341
342
# File 'lib/lumberjack/logger.rb', line 337

def remove_tag(*tag_names)
  Utils.deprecated("Logger#remove_tag", "Lumberjack::Logger#remove_tag is deprecated and will be removed in version 2.1; use untag or untag! instead.") do
    attributes = current_context&.attributes
    AttributesHelper.new(attributes).delete(*tag_names) if attributes
  end
end

#reopen(logdev = nil) ⇒ Lumberjack::Logger

Reopen the logging device.

Parameters:

  • logdev (Object) (defaults to: nil)

    passed through to the logging device.

Returns:



266
267
268
269
270
# File 'lib/lumberjack/logger.rb', line 266

def reopen(logdev = nil)
  @closed = false
  device.reopen(logdev) if device.respond_to?(:reopen)
  self
end

#set_progname(value, &block) ⇒ void

Deprecated.

Use with_progname or progname= instead.

This method returns an undefined value.

Set the program name that is associated with log messages. If a block is given, the program name will be valid only within the block.

Parameters:

  • value (String)

    The program name to use.



278
279
280
281
282
283
284
285
286
# File 'lib/lumberjack/logger.rb', line 278

def set_progname(value, &block)
  Utils.deprecated("Logger#set_progname", "Lumberjack::Logger#set_progname is deprecated and will be removed in version 2.1; use with_progname or progname= instead.") do
    if block
      with_progname(value, &block)
    else
      self.progname = value
    end
  end
end

#silence(level = Logger::ERROR, &block) ⇒ Object

Deprecated.

This implementation is deprecated. Install the lumberjack_rails gem for full support.

Alias for with_level for compatibilty with ActiveSupport loggers. This functionality has been moved to the lumberjack_rails gem.



384
385
386
387
388
389
# File 'lib/lumberjack/logger.rb', line 384

def silence(level = Logger::ERROR, &block)
  deprecation_message = "Install the lumberjack_rails gem for full support of the silence method."
  Utils.deprecated("Logger#silence", deprecation_message) do
    with_level(level, &block)
  end
end

#tag_formatterObject

Deprecated.

Use #attribute_formatter instead.



223
224
225
226
227
# File 'lib/lumberjack/logger.rb', line 223

def tag_formatter
  Utils.deprecated("Logger#tag_formatter", "Lumberjack::Logger#tag_formatter is deprecated and will be removed in version 2.1; use attribute_formatter instead.") do
    formatter.attributes.attribute_formatter
  end
end

#tag_formatter=(value) ⇒ Object

Deprecated.

Use #attribute_formatter= instead.



230
231
232
233
234
# File 'lib/lumberjack/logger.rb', line 230

def tag_formatter=(value)
  Utils.deprecated("Logger#tag_formatter=", "Lumberjack::Logger#tag_formatter= is deprecated and will be removed in version 2.1; use attribute_formatter= instead.") do
    formatter.attributes.attribute_formatter = value
  end
end

#tag_globally(tags) ⇒ void

Deprecated.

Use ContextLogger#tag! instead.

This method returns an undefined value.

Use tag! instead



314
315
316
317
318
# File 'lib/lumberjack/logger.rb', line 314

def tag_globally(tags)
  Utils.deprecated("Logger#tag_globally", "Lumberjack::Logger#tag_globally is deprecated and will be removed in version 2.1; use tag! instead.") do
    tag!(tags)
  end
end

#tag_value(name) ⇒ Hash

Deprecated.

Alias method for #attribute_value to provide backward compatibility with version 1.x API. This method will eventually be removed.

Returns:

  • (Hash)


304
305
306
307
308
# File 'lib/lumberjack/logger.rb', line 304

def tag_value(name)
  Utils.deprecated("Logger#tag_value", "Lumberjack::Logger#tag_value is deprecated and will be removed in version 2.1; use attribute_value instead.") do
    attribute_value(name)
  end
end

#tagged(*tags, &block) ⇒ Object

Deprecated.

This implementation is deprecated. Install the lumberjack_rails gem for full support.

Alias for append_to(:tagged) for compatibility with ActiveSupport support in Lumberjack 1.x. This functionality has been moved to the lumberjack_rails gem. Note that in that gem the tags are added to the :tags attribute instead of the :tagged attribute.



350
351
352
353
354
355
# File 'lib/lumberjack/logger.rb', line 350

def tagged(*tags, &block)
  deprecation_message = "Install the lumberjack_rails gem for full support of the tagged method."
  Utils.deprecated("Logger#tagged", deprecation_message) do
    append_to(:tagged, *tags, &block)
  end
end

#tagsHash

Deprecated.

Alias method for #attributes to provide backward compatibility with version 1.x API. This method will eventually be removed.

Returns:

  • (Hash)


293
294
295
296
297
# File 'lib/lumberjack/logger.rb', line 293

def tags
  Utils.deprecated("Logger#tags", "Lumberjack::Logger#tags is deprecated and will be removed in version 2.1; use attributes instead.") do
    attributes
  end
end

#untagged(&block) ⇒ Object

Deprecated.

Use clear_attributes instead.

Alias for clear_attributes.



361
362
363
364
365
# File 'lib/lumberjack/logger.rb', line 361

def untagged(&block)
  Utils.deprecated("Logger#untagged", "Lumberjack::Logger#untagged is deprecated and will be removed in version 2.1; use clear_attributes instead.") do
    clear_attributes(&block)
  end
end