Class: ActiveSupport::BroadcastLogger

Inherits:
Object
  • Object
show all
Includes:
LoggerSilence
Defined in:
lib/active_support/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 a 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]

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from LoggerSilence

#silence

Methods included from Concern

#append_features, #class_methods, extended, #included, #prepend_features, #prepended

Constructor Details

#initialize(*loggers) ⇒ BroadcastLogger

Returns a new instance of BroadcastLogger.



82
83
84
85
86
87
# File 'lib/active_support/broadcast_logger.rb', line 82

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) ⇒ Object (private)



235
236
237
238
239
240
241
242
243
244
245
# File 'lib/active_support/broadcast_logger.rb', line 235

def method_missing(name, ...)
  loggers = @broadcasts.select { |logger| logger.respond_to?(name) }

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

Instance Attribute Details

#broadcastsObject (readonly)

Returns all the logger that are part of this broadcast.



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

def broadcasts
  @broadcasts
end

#formatterObject

Returns the value of attribute formatter.



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

def formatter
  @formatter
end

#prognameObject

Returns the value of attribute progname.



80
81
82
# File 'lib/active_support/broadcast_logger.rb', line 80

def progname
  @progname
end

Instance Method Details

#<<(message) ⇒ Object



112
113
114
# File 'lib/active_support/broadcast_logger.rb', line 112

def <<(message)
  dispatch { |logger| logger.<<(message) }
end

#add(*args, &block) ⇒ Object Also known as: log



116
117
118
# File 'lib/active_support/broadcast_logger.rb', line 116

def add(*args, &block)
  dispatch { |logger| logger.add(*args, &block) }
end

#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))


93
94
95
# File 'lib/active_support/broadcast_logger.rb', line 93

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

#closeObject



162
163
164
# File 'lib/active_support/broadcast_logger.rb', line 162

def close
  dispatch { |logger| logger.close }
end

#debug(*args, &block) ⇒ Object



121
122
123
# File 'lib/active_support/broadcast_logger.rb', line 121

def debug(*args, &block)
  dispatch { |logger| logger.debug(*args, &block) }
end

#debug!Object

Sets the log level to Logger::DEBUG for the whole broadcast.



173
174
175
# File 'lib/active_support/broadcast_logger.rb', line 173

def debug!
  dispatch { |logger| logger.debug! }
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)


168
169
170
# File 'lib/active_support/broadcast_logger.rb', line 168

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

#error(*args, &block) ⇒ Object



133
134
135
# File 'lib/active_support/broadcast_logger.rb', line 133

def error(*args, &block)
  dispatch { |logger| logger.error(*args, &block) }
end

#error!Object

Sets the log level to Logger::ERROR for the whole broadcast.



206
207
208
# File 'lib/active_support/broadcast_logger.rb', line 206

def error!
  dispatch { |logger| logger.error! }
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)


201
202
203
# File 'lib/active_support/broadcast_logger.rb', line 201

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

#fatal(*args, &block) ⇒ Object



137
138
139
# File 'lib/active_support/broadcast_logger.rb', line 137

def fatal(*args, &block)
  dispatch { |logger| logger.fatal(*args, &block) }
end

#fatal!Object

Sets the log level to Logger::FATAL for the whole broadcast.



217
218
219
# File 'lib/active_support/broadcast_logger.rb', line 217

def fatal!
  dispatch { |logger| logger.fatal! }
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)


212
213
214
# File 'lib/active_support/broadcast_logger.rb', line 212

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

#info(*args, &block) ⇒ Object



125
126
127
# File 'lib/active_support/broadcast_logger.rb', line 125

def info(*args, &block)
  dispatch { |logger| logger.info(*args, &block) }
end

#info!Object

Sets the log level to Logger::INFO for the whole broadcast.



184
185
186
# File 'lib/active_support/broadcast_logger.rb', line 184

def info!
  dispatch { |logger| logger.info! }
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)


179
180
181
# File 'lib/active_support/broadcast_logger.rb', line 179

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

#initialize_copy(other) ⇒ Object



221
222
223
224
225
226
227
# File 'lib/active_support/broadcast_logger.rb', line 221

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

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

#levelObject



108
109
110
# File 'lib/active_support/broadcast_logger.rb', line 108

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

#level=(level) ⇒ Object Also known as: sev_threshold=



151
152
153
# File 'lib/active_support/broadcast_logger.rb', line 151

def level=(level)
  dispatch { |logger| logger.level = level }
end

#local_level=(level) ⇒ Object



156
157
158
159
160
# File 'lib/active_support/broadcast_logger.rb', line 156

def local_level=(level)
  dispatch do |logger|
    logger.local_level = level if logger.respond_to?(:local_level=)
  end
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)


104
105
106
# File 'lib/active_support/broadcast_logger.rb', line 104

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

#unknown(*args, &block) ⇒ Object



141
142
143
# File 'lib/active_support/broadcast_logger.rb', line 141

def unknown(*args, &block)
  dispatch { |logger| logger.unknown(*args, &block) }
end

#warn(*args, &block) ⇒ Object



129
130
131
# File 'lib/active_support/broadcast_logger.rb', line 129

def warn(*args, &block)
  dispatch { |logger| logger.warn(*args, &block) }
end

#warn!Object

Sets the log level to Logger::WARN for the whole broadcast.



195
196
197
# File 'lib/active_support/broadcast_logger.rb', line 195

def warn!
  dispatch { |logger| logger.warn! }
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)


190
191
192
# File 'lib/active_support/broadcast_logger.rb', line 190

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