Class: ActiveSupport::BroadcastLogger

Inherits:
Object
  • Object
show all
Includes:
LoggerSilence
Defined in:
lib/activesupport/broadcast_logger.rb

Overview

Active Support Broadcast Logger

The Broadcast logger is a logger used to write messages to multiple IO. It is commonly used in development to display messages on STDOUT and also write them to a file (development.log). With the Broadcast logger, you can broadcast your logs to an unlimited number of sinks.

The BroadcastLogger acts as a standard logger and all methods you are used to are available. However, all the methods on this logger will propagate and be delegated to the other loggers that are part of the broadcast.

Broadcasting your logs.

stdout_logger = Logger.new(STDOUT)
file_logger   = Logger.new("development.log")
broadcast = BroadcastLogger.new(stdout_logger, file_logger)

broadcast.info("Hello world!") # Writes the log to STDOUT and the development.log file.

Add a logger to the broadcast.

stdout_logger = Logger.new(STDOUT)
broadcast = BroadcastLogger.new(stdout_logger)
file_logger   = Logger.new("development.log")
broadcast.broadcast_to(file_logger)

broadcast.info("Hello world!") # Writes the log to STDOUT and the development.log file.

Modifying the log level for all broadcasted loggers.

stdout_logger = Logger.new(STDOUT)
file_logger   = Logger.new("development.log")
broadcast = BroadcastLogger.new(stdout_logger, file_logger)

broadcast.level = Logger::FATAL # Modify the log level for the whole broadcast.

Stop broadcasting log to a sink.

stdout_logger = Logger.new(STDOUT)
file_logger   = Logger.new("development.log")
broadcast = BroadcastLogger.new(stdout_logger, file_logger)
broadcast.info("Hello world!") # Writes the log to STDOUT and the development.log file.

broadcast.stop_broadcasting_to(file_logger)
broadcast.info("Hello world!") # Writes the log *only* to STDOUT.

At least one sink has to be part of the broadcast. Otherwise, your logs will not be written anywhere. For instance:

broadcast = BroadcastLogger.new
broadcast.info("Hello world") # The log message will appear nowhere.

If you are adding a custom logger with custom methods to the broadcast, the ‘BroadcastLogger` will proxy them and return the raw value, or an array of raw values, depending on how many loggers in the broadcasts responded to the method:

class MyLogger < ::Logger
  def loggable?
    true
  end
end

logger = BroadcastLogger.new
logger.loggable? # => A NoMethodError exception is raised because no loggers in the broadcasts could respond.

logger.broadcast_to(MyLogger.new(STDOUT))
logger.loggable? # => true
logger.broadcast_to(MyLogger.new(STDOUT))
puts logger.broadcasts # => [MyLogger, MyLogger]
logger.loggable? # [true, true]

Constant Summary collapse

LOGGER_METHODS =

Forward all standard Logger methods to each logger in the broadcast.

%w[
  <<
  log
  add
  debug
  info
  warn
  error
  fatal
  unknown
  debug!
  info!
  warn!
  error!
  fatal!
  level=
  sev_threshold=
  local_level
  local_level=
  close
  formatter
  formatter=
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*loggers) ⇒ BroadcastLogger

Returns a new instance of BroadcastLogger.



81
82
83
84
85
86
# File 'lib/activesupport/broadcast_logger.rb', line 81

def initialize(*loggers)
  @broadcasts = []
  @progname = "Broadcast"

  broadcast_to(*loggers)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, **kwargs, &block) ⇒ Object (private)



205
206
207
208
209
210
211
212
213
214
215
# File 'lib/activesupport/broadcast_logger.rb', line 205

def method_missing(name, *args, **kwargs, &block)
  loggers = @broadcasts.select { |logger| logger.respond_to?(name) }

  if loggers.none?
    super
  elsif loggers.one?
    loggers.first.send(name, *args, **kwargs, &block)
  else
    loggers.map { |logger| logger.send(name, *args, **kwargs, &block) }
  end
end

Instance Attribute Details

#broadcastsObject (readonly)

Returns all the logger that are part of this broadcast.



78
79
80
# File 'lib/activesupport/broadcast_logger.rb', line 78

def broadcasts
  @broadcasts
end

#prognameObject

Returns the value of attribute progname.



79
80
81
# File 'lib/activesupport/broadcast_logger.rb', line 79

def progname
  @progname
end

Instance Method Details

#broadcast_to(*loggers) ⇒ Object

Add logger(s) to the broadcast.

broadcast_logger = ActiveSupport::BroadcastLogger.new
broadcast_logger.broadcast_to(Logger.new(STDOUT), Logger.new(STDERR))


92
93
94
# File 'lib/activesupport/broadcast_logger.rb', line 92

def broadcast_to(*loggers)
  @broadcasts.concat(loggers)
end

#debug?Boolean

True if the log level allows entries with severity Logger::DEBUG to be written to at least one broadcast. False otherwise.

Returns:

  • (Boolean)


146
147
148
# File 'lib/activesupport/broadcast_logger.rb', line 146

def debug?
  @broadcasts.any? { |logger| logger.debug? }
end

#error?Boolean

True if the log level allows entries with severity Logger::ERROR to be written to at least one broadcast. False otherwise.

Returns:

  • (Boolean)


164
165
166
# File 'lib/activesupport/broadcast_logger.rb', line 164

def error?
  @broadcasts.any? { |logger| logger.error? }
end

#fatal?Boolean

True if the log level allows entries with severity Logger::FATAL to be written to at least one broadcast. False otherwise.

Returns:

  • (Boolean)


170
171
172
# File 'lib/activesupport/broadcast_logger.rb', line 170

def fatal?
  @broadcasts.any? { |logger| logger.fatal? }
end

#info?Boolean

True if the log level allows entries with severity Logger::INFO to be written to at least one broadcast. False otherwise.

Returns:

  • (Boolean)


152
153
154
# File 'lib/activesupport/broadcast_logger.rb', line 152

def info?
  @broadcasts.any? { |logger| logger.info? }
end

#initialize_copy(other) ⇒ Object



174
175
176
177
178
179
# File 'lib/activesupport/broadcast_logger.rb', line 174

def initialize_copy(other)
  @broadcasts = []
  @progname = other.progname.dup

  broadcast_to(*other.broadcasts.map(&:dup))
end

#levelObject

Returns the lowest level of all the loggers in the broadcast.



140
141
142
# File 'lib/activesupport/broadcast_logger.rb', line 140

def level
  @broadcasts.map(&:level).min
end

#stop_broadcasting_to(logger) ⇒ Object

Remove a logger from the broadcast. When a logger is removed, messages sent to the broadcast will no longer be written to its sink.

sink = Logger.new(STDOUT)
broadcast_logger = ActiveSupport::BroadcastLogger.new

broadcast_logger.stop_broadcasting_to(sink)


103
104
105
# File 'lib/activesupport/broadcast_logger.rb', line 103

def stop_broadcasting_to(logger)
  @broadcasts.delete(logger)
end

#warn?Boolean

True if the log level allows entries with severity Logger::WARN to be written to at least one broadcast. False otherwise.

Returns:

  • (Boolean)


158
159
160
# File 'lib/activesupport/broadcast_logger.rb', line 158

def warn?
  @broadcasts.any? { |logger| logger.warn? }
end