From: Jim C. <jc...@di...> - 2002-12-27 21:00:28
|
Folks, nice module - easy to use and powerful / flexible. The only problem Ive encountered is trying to get something like this to work - log4j.appender.LOGFILE.filename=$ENV{APP_ROOT}/logs/rootlog The code is installed into different places on several machines, and its a bit of a hassle to fix the config file accordingly as I propagate code off my development box. I tried this - hoping the layoutpattern tricks would work here, but no joy - log4j.appender.LOGFILE.filename= sub {return "$ENV{APP_ROOT}/logs/rootlog"} Also, for what its worth, Ive disregarded your warnings (sort of): However, be careful, don't go overboard: if you're devel oping a system in object-oriented style, using the class hierarchy is usually your best choice. Think about the people taking over your code one day: The class hierarchy is probably what they know right up front, so it's easy for them to tune the logging to their needs. Ive written a wrapper (myLogger) which uses AUTOLOAD to delegate calls like myLogger->debug(@args) to Log::Log4perl. AUTOLOAD constructs a category dynamically, then tests it before logging it, # use FQ name as category my ($pkg,$file,$ln,$sub) = caller(my $i=1); # once had stackwalk, to get past '(eval)' my $cat = "$sub_$meth_$ln"; my $log = Log::Log4perl->get_logger($cat); my $predicate = "is_$cat"; # is it runnable ? eval { $runnable = $log->$predicate() }; if ($@) { carp("logger: cant $meth on $cat: $@"); return; } else { $seenCat{$cat}++ } if ($runnable) { # Dump arrays or refs eval { @p = shift @_ while @_ and not ref $_[0]; pop @_ while @_ and not $_[$#_]; $log->$meth(Data::Dumper->Dump([\@_],["@p"])) if @_; $log->$meth(@p) if ! @_; }; if ($@) { carp("logger dump problem on $sub.$ln") } } return; This gives me extraordinary control over the logging - I can turn logging on/off at any level - even down to line-number; something like: log4j.category.GwApi=DEBUG log4j.category.GwApi._precond=INFO # these both warn of interface violation log4j.category.GwApi._required.notice=ERROR log4j.category.GwApi._precond.notice=ERROR # but.. # above suppresses a notice-level message by raising # the logging threshold above it # precondition check. Ive seen enough of them.. #log4j.category.GwApi._precond.info.181=WARN Also, AUTOLOAD uuses Data::Dumper to print data-structures when @_ are refs its a cheap (programmer-time) way to get a lot of context in the logs. <441688> GwApi.AUTOLOAD.info: $screen yielded: = [ bless( { 'Buf' => [], 'Cmd' => undef, 'Id' => 10, 'Vals' => {}, 'response' => bless( do{\(my $o = ' 0')}, 'TnResponse' ), 'session' => bless( { '1024' => '1024', 'host' => 'localhost', 'resp' => bless( do{\(my $o = 'U U U C(localhost) I 2 24 80 0 0 0x2e00028 1')}, 'TnResponse' ), 'win' => bless( \*Symbol::GEN6, 'Expect' ) }, 'TnSession' ) }, 'TirksScreen' ) ]; Finally - given that line-numbers are a clumsy way of controlling output (better done by super-category) I thought it would be good to catalog all invoations encountered in a given run of the sw, which should be written out to a file written at process end. This would be useful for assessing the coverage of a test case/suite. Its not working yet (probly should be in an END block), but you can see the direction. sub DESTROY { print "# observed logging categories:\n", Dumper \%seenCat; } |