Skip to content

Commit

Permalink
Expose the logdev
Browse files Browse the repository at this point in the history
The motivation here is to fix a Rails issue caused by the way
ActiveSupport extends the ruby Logger to add broadcasting of messages to
multiple destinations. [1] I believe the problem could be much more
elegantly solved if Logger exposed the underlying LogDevice. Going by
repo history, the existence of this object hasn't changed since 2003, so
I think it's stable enough to expose.

In addition to letting you read the logdev, this also lets you pass a
logdev in. To implement broadcasting, we could now define a LogDevice
subclass that delegates its 3 methods to the LogDevices of a list of
underlying loggers, and simply create a new logger with this device.

[1]: https://github.com/rails/rails/blob/ba19dbc49956a73f417abd68c7a5f33e302eacd3/activesupport/lib/active_support/logger.rb#L23
  • Loading branch information
oggy authored and hsbt committed Jun 6, 2024
1 parent 1a9c0a8 commit 89614f0
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
19 changes: 15 additions & 4 deletions lib/logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ def fatal!; self.level = FATAL; end
# new entries are appended.
# - An IO stream (typically +$stdout+, +$stderr+. or an open file):
# entries are to be written to the given stream.
# - An instance of Logger::LogDevice, such as the #logdev of another Logger.
# - +nil+ or +File::NULL+: no entries are to be written.
#
# Examples:
Expand Down Expand Up @@ -586,13 +587,23 @@ def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG,
@logdev = nil
@level_override = {}
if logdev && logdev != File::NULL
@logdev = LogDevice.new(logdev, shift_age: shift_age,
shift_size: shift_size,
shift_period_suffix: shift_period_suffix,
binmode: binmode)
if logdev.is_a?(LogDevice)
@logdev = logdev
else
@logdev = LogDevice.new(logdev, shift_age: shift_age,
shift_size: shift_size,
shift_period_suffix: shift_period_suffix,
binmode: binmode)
end
end
end

# The underlying log device.
#
# This is the first argument passed to the constructor, wrapped in a
# Logger::LogDevice, along with the binmode flag and rotation options.
attr_reader :logdev

# Sets the logger's output stream:
#
# - If +logdev+ is +nil+, reopens the current output stream.
Expand Down
10 changes: 10 additions & 0 deletions test/logger/test_logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,16 @@ def test_initialize
assert_nil(logger.datetime_format)
end

def test_logdev
logger = Logger.new(STDERR)
assert_instance_of(Logger::LogDevice, logger.logdev)

logdev = Logger::LogDevice.new(STDERR)
logger = Logger.new(logdev)
assert_instance_of(Logger::LogDevice, logger.logdev)
assert_equal(STDERR, logger.logdev.dev)
end

def test_initialize_with_level
# default
logger = Logger.new(STDERR)
Expand Down

0 comments on commit 89614f0

Please sign in to comment.