1

I use log4r as my logger. I have two questions to the fourum.

  1. I find a mysterious behavior, such that the log messages are printed twice in STDOUT. I don’t understand why it is occurring and how to fix.
  2. I would like to provide color coding for the level tags (FATAL as Red, ERROR as Purple, WARN as Orange, INFO as Green, and so on). This needs to be only effective for STDOUT and no special (meta) character should come to my log file (to make it easy for reading). I tried several attempts but could not achieve this. How to fix?

Following is the detail about my code I use. Please help in fixing this issue.

My YAML configuration is as below: File: yml.cfg


    # *** YAML2LOG4R ***
    log4r_config:
      # define all pre config global log4r settings ...
      pre_config:
        custom_levels:
          - DEBUG2
          - DEBUG
          - PRINT
          - INFO
          - WARN
          - ERROR
          - FATAL
        global:
          level       : ALL 
        root  :
          level       : DEBUG2
          trace       : 'true'

      # define all outputters (stderr, stdout and logfile with custom formatters)
      outputters:
        - type        : StderrOutputter
          name        : stderr 
          level       : ERROR 
          only_at     :
            - ERROR
            - FATAL
          formatter:
            pattern   : '%-7l: %m'
            type      : PatternFormatter

        - type        : StdoutOutputter
          name        : stdout 
          level       : INFO 
          only_at     :
            - INFO
            - WARN
            - ERROR
            - FATAL
          formatter:
            pattern   : '%-7l: %m'
            type      : PatternFormatter

        - type        : FileOutputter
          filename    : debug.log
          name        : logfile
          level       : ALL 
          trace       : 'true'
          trunc       : 'false'
          formatter   :
            type      : MyLogFormatter

      loggers: 

      - name        : MyAppClass
        additive    : 'false'
        trace       : 'true'
        level       : ALL
        outputters  :
             - stderr
             - stdout
             - logfile

I have a log config class (logConfig.rb)

 require 'log4r'
 require 'log4r/lib/yamlconfigurator'

  class LogConfig
    class Log4r::MyLogFormatter < Log4r::Formatter
      def format(event)
        buff = "%-7s: " % Log4r::LNAMES[event.level]
        buff += "(Trace: %-30s): " % [event.tracer[0].split(File::SEPARATOR)[-1]] 
        if event.data.kind_of?(String) then buff += event.data
        elsif event.data.kind_of?(Array) then  buff += "\n\t\t%s : %s\n" % [event.data.class, event.data.inspect] 
        elsif event.data.kind_of?(Hash)  then  buff += "\n\t\t%s : %s\n" % [event.data.class, event.data.inspect] end
        return buff + "\n"
      end
    end # class MyLogFormatter

   def initialize
      cfg = Log4r::YamlConfigurator
      cfg.load_yaml_file('yml.cfg')
      Log4r::StderrOutputter.new 'console'
      Log4r::StdoutOutputter.new 'console'
    end # def initialize

  end # class LogConfig

In my application class (myClass.rb)

  require 'logConfig'
  class MyAppClass
    ClassName = self
    def initialize
      LogConfig.new
      @log = Log4r::Logger["#{ClassName}"]
    end # initialize

    def print_logs
       @log.fatal 'this is fatal'
       @log.error 'this is error'
       @log.warn 'this is warning'
       @log.info 'this is info'
       @log.print 'this is print'
       @log.debug 'this is debug'
       @log.debug2 'this is debug2'
    end
end
MyAppClass.new().print_logs

In debug.log file, I get expected messages properly:

FATAL  : (Trace: myClass.rb:11:in `print_logs' ): this is fatal
ERROR  : (Trace: myClass.rb:12:in `print_logs' ): this is error
WARN   : (Trace: myClass.rb:13:in `print_logs' ): this is warning
INFO   : (Trace: myClass.rb:14:in `print_logs' ): this is info
PRINT  : (Trace: myClass.rb:15:in `print_logs' ): this is print
DEBUG  : (Trace: myClass.rb:16:in `print_logs' ): this is debug
DEBUG2 : (Trace: myClass.rb:17:in `print_logs' ): this is debug2

However, in console (terminal), I get the ERROR and FATAL messages printed twice.

>ruby myClass.rb
FATAL  : this is fatal
FATAL  : this is fatal
ERROR  : this is error
ERROR  : this is error
WARN   : this is warning
INFO   : this is info

Please help resolving above.

user2562153
  • 317
  • 1
  • 3
  • 12

1 Answers1

1

I guess you mentioned the same in config file.

outputters:
        - type        : StderrOutputter
          name        : stderr 
          level       : ERROR 
          only_at     :
            - ERROR
            - FATAL

          - type        : StdoutOutputter
          name        : stdout 
          level       : INFO 
          only_at     :
            - INFO
            - WARN
            - ERROR
            - FATAL



          - type        : FileOutputter
          filename    : debug.log
          name        : logfile
          level       : ALL 
          trace       : 'true'
          trunc       : 'false'

Error and Fatal should be printed for for both stdout and stderr outputters.

and in console you are asking both stdout and stderr prints

      Log4r::StderrOutputter.new 'console'
      Log4r::StdoutOutputter.new 'console'

Just remove error and fatal in stdout of config file then the two prints will disappear. So for fatal or errors it will take stderr and for info and warn it will use stdout.

As far as colours are concerned you can use http://rubygems.org/gems/log4r-color instead of just log4r. This is an extension of the log4r gem. Please take a look at Class: Log4r::ColorOutputter

Vamsi Krishna
  • 3,742
  • 4
  • 20
  • 45
  • Thanks @vamsi, I will try out your suggestions. For color output, I use Ruby 1.8.6 and I don't have gem installer (no permission to install). Is it available in zip format, elsewhere? – user2562153 Sep 19 '13 at 17:10
  • log4r-color works great. However, I have two issues. a) I tee the console output to a log file. If I do so, the coloring doesn't happen. How do I have both color output at console, well as message gets recorded in a file. I tried adding `:filename => 'console.log'`, it doesn't help. B) How do I colorize only the level (not entire text)? – user2562153 Sep 19 '13 at 18:15
  • You can add your own color codes to the log message format. These will then also be written to files (which usually is not desired). You can colorize plain output via ack like this: http://powdahound.com/2009/10/colorize-log-output-with-ack – mmlac Dec 01 '13 at 09:19