Class: Hoodoo::Logger
- Inherits:
-
Object
- Object
- Hoodoo::Logger
- Defined in:
- lib/hoodoo/logger/logger.rb,
lib/hoodoo/logger/fast_writer.rb,
lib/hoodoo/logger/slow_writer.rb,
lib/hoodoo/logger/writer_mixin.rb,
lib/hoodoo/logger/flattener_mixin.rb,
lib/hoodoo/logger/writers/file_writer.rb,
lib/hoodoo/logger/writers/stream_writer.rb,
lib/hoodoo/logger/writers/log_entries_dot_com_writer.rb
Overview
Multiple output logging via local code or external services. Instantiate a new Logger, then use #add to add instances of writer classes to the collection of log writers. When #report, #debug, #info, #warn or #error are called, a corresponding log message is sent once to each of the writers, provided that the configured logging level (#level, #level=) allows it.
By default, a new logger instance has no configured writers so logged messages will not go anywhere. You must use #add to add at least one writer for the instance to be useful.
Some writer classes are provided by Hoodoo, including:
-
Hoodoo::Logger::StreamWriter - write to output streams, typically expected to be fast, e.g. unredirected $stdout or $stderr.
-
Hoodoo::Logger::FileWriter - write to files, typically expected to be relatively slow.
Some loggers can preserve structural logged data (see #report) while others flatten all log messages. For example, Hoodoo::Logger::StreamWriter must flatten messages but a custom writer that, say, persisted messages in a database should be able to preserve structure.
Writers are either considered fast or slow. Fast writers are called inline as soon as a message gets logged. Slow writers are called asynchronously via a Thread. A Queue is used to buffer messages for slow writers; if this gets too large, messages may be dropped. Once the slow writer catches up, a warn
level log message is automatically logged to report the number of dropped messages in the interim.
To create a new custom writer class of any name/namespace, just subclass Hoodoo::Logger::FastWriter or Hoodoo::Logger::SlowWriter - see those classes for details.
Defined Under Namespace
Modules: Communicator, FlattenerMixin, WriterMixin Classes: FastCommunicator, FastWriter, FileWriter, Payload, SlowCommunicator, SlowWriter, StreamWriter
Instance Attribute Summary collapse
-
#level ⇒ Object
Return or set the current log level.
Instance Method Summary collapse
-
#add(*writer_instances) ⇒ Object
Add a new writer instance to this logger.
-
#debug(*args) ⇒ Object
Write a
debug
log message, provided the log level is:debug
. -
#error(*args) ⇒ Object
Write an
error
log message, regardless of logging level. -
#include?(writer_instance) ⇒ Boolean
(also: #includes?)
Does this log instance’s collection of writers include the given writer instance? Returns
true
if so, elsefalse
. -
#include_class?(writer_class) ⇒ Boolean
(also: #includes_class?)
Does this log instance’s collection of writers include any writer instances which are of the given writer class? Returns
true
if so, elsefalse
. -
#info(*args) ⇒ Object
Write an
info
log message, provided the log level is:debug
or:info
. -
#initialize(component = :Middleware) ⇒ Logger
constructor
Create a new logger instance.
-
#instances ⇒ Object
Returns an array of all log writer instances currently in use, in order of addition.
-
#remove(*writer_instances) ⇒ Object
Remove a writer instance from this logger.
-
#remove_all ⇒ Object
Remove all writer instances from this logger.
-
#report(log_level, component, code, data) ⇒ Object
Logs a message using the structured logger.
-
#report?(log_level) ⇒ Boolean
Given the log level configuration of this instance - see #level= and #level - should a message of the given log level be reported? Returns
true
if so elsefalse
. -
#wait ⇒ Object
Wait for all writers to finish writing all log messages sent up to the point of calling.
-
#warn(*args) ⇒ Object
Write a
warn
log message, provided the log level is:debug
,:info
or:warn
.
Constructor Details
#initialize(component = :Middleware) ⇒ Logger
Create a new logger instance. Once created, use #add to add writers.
component
-
Flat logging methods (see #debug, #info, #warn and #error) are internally logged through the structured logger (see #report) using the
component
(again, see #report) optionally passed here as a Symbol or String. Default is:Middleware
.
57 58 59 60 61 62 |
# File 'lib/hoodoo/logger/logger.rb', line 57 def initialize( component = :Middleware ) @level = :debug @pool = Hoodoo::Communicators::Pool.new @component = component @writers = {} end |
Instance Attribute Details
#level ⇒ Object
Return or set the current log level. This is :debug
by default.
189 190 191 |
# File 'lib/hoodoo/logger/logger.rb', line 189 def level @level end |
Instance Method Details
#add(*writer_instances) ⇒ Object
Add a new writer instance to this logger. Example:
file_writer = Hoodoo::Logger::FileWriter.new( 'output.log' )
stdout_writer = Hoodoo::Logger::StreamWriter.new
@logger = Hoodoo::Logger.new
logger.add( file_writer )
logger.add( stdout_writer )
# ...then later...
logger.report( ... ) # -> Sends to "output.log" and $stdout
writer_instances
-
One or more instances of a subclass of Hoodoo::Logger::FastWriter or Hoodoo::Logger::SlowWriter, passed as one or more comma-separated parameters.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/hoodoo/logger/logger.rb', line 83 def add( *writer_instances ) writer_instances.each do | writer_instance | communicator = if writer_instance.is_a?( Hoodoo::Logger::FastWriter ) FastCommunicator.new( writer_instance, self ) elsif writer_instance.is_a?( Hoodoo::Logger::SlowWriter ) SlowCommunicator.new( writer_instance, self ) else raise "Hoodoo::Logger\#add: Only instances of Hoodoo::Logger::FastWriter or Hoodoo::Logger::SlowWriter can be added - #{ writer_instance.class.name } was given" end @pool.add( communicator ) @writers[ writer_instance ] = communicator end end |
#debug(*args) ⇒ Object
Write a debug
log message, provided the log level is :debug
.
The logging data is unstructured, but gets passed to #report for structured logging under the component specified in the constructor and code ‘log’.
Calling #report is recommended over unstructured direct logging.
- *args
-
One or more arguments that will be treated as strings and written in the presented order to the log, each on its own line of output (“\n” terminated).
260 261 262 |
# File 'lib/hoodoo/logger/logger.rb', line 260 def debug( *args ) self.report( :debug, @component, :log, { '_data' => args } ) end |
#error(*args) ⇒ Object
Write an error
log message, regardless of logging level.
The logging data is unstructured, but gets passed to #report for structured logging under the component specified in the constructor and code ‘log’.
Calling #report is recommended over unstructured direct logging.
- *args
-
One or more arguments that will be treated as strings and written in the presented order to the log, each on its own line of output (“\n” terminated).
310 311 312 |
# File 'lib/hoodoo/logger/logger.rb', line 310 def error( *args ) self.report( :error, @component, :log, { '_data' => args } ) end |
#include?(writer_instance) ⇒ Boolean Also known as: includes?
Does this log instance’s collection of writers include the given writer instance? Returns true
if so, else false
.
writer_instance
-
An instance of a subclass of Hoodoo::Logger::FastWriter or Hoodoo::Logger::SlowWriter.
138 139 140 |
# File 'lib/hoodoo/logger/logger.rb', line 138 def include?( writer_instance ) @writers.has_key?( writer_instance ) end |
#include_class?(writer_class) ⇒ Boolean Also known as: includes_class?
Does this log instance’s collection of writers include any writer instances which are of the given writer class? Returns true
if so, else false
.
This is slower than #include? so try to work with writer instance queries rather than writer class queries if you can.
writer_class
-
A subclass (class reference, not instance) of Hoodoo::Logger::FastWriter or Hoodoo::Logger::SlowWriter.
155 156 157 158 159 160 161 |
# File 'lib/hoodoo/logger/logger.rb', line 155 def include_class?( writer_class ) @writers.keys.each do | writer_instance | return true if writer_instance.is_a?( writer_class ) end return false end |
#info(*args) ⇒ Object
Write an info
log message, provided the log level is :debug
or :info
.
The logging data is unstructured, but gets passed to #report for structured logging under the component specified in the constructor and code ‘log’.
Calling #report is recommended over unstructured direct logging.
- *args
-
One or more arguments that will be treated as strings and written in the presented order to the log, each on its own line of output (“\n” terminated).
277 278 279 |
# File 'lib/hoodoo/logger/logger.rb', line 277 def info( *args ) self.report( :info, @component, :log, { '_data' => args } ) end |
#instances ⇒ Object
Returns an array of all log writer instances currently in use, in order of addition. See #add.
168 169 170 171 172 173 174 175 |
# File 'lib/hoodoo/logger/logger.rb', line 168 def instances # Implicit ordering relies on Ruby >= 1.9 documented behaviour of # preserving order of addition to a Hash. # @writers.keys end |
#remove(*writer_instances) ⇒ Object
Remove a writer instance from this logger. If the instance has not been previously added, no error is raised.
Slow writers may take a while to finish processing and shut down in the background. As a result, this method might take a while to return. Internal default timeouts may even mean that the writer is still running (possibly entirely hung).
writer_instances
-
One or more instances of a subclass of Hoodoo::Logger::FastWriter or Hoodoo::Logger::SlowWriter, passed as one or more comma-separated parameters.
111 112 113 114 115 116 117 |
# File 'lib/hoodoo/logger/logger.rb', line 111 def remove( *writer_instances ) writer_instances.each do | writer_instance | communicator = @writers[ writer_instance ] @pool.remove( communicator ) unless communicator.nil? @writers.delete( writer_instance ) end end |
#remove_all ⇒ Object
Remove all writer instances from this logger.
Slow writers may take a while to finish processing and shut down in the background. As a result, this method might take a while to return. Internal default timeouts may even mean that one or more slow writers are still running (possibly entirely hung).
126 127 128 129 |
# File 'lib/hoodoo/logger/logger.rb', line 126 def remove_all @pool.terminate() @writers = {} end |
#report(log_level, component, code, data) ⇒ Object
Logs a message using the structured logger. Whether or not log data is written in a stuctured manner depends upon the writer(s) in use (see #add). Structured writers preserve data structures like hashes or arrays rather than (say) dumping things out as strings into flat output streams.
As with flat logging methods #debug, #info, #warn and #error, a message is only logged if the logging threshold level (see #level=) is set to an equal or lower level.
log_level
-
Log level as a symbol - one of, from most trivial to most severe,
:debug
,:info
,:warn
or:error
. component
-
Component; for example, the resource name for a specific resource endpoint implementation, ‘Middleware’ for Hoodoo middleware itself, or some other name you think is useful. String or Symbol.
code
-
Component-defined code. Think of this in a manner similar to platform error codes, appearing after the “.”; messages related to the same thing should share the same code. The intent is to produce log data that someone can filter on code to get useful information about that specific aspect of a service implementation’s behaviour.
data
-
A Hash containing the level-, component- and code-dependent payload data to be logged.
235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/hoodoo/logger/logger.rb', line 235 def report( log_level, component, code, data ) return unless self.report?( log_level ) @pool.communicate( Payload.new( log_level: log_level, component: component, code: code, data: data ) ) end |
#report?(log_level) ⇒ Boolean
Given the log level configuration of this instance - see #level= and #level - should a message of the given log level be reported? Returns true
if so else false
.
This is mostly for internal use but external callers might find it useful from time to time, especially in tests.
log_level
-
Log level of interest as a Symbol -
debug
,info
,warn
orerror
.
201 202 203 204 205 206 |
# File 'lib/hoodoo/logger/logger.rb', line 201 def report?( log_level ) return false if log_level == :debug && @level != :debug return false if log_level == :info && @level != :debug && @level != :info return false if log_level == :warn && @level != :debug && @level != :info && @level != :warn return true end |
#wait ⇒ Object
Wait for all writers to finish writing all log messages sent up to the point of calling. Internal default timeouts for slow writers mean that hung or extremely slow/backlogged writers may not have finished by the time the call returns, but it’s necessary to enforce a timeout else this call may never return at all.
183 184 185 |
# File 'lib/hoodoo/logger/logger.rb', line 183 def wait @pool.wait() end |
#warn(*args) ⇒ Object
Write a warn
log message, provided the log level is :debug
, :info
or :warn
.
The logging data is unstructured, but gets passed to #report for structured logging under the component specified in the constructor and code ‘log’.
Calling #report is recommended over unstructured direct logging.
- *args
-
One or more arguments that will be treated as strings and written in the presented order to the log, each on its own line of output (“\n” terminated).
294 295 296 |
# File 'lib/hoodoo/logger/logger.rb', line 294 def warn( *args ) self.report( :warn, @component, :log, { '_data' => args } ) end |