views:

303

answers:

1

I must really be missing something obvious, but I'm having trouble with general use of Log4r in my Ruby application. I am able to log without issue, but the overhead seems clunky the way I have it setup. I'm basically passing the full path to a filename to log in each class in my application. The ruby script that is called pulls the log file from one of the arguments in ARGV which is then passed around and set in each class that I call in ruby. In each class I use the patternFormatter to insert the class/file name into the log statement.

Is there a better way to make this work? It feels like no matter what I think of will require something to be passed to each class in my ruby application. I could set the log file in a yaml configuration file instead, but then I would be passing around the configuration file to each class as well.

Any advice? If this doesn't make sense I could try and post some more specific code samples to further explain what I mean.

Thanks!

+1  A: 

Hmm, any reason why you don't instantiate Log4r::Logger class at the beginning of your script and pass the instance around? You don't even have to pass it around, you can always get it by name from Logger class:

run.rb:

require 'log4r'
require 'class_a'

logger = Log4r::Logger.new('test')
logger.outputters << Log4r::Outputter.stdout
logger.outputters << Log4r::FileOutputter.new('logtest', :filename =>  'logtest.log')
logger.info('started script')
a = A.new
a.do_something
logger.info('finishing')

class_a.rb:

class A
  def do_something
    logger = Log4r::Logger['test']
    logger.info('in do_something')
    puts 'hi!'
  end
end

and when you run run.rb you get:

$ ruby run.rb 
 INFO test: started script
 INFO test: in do_something
hi!
 INFO test: finishing

and a log file named logtest.log on disk.

Mladen Jablanović
I can't seem to make that work. The call to Logger['mylog'] in another .rb file returns nil.
Spencer
And how would I tell Logger what file to log out to?
Spencer
Take a look at the updated example above. What do you mean when you say "another .rb file"?
Mladen Jablanović
If you have many connected ruby scripts that do not run in the same instance (such as one script calling another externally, or a batch that runs 10 scripts sequentially) then you will need to instantiate the logger in each script separately.If you are discussing other scripts that you include via 'require', then you may need to create your Log4r instance before requiring these external files, if they log during the first pass through the file (rather than just when they are used later).
Myrddin Emrys
Eureka! Your code example above made it crystal clear Mladen. Now I will just need to figure out how I can change the log tag or whatever you call it that is displayed at the beginning of each line to display the ruby class or filename. But, now I'm off on the right track. Thanks!
Spencer
Well, I figure I may as well continue my logging saga with an add on question. Would there be a better way to get the executing filename into the log file over doing the following in class A's do_something method?logger.info("<#{File.basename(__FILE__)}> in do_something")Note, there are two underscores prefixing/postfixing the word FILE above. It was marked up as bold instead of being displayed.
Spencer
That sounds ok, if you want to log the filename once. If you'd want to print the file name as part of each log message, you'd probably better change the logger's formatter.
Mladen Jablanović
That's my real question, I do not see anything in PatternFormatter that will give me the filename or ruby class that is currently executing/logging. I do not like the prospects of adding '<#{File.basename(FILE)}>' each time I log.
Spencer
Perhaps you should open a new question... :)
Mladen Jablanović