Beispiele und Hinweise zur Nutzung von log4r.rb


Sie sind hier: RubyLoggerlog4r


Übersicht

Mehrfache Ausgabe
Mehrfache Ausgabe mit unterschiedlichem Level
Eigene Level möglich
Abfrage auf Level möglich?
Format definierbar
Tracing möglich?
Verhalten bei Logfiles overwrite
URL des Rubyforge-Projekts log4r

Ausgabeziele:

Vorhandene Level:

Weitere URLS:

Weitere Möglichkeiten:

Coding-Beispiele

Beispiel 1: Logger auf STDOUT

require 'rubygems' 
require 'log4r' 
include Log4r

log = Logger.new('my_log')
log.outputters = StdoutOutputter.new('log_stdout', :level => WARN )
log.debug("just a debug message") 
log.info("important information") 
log.warn("you better be prepared") 
log.error("now you are in trouble") 
log.fatal("this is the end...")

Ausgabe des Loggers log_stdout

        WARN my_log: you better be prepared
    ERROR my_log: now you are in trouble
    FATAL my_log: this is the end...

Beispiel 2: Logger in Datei

require 'rubygems' 
require 'log4r' 
include Log4r 

log = Logger.new('my_log')
log.outputters = FileOutputter.new('log_warn', :filename => "test_log4r_file.log", :level => WARN )
log.debug("just a debug message") 
log.info("important information") 
log.warn("you better be prepared") 
log.error("now you are in trouble") 
log.fatal("this is the end...")

Ausgabe des Loggers log_warn (File)

 WARN my_log: you better be prepared
ERROR my_log: now you are in trouble
FATAL my_log: this is the end...

Beispiel 2b: Logger in Datei/Anhängen

Per Standard wird die Log-Datei jeweils neu erstellt, bisherige Log-Daten werden überschrieben.

Mit der Option :trunc ⇒ false werden neue Log-Daten an ein existierendes Logfile angehängt.

require 'rubygems' 
require 'log4r' 
include Log4r 

log = Logger.new('my_log')
log.outputters = FileOutputter.new('log_warn', :filename => "test_log4r_file_trunc_false.log", 
        :level => WARN,
        :trunc  => false  #log info attached
)
log.add(FileOutputter.new('log_warn', :filename => "test_log4r_file_trunc_true.log", 
        :level => WARN,
        :trunc => true        
))

1.upto(100){|i|
  log.warn("Warning number #{i}") 
}

Korrektur: Der Default-Wert der trunc-Option ist Versionsabhängig.

Beispiel 2c: Logger in Datei mit max. Größe und Alter

Eine Unterklasse von FileOutputter erlaubt die Begrenzung auf eine maximale Dateigröße und Alter einer Log-Datei.

Bei erreichen der Grenze (max. Größe in Byte oder Alter in Sekunden) wird die Log-Datei geschlossen und eine neue angelegt. Die jeweiligen Log-Dateien sind durchnummeriert.

require 'rubygems' 
require 'log4r' 
include Log4r 

log = Logger.new('my_log')
log.outputters = FileOutputter.new('log_warn', :filename => "test_log4r_file_rollingfile.log", 
        :level => WARN
)
log.add(RollingFileOutputter.new('log_warn', :filename => "test_log4r_file_rollingfile_maxsize.log", 
        :level => WARN,
        :maxsize  => 1024 #Maximum size of the file in bytes
))
log.add(RollingFileOutputter.new('log_warn', :filename => "test_log4r_file_rollingfile_trunc.log", 
        :level => WARN,
        :maxtime  => 42 #Maximum age of the file in seconds
))
1.upto(100){|i|
  log.warn("Warning number #{i}") 
}

Beispiel 3: Mehrere gleichzeitige Loggerausgaben

Die mehrfache Ausgabe eines Logs kann sinnvoll sein. Fehler (ERROR und FATAL) werden beim Programmablauf ausgegeben (STDOUT), gleichzeitig werden in einer Datei zusätzlich die Warnungen, Informationen und Debughinweise gespeichert.

require 'rubygems' 
require 'log4r' 
include Log4r 

log = Logger.new('my_log')
log.outputters = StdoutOutputter.new('log_stdout', :level => ERROR )
log.add(FileOutputter.new('log_warn', :filename => "test_log4r_multi_warn.log", :level => WARN ) )
log.add(FileOutputter.new('log_info', :filename => "test_log4r_multi_info.log", :level => INFO)  )

