require 'logger'
# A simple extension of the Ruby logger. Mainly for
# compatibility purposes.
#
# === Convention
#
# When using debug level logger messages always append 'if $DBG'
# at the end. This hack is needed because Ruby does not support
# lazy evaluation (lisp macros).
#--
# THINK: some people think, this extension is dangerous,
# investigate.
#++
class Logger
alias_method :devel, :debug
alias_method :fine, :debug
# Prints a trace message to DEBUGLOG (at debug level).
# Useful for emitting the value of variables, etc. Use
# like this:
#
# x = y = 5
# trace 'x' # -> 'x = 5'
# trace 'x ** y' # -> 'x ** y = 3125'
#
# If you have a more complicated value, like an array of
# hashes, then you'll probably want to use an alternative
# output format. For instance:
#
# trace 'value', :yaml
#
# Valid output format values (the _style_ parameter) are:
#
# :p :inspect
# :pp (pretty-print, using 'pp' library)
# :s :to_s
# :y :yaml :to_yaml (using the 'yaml' library')
#
# The default is :p.
#
# CREDITS:
#
# This code comes straight from the dev-utils Gem.
# Author: Gavin Sinclair
def trace(expr, style=:p)
unless expr.respond_to? :to_str
warn "trace: Can't evaluate the given value: #{caller.first}"
else
require 'facet/binding/self/of_caller'
Binding.of_caller do |b|
value = b.eval(expr.to_str)
formatter = TRACE_STYLES[style] || :inspect
case formatter
when :pp then require 'pp'
when :y, :yaml, :to_yaml then require 'yaml'
end
value_s = value.send(formatter)
message = "#{expr} = #{value_s}"
lines = message.split(/\n/)
indent = " "
debug(lines.shift)
lines.each do |line|
debug(indent + line)
end
end
end
end
TRACE_STYLES = {} # :nodoc:
TRACE_STYLES.update(
:pp => :pp_s, :s => :to_s, :p => :inspect,
:y => :to_yaml, :yaml => :to_yaml,
:inspect => :inspect, :to_yaml => :to_yaml
)
# Dictate the way in which this logger should format the
# messages it displays. This method requires a block. The
# block should return formatted strings given severity,
# timestamp, msg, progname.
#
# === Example
#
# logger = Logger.new
# logger.setup_format do |severity, timestamp, msg, progname|
# "#{progname}@#{timestamp} - #{severity}::#{msg}"
# end
def setup_format(&format_proc)
raise 'Formating block needed' unless format_proc
@format_proc = format_proc
end
private
# hackish use of *args, give me some love.
alias_method :old_format_message, :format_message # :nodoc:
def format_message(*args) # :nodoc:
@format_proc ? @format_proc.call(*args) : old_format_message(*args)
end
end
# Global logger interface. This provides an alternative
# Singleton interface to the Logger.
class Logger
SIMPLE_FORMAT = "%5s: %s\n"
@@global_logger = Logger.new(STDERR)
@@global_logger.setup_format do |severity, timestamp, progname, msg|
SIMPLE_FORMAT % [severity, msg]
end
# Set the global Logger.
def self.set(logger)
if logger.is_a?(String)
@@global_logger = Logger.new(logger)
@@global_logger.setup_format do |severity, timestamp, progname, msg|
SIMPLE_FORMAT % [severity, msg]
end
elsif logger.is_a?(Logger)
@@global_logger = logger
@@global_logger.setup_format do |severity, timestamp, progname, msg|
SIMPLE_FORMAT % [severity, msg]
end
else
raise ArgumentError.new
end
end
def self.get
@@global_logger
end
def self.warn(str)
@@global_logger.warn(str)
end
def self.info(str)
@@global_logger.info(str)
end
def self.debug(str)
@@global_logger.debug(str)
end
def self.error(str)
@@global_logger.error(str)
end
#--
# Saddly have to duplicate the code to make
# Binding.of_caller work.
#++
def self.trace(expr, style=:p)
unless expr.respond_to? :to_str
warn "trace: Can't evaluate the given value: #{caller.first}"
else
require 'facet/binding/self/of_caller'
Binding.of_caller do |b|
value = eval(expr.to_str, b)
formatter = TRACE_STYLES[style] || :inspect
case formatter
when :pp then require 'pp'
when :y, :yaml, :to_yaml then require 'yaml'
end
value_s = value.send(formatter)
message = "#{expr} = #{value_s}"
lines = message.split(/\n/)
indent = " "
debug(lines.shift)
lines.each do |line|
debug(indent + line)
end
end
end
end
end
module Glue
# UNDER CONSTRUCTION.
#
# Add logging capabilities to the including class.
#
# === Examples
#
# Og.log_info 'Hello' => '[Og] Hello'
# Render.log_info ...
# In Render:
# log_info '...'
module Logging
=begin
def self.included base
[ :info, :debug ].each do |l|
end
end
=end
end
end