#!/usr/bin/ruby require 'logger' require 'erb' require 'bigdecimal' require 'date' require 'treequel' require 'treequel/mixins' module Treequel # A alternate formatter for Logger instances. # @private class LogFormatter < Logger::Formatter # The format to output unless debugging is turned on DEFAULT_FORMAT = "[%1$s.%2$06d %3$d/%4$s] %5$5s -- %7$s\n" # The format to output if debugging is turned on DEFAULT_DEBUG_FORMAT = "[%1$s.%2$06d %3$d/%4$s] %5$5s {%6$s} -- %7$s\n" ### Initialize the formatter with a reference to the logger so it can check for log level. def initialize( logger, format=DEFAULT_FORMAT, debug=DEFAULT_DEBUG_FORMAT ) # :notnew: @logger = logger @format = format @debug_format = debug super() end ###### public ###### # The Logger object associated with the formatter attr_accessor :logger # The logging format string attr_accessor :format # The logging format string that's used when outputting in debug mode attr_accessor :debug_format ### Log using either the DEBUG_FORMAT if the associated logger is at ::DEBUG level or ### using FORMAT if it's anything less verbose. def call( severity, time, progname, msg ) args = [ time.strftime( '%Y-%m-%d %H:%M:%S' ), # %1$s time.usec, # %2$d Process.pid, # %3$d Thread.current == Thread.main ? 'main' : Thread.object_id, # %4$s severity, # %5$s progname, # %6$s msg # %7$s ] if @logger.level == Logger::DEBUG return self.debug_format % args else return self.format % args end end end # class LogFormatter # A ANSI-colorized formatter for Logger instances. # @private class ColorLogFormatter < Logger::Formatter extend Treequel::ANSIColorUtilities # Color settings LEVEL_FORMATS = { :debug => colorize( :bold, :black ) {"[%1$s.%2$06d %3$d/%4$s] %5$5s {%6$s} -- %7$s\n"}, :info => colorize( :normal ) {"[%1$s.%2$06d %3$d/%4$s] %5$5s -- %7$s\n"}, :warn => colorize( :bold, :yellow ) {"[%1$s.%2$06d %3$d/%4$s] %5$5s -- %7$s\n"}, :error => colorize( :red ) {"[%1$s.%2$06d %3$d/%4$s] %5$5s -- %7$s\n"}, :fatal => colorize( :bold, :red, :on_white ) {"[%1$s.%2$06d %3$d/%4$s] %5$5s -- %7$s\n"}, } ### Initialize the formatter with a reference to the logger so it can check for log level. def initialize( logger, settings={} ) # :notnew: settings = LEVEL_FORMATS.merge( settings ) @logger = logger @settings = settings super() end ###### public ###### # The Logger object associated with the formatter attr_accessor :logger # The formats, by level attr_accessor :settings ### Log using the format associated with the severity def call( severity, time, progname, msg ) args = [ time.strftime( '%Y-%m-%d %H:%M:%S' ), # %1$s time.usec, # %2$d Process.pid, # %3$d Thread.current == Thread.main ? 'main' : Thread.object_id, # %4$s severity, # %5$s progname, # %6$s msg # %7$s ] return self.settings[ severity.downcase.to_sym ] % args end end # class LogFormatter # An alternate formatter for Logger instances that outputs +div+ HTML # fragments. # @private class HtmlLogFormatter < Logger::Formatter include ERB::Util # for html_escape() # The default HTML fragment that'll be used as the template for each log message. HTML_LOG_FORMAT = %q{
} ### Override the logging formats with ones that generate HTML fragments def initialize( logger, format=HTML_LOG_FORMAT ) # :notnew: @logger = logger @format = format super() end ###### public ###### # The HTML fragment that will be used as a format() string for the log attr_accessor :format ### Return a log message composed out of the arguments formatted using the ### formatter's format string def call( severity, time, progname, msg ) args = [ time.strftime( '%Y-%m-%d %H:%M:%S' ), # %1$s time.usec, # %2$d Process.pid, # %3$d Thread.current == Thread.main ? 'main' : Thread.object_id, # %4$s severity.downcase, # %5$s progname, # %6$s html_escape( msg ).gsub(/\n/, '