log.debug("just a debug message") 
log.info("important information") 
log.warn("you better be prepared") 
log.error("now you are in trouble") 
log.fatal("this is the end...")

Hinweise:

Ausgabe des Loggers log_stdout

    ERROR my_log: now you are in trouble
    FATAL my_log: this is the end...

Ausgabe des Loggers log_warn (File)

 WARN my_log: you better be prepared
ERROR my_log: now you are in trouble
FATAL my_log: this is the end...

Ausgabe des Loggers log_info (File)

 INFO my_log: important information
 WARN my_log: you better be prepared
ERROR my_log: now you are in trouble
FATAL my_log: this is the end...

Beispiel 4: Logger mit Trace-Information

Was nützt ein Log-File, wenn man anschliessend nicht weiß, woher das Problem stammt? Die Lösung: Ausgeben, wo die log-Information ermittelt wird

require 'rubygems' 
require 'log4r' 
include Log4r 

log = Logger.new('my_log')
log.trace = true
log.outputters = StdoutOutputter.new('log_stdout', :level => WARN )
log.debug("just a debug message") 
log.info("important information") 
log.warn("you better be prepared") 
log.error("now you are in trouble") 
log.fatal("this is the end...")

Beispiel 5: Logger mit Level

Die Ausgabe des Loggers erfordert evtl. viel Aufwand (=Rechenzeit). Man denke blos an komplexe Strukturen, die im Logger protokolliert werden sollen.

Zur Einsparung von Laufzeit bietet es sich an, den Logger nur dann zu rufen, wenn das entsprechende Level überhaupt verwendet wird.

require 'rubygems' 
require 'log4r' 
include Log4r 

log = Logger.new('my_log')
log.level = ERROR
log.outputters = StdoutOutputter.new('log_stdout', :level => WARN )

puts "log.debug?: #{log.debug?}"
puts "log.info?: #{log.info?}"
puts "log.warn?: #{log.warn?}"
puts "log.error?: #{log.error?}"
puts "log.fatal?: #{log.fatal?}"

log.debug("just a debug message") if log.debug?
log.info("important information") if log.info?
log.warn("you better be prepared") if log.warn?
log.warn("a warning without a 'if' afterwords")
log.error("now you are in trouble") if log.error?
log.fatal("this is the end...") if log.fatal?

Ausgabe des Loggers mit Trace

        WARN my_log(test_log4r_trace.rb:10): you better be prepared
    ERROR my_log(test_log4r_trace.rb:11): now you are in trouble
    FATAL my_log(test_log4r_trace.rb:12): this is the end...

Ausgabe des Loggers mit level

    ERROR my_log: now you are in trouble
    FATAL my_log: this is the end...
    log.debug?: false
    log.info?: false
    log.warn?: false
    log.error?: true
    log.fatal?: true
    ERROR my_log: now you are in trouble
    FATAL my_log: this is the end...

Anmerkungen:

Beispiel 6: Tempfile

Bei Bedarf kann die Ausgabe auch in temporäre Dateien umgeleitet werden.

require 'rubygems' 
require 'log4r' 
include Log4r 

require 'tempfile' 
logfile = Tempfile.new("xxx_warn.log")

log = Logger.new('my_log')
log.outputters = Log4r::IOOutputter.new('log_xxx', logfile, :level => WARN )
log.debug("just a debug message") 
log.info("important information") 
log.warn("you better be prepared") 
log.error("now you are in trouble") 
log.fatal("this is the end...")

logfile.close()
logfile.open()
puts logfile.readlines()
logfile.close(true)

Formatter

Mit Hilfe von Formatters ist es möglich, die Ausgabe des Loggers anzupassen.

Beispiel: Simple Formatter

require 'rubygems' 
require 'log4r' 
include Log4r 

log = Logger.new('my_log')
log.trace = true
log.outputters =  FileOutputter.new('log_format', 
                              :filename => 'test_log4r_formatter_simple.log',
                              :level      => WARN, 
                              :formatter => Log4r::SimpleFormatter 
                            )
log.debug("just a debug message") 
log.info("important information") 
log.warn("you better be prepared") 
log.error("now you are in trouble") 
log.fatal("this is the end...")

Ein Trace wird nicht unterstützt!

