class ZTK::Logger

Standard Logging Class

Allows chaining standard Ruby loggers as well as adding extra spice to your log messages. This includes uSec timestamping, PIDs and caller tree details.

This class accepts the same initialize arguments as the Ruby logger class. You can chain multiple loggers together, for example to get an effect of logging to STDOUT and a file simultaneously without having to modify your existing logging statements.

One can override the logging level on the command line with programs that use this library by defining the LOG_LEVEL environment variable to the desired logging level.

@example Override the logging level at runtime

LOG_LEVEL=DEBUG bin/a_ruby_script.rb

@example Typical usage

$logger = ZTK::Logger.new("/dev/null")

$logger.debug { "This is a debug message!" }
$logger.info { "This is a info message!" }
$logger.warn { "This is a warn message!" }
$logger.error { "This is a error message!" }
$logger.fatal { "This is a fatal message!" }

@example Simple logger chaining

logger = ZTK::Logger.new
logger.loggers << ::Logger.new(STDOUT)
logger.loggers << ::Logger.new('test.log')

logger.debug { "This will be written to STDOUT as well as test.log!" }

@example Simple logger chaining

logger = ZTK::Logger.new(STDOUT)
logger.loggers << ::Logger.new('test.log')

logger.debug { "This will be written to STDOUT as well as test.log!" }

@author Zachary Patten <zpatten AT jovelabs DOT io>

Constants

SEVERITIES

Log Levels

Attributes

loggers[RW]

Public Class Methods

new(*args) click to toggle source
Calls superclass method
# File lib/ztk/logger.rb, line 82
def initialize(*args)
  super(::StringIO.new)

  @loggers = Array.new
  if args.count > 0
    @loggers << ::Logger.new(*args)
  end

  @logdev = LogDevice.new(self)

  set_log_level
end

Public Instance Methods

inspect() click to toggle source

Generates a human-readable string about the logger.

# File lib/ztk/logger.rb, line 96
def inspect
  loggers_inspect = @loggers.collect{|logger| logger.instance_variable_get(:@logdev).instance_variable_get(:@dev).inspect }.join(', ')
  "#<#{self.class} loggers=[#{loggers_inspect}]>"
end
level=(value) click to toggle source
# File lib/ztk/logger.rb, line 117
def level=(value)
  @level = value

  @loggers.each { |logger| logger.level = @level }

  value
end
shift(severity, shift=0, &block) click to toggle source

Specialized logging. Logs messages in the same format, except has the option to shift the caller_at position to exposed the proper calling method.

Very useful in situations of class inheritence, for example, where you might have logging statements in a base class, which are inherited by another class. When calling the base class method via the inherited class the log messages will indicate the base class as the caller. While this is technically true it is not always what we want to see in the logs because it is ambigious and does not show us where the call truly originated from.

# File lib/ztk/logger.rb, line 112
def shift(severity, shift=0, &block)
  severity = ZTK::Logger.const_get(severity.to_s.upcase)
  add(severity, nil, nil, shift, &block)
end

Private Instance Methods

add(severity, message=nil, progname=nil, shift=0, &block) click to toggle source

Writes a log message if the current log level is at or below the supplied severity.

@param [Constant] severity Log level severity. @param [String] message Optional message to prefix the log entry with. @param [String] progname Optional name of the program to prefix the log

entry with.

@yieldreturn [String] The block should return the desired log message.

# File lib/ztk/logger.rb, line 150
def add(severity, message=nil, progname=nil, shift=0, &block)
  return if (@level > severity)

  message = block.call if message.nil? && block_given?
  return if message.nil?

  called_by = parse_caller(caller[1+shift])

  message = [message.chomp, progname].flatten.compact.join(": ")
  message = "%19s.%06d|%05d|%5s|%s%s\n" % [Time.now.utc.strftime("%Y-%m-%d|%H:%M:%S"), Time.now.utc.usec, Process.pid, SEVERITIES[severity], called_by, message]

  @logdev.write(ZTK::ANSI.uncolor(message))
  @logdev.respond_to?(:flush) and @logdev.flush

  true
end
parse_caller(at) click to toggle source

Parses caller entries, extracting the file, line number and method.

@param [String] at Entry from the caller Array.

# File lib/ztk/logger.rb, line 131
def parse_caller(at)
  if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
    file = Regexp.last_match[1]
    line = Regexp.last_match[2]
    method = Regexp.last_match[3]
    "#{File.basename(file)}:#{line}:#{method}|"
  else
    ""
  end
end
set_log_level(level=nil) click to toggle source

Sets the log level.

@param [String] level Log level to use.

# File lib/ztk/logger.rb, line 170
def set_log_level(level=nil)
  defined?(Rails) and (default = (Rails.env.production? ? "INFO" : "DEBUG")) or (default = "INFO")
  log_level = (ENV['LOG_LEVEL'] || level || default)
  self.level = ZTK::Logger.const_get(log_level.to_s.upcase)
end