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:

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.

Namespace
Methods
A
D
E
I
N
R
W
Attributes
[RW] level

Return or set the current log level. This is :debug by default.

Class Public methods
new( component = :Middleware )

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.

# File lib/hoodoo/logger/logger.rb, line 57
def initialize( component = :Middleware )
  @level     = :debug
  @pool      = Hoodoo::Communicators::Pool.new
  @component = component
  @writers   = {}
end
Instance Public methods
add( *writer_instances )

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.

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

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

# File lib/hoodoo/logger/logger.rb, line 260
def debug( *args )
  self.report( :debug, @component, :log, { '_data' => args } )
end
error( *args )

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

# File lib/hoodoo/logger/logger.rb, line 310
def error( *args )
  self.report( :error, @component, :log, { '_data' => args } )
end
include?( writer_instance )

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.

Also aliased as: includes?
# File lib/hoodoo/logger/logger.rb, line 138
def include?( writer_instance )
  @writers.has_key?( writer_instance )
end
include_class?( writer_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.

Also aliased as: includes_class?
# 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
includes?( writer_instance )
Alias for: include?
includes_class?( writer_class )
Alias for: include_class?
info( *args )

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

# File lib/hoodoo/logger/logger.rb, line 277
def info( *args )
  self.report( :info, @component, :log, { '_data' => args } )
end
instances()

Returns an array of all log writer instances currently in use, in order of addition. See add.

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

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.

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

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

# File lib/hoodoo/logger/logger.rb, line 126
def remove_all
  @pool.terminate()
  @writers = {}
end
report( log_level, component, code, data )

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.

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

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 or error.

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

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.

# File lib/hoodoo/logger/logger.rb, line 183
def wait
  @pool.wait()
end
warn( *args )

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

# File lib/hoodoo/logger/logger.rb, line 294
def warn( *args )
  self.report( :warn, @component, :log, { '_data' => args } )
end