Ausgabe des Loggers mit allen trace-Ebenen

 WARN my_log> you better be prepared
ERROR my_log> now you are in trouble
FATAL my_log> this is the end...

Beispiel: Basic Formatter

Der Basic-Formatter ist zugleich der Default-Formatter.

require 'rubygems' 
require 'log4r' 
include Log4r 

log = Logger.new('my_log')
log.trace = true
log.outputters =  FileOutputter.new('log_format', 
                              :filename => 'test_log4r_formatter_basic.log',
                              :level      => WARN, 
                              :formatter => Log4r::BasicFormatter 
                            )
log.debug("just a debug message") 
log.info("important information") 
log.warn("you better be prepared") 
log.error("now you are in trouble") 
log.fatal("this is the end...")

Ausgabe des Loggers mit allen trace-Ebenen

 WARN my_log(./test_log4r_formatter_basic.rb:14): you better be prepared
ERROR my_log(./test_log4r_formatter_basic.rb:15): now you are in trouble
FATAL my_log(./test_log4r_formatter_basic.rb:16): this is the end...

Beispiel: Änderung des Formatters

Je nach Anwendung liegt ein Fehler nicht an der Stelle, an der das Problem auftritt, sondern an einem Aufruf vorher. Da kann es sinnvoll sein, den kompletten Aufrufpfad zu nutzen.

Zur Realisierung bietet es sich an, einen eigenen Formatter zu definieren.

require 'rubygems' 
require 'log4r' 
include Log4r 

class Log4r::LevelFormatter < Log4r::BasicFormatter
    #Use another log-format with the complete trace path
    def format(event)
      buff = sprintf(@@basicformat, MaxLevelLength, LNAMES[event.level],
             event.name)
      #~ buff += (event.tracer.nil? ? "" : "(#{event.tracer[2]})") + ": "
      buff += ": "
      buff += format_object(event.data) 
      buff += (event.tracer.nil? ? "" : " (#{event.tracer.join('/')})")
      buff += "\n"
      buff
    end
end

def test()
  log = Logger.new('my_log')
  log.trace = true
  log.outputters =  FileOutputter.new('log_format', 
                                :filename => 'test_log4r_formatter.log',
                                :level      => WARN, 
                                :formatter => Log4r::LevelFormatter 
                              )
  log.debug("just a debug message") 
  log.info("important information") 
  log.warn("you better be prepared") 
  log.error("now you are in trouble") 
  log.fatal("this is the end...")
end

def test2()
  test
end

def test3()
  test2
end

test3

Ausgabe des Loggers mit allen trace-Ebenen

 WARN my_log: you better be prepared (./test_log4r_formatter.rb:30:in `test'/./test_log4r_formatter.rb:36:in `test2'/./test_log4r_formatter.rb:40:in `test3'/./test_log4r_formatter.rb:43/c:/program files/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'/c:/program files/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'/log4r.wiki.rb:13)
ERROR my_log: now you are in trouble (./test_log4r_formatter.rb:31:in `test'/./test_log4r_formatter.rb:36:in `test2'/./test_log4r_formatter.rb:40:in `test3'/./test_log4r_formatter.rb:43/c:/program files/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'/c:/program files/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'/log4r.wiki.rb:13)
FATAL my_log: this is the end... (./test_log4r_formatter.rb:32:in `test'/./test_log4r_formatter.rb:36:in `test2'/./test_log4r_formatter.rb:40:in `test3'/./test_log4r_formatter.rb:43/c:/program files/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'/c:/program files/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'/log4r.wiki.rb:13)

Weitere Hinweise

Logger-Ebenen

Es ist möglich verschiedene eigene Levels anzugeben. Die verschiedenen Levels werden dynamisch generiert.

Ein Seiteneffekt davon ist, das Log4r::INFO u.Co. erst nach dem erzeugen des Loggers zur Verfügung stehen.

Werden die Konstanten vorab benötigt, kann man sie selbst erzeugen mit:

                    Log4r.define_levels(*Log4r::Log4rConfig::LogLevels) #Generieren  Log4r::INFO u.Co.

Loglevels-Konstanten

Verwendet man Log4r::INFO und bekommt man die Fehlermeldung, das die Konstante nicht definiert ist:

Es muss erst ein Logger definiert sein. Die Konstanten werden dynamisch generiert.

Weblinks