You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(3) |
Aug
(38) |
Sep
(126) |
Oct
(23) |
Nov
(72) |
Dec
(36) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(76) |
Feb
(32) |
Mar
(19) |
Apr
(6) |
May
(54) |
Jun
(40) |
Jul
(45) |
Aug
(35) |
Sep
(51) |
Oct
(67) |
Nov
(10) |
Dec
(50) |
2004 |
Jan
(51) |
Feb
(22) |
Mar
(22) |
Apr
(28) |
May
(53) |
Jun
(99) |
Jul
(38) |
Aug
(49) |
Sep
(23) |
Oct
(29) |
Nov
(30) |
Dec
(48) |
2005 |
Jan
(15) |
Feb
(21) |
Mar
(25) |
Apr
(16) |
May
(131) |
Jun
|
Jul
(8) |
Aug
(5) |
Sep
(15) |
Oct
|
Nov
(15) |
Dec
(12) |
2006 |
Jan
(15) |
Feb
(20) |
Mar
(8) |
Apr
(10) |
May
(3) |
Jun
(16) |
Jul
(15) |
Aug
(11) |
Sep
(17) |
Oct
(27) |
Nov
(11) |
Dec
(12) |
2007 |
Jan
(19) |
Feb
(18) |
Mar
(33) |
Apr
(4) |
May
(15) |
Jun
(22) |
Jul
(19) |
Aug
(20) |
Sep
(14) |
Oct
(4) |
Nov
(34) |
Dec
(11) |
2008 |
Jan
(8) |
Feb
(18) |
Mar
(2) |
Apr
(4) |
May
(26) |
Jun
(9) |
Jul
(8) |
Aug
(8) |
Sep
(3) |
Oct
(17) |
Nov
(14) |
Dec
(4) |
2009 |
Jan
(6) |
Feb
(41) |
Mar
(21) |
Apr
(10) |
May
(21) |
Jun
|
Jul
(8) |
Aug
(4) |
Sep
(3) |
Oct
(8) |
Nov
(6) |
Dec
(5) |
2010 |
Jan
(14) |
Feb
(13) |
Mar
(7) |
Apr
(12) |
May
(4) |
Jun
(1) |
Jul
(11) |
Aug
(5) |
Sep
|
Oct
(1) |
Nov
(10) |
Dec
|
2011 |
Jan
(7) |
Feb
(3) |
Mar
(1) |
Apr
(5) |
May
|
Jun
(1) |
Jul
(6) |
Aug
(6) |
Sep
(10) |
Oct
(5) |
Nov
(4) |
Dec
(5) |
2012 |
Jan
(4) |
Feb
(5) |
Mar
(1) |
Apr
(7) |
May
(1) |
Jun
|
Jul
(2) |
Aug
|
Sep
(5) |
Oct
(5) |
Nov
(4) |
Dec
(5) |
2013 |
Jan
(6) |
Feb
|
Mar
(14) |
Apr
(9) |
May
(3) |
Jun
(2) |
Jul
(1) |
Aug
(1) |
Sep
|
Oct
|
Nov
(4) |
Dec
(6) |
2014 |
Jan
|
Feb
(1) |
Mar
(10) |
Apr
|
May
(3) |
Jun
|
Jul
|
Aug
|
Sep
(4) |
Oct
(1) |
Nov
|
Dec
(4) |
2015 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2016 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
From: Mike S. <msc...@ao...> - 2002-12-11 18:56:27
|
ke...@go... wrote: > That looks like a good solution to me, anybody else have any thoughts? > That effectively works around the problem of having to retrieve the appender by name and making sure it still exists due to config reloads etc. ... I like it! Maybe config values should be generally settable via callbacks into Perl? -- -- Mike Mike Schilli log...@pe... > > Kai Poitschke wrote: > >> Hi, >> how about a construct like this in the config file? >> >> log4perl.appender.File.filename = sub { return GetLogflleName(); } >> >> Kai >> >> >> On Thursday 05 December 2002 20:20, Duncan Cameron wrote: >> >>> On 2002-12-03 Mike Schilli <msc...@ao...> wrote: >>> >>>> Hi there, >>>> >>>> Kai Poitschke has brought up an interestingfeature request: Suppose, >>>> your application had a configuration "-l logfilename" option to >>>> specify >>>> the name of the log file to be used. Now, if you have an external >>>> configuration file (as opposed to a string ref passed to init()), how >>>> would you be able to adapt the config file setting in the code? >>>> >>>> He suggests to have init() overwrite certain properties of the config >>>> file like in: >>>> >>>> Dump2OWH.conf: >>>> >>>> log4perl.category.Dump2OWH = INFO, File, Screen >>>> >>>> log4perl.appender.File = Log::Dispatch::File >>>> log4perl.appender.File.filename = Dump2OWH.log >>>> log4perl.appender.File.mode = write >>>> log4perl.appender.File.layout = >>>> Log::Log4perl::Layout::PatternLayout >>>> log4perl.appender.File.layout.ConversionPattern = %d: %m%n >>>> >>>> log4perl.appender.Screen = Log::Dispatch::Screen >>>> log4perl.appender.Screen.stderr = 0 >>>> log4perl.appender.Screen.layout = >>>> Log::Log4perl::Layout::PatternLayout >>>> log4perl.appender.Screen.layout.ConversionPattern = %-5p> %m%n >>>> >>>> >>>> test.pl: >>>> # Einstellungen z.B. aus Programmflags bestimmt >>>> $more_conf = q(log4perl.appender.File.filename = test.log >>>> log4perl.appender.File.mode = append); >>>> >>>> Log::Log4perl::init('Dump2OWH.conf', $more_conf); >>>> >>>> >>>> I can see at least one other way to implement it: a >>>> not-yet-implemented-in-Log4perl feature like variables in config files >>>> (log4j has something like that but I don't think they can specify the >>>> variable replacement values via code) and a mechanism to define the >>>> placeholders in init(conf_file, key => value, key => value); >>>> >>>> Any other ideas? Sounds like a pretty useful feature to me. >>> >>> >>> Initially I wondered why I couldn't do something like this: >>> >>> Log::Log4perl::init('Dump2OWH.conf'); >>> my $appender = get_appender('File'); >>> $appender->filename('test.log'); >>> >>> but after investigating found that get_appender is part of the log4j >>> API which hasn't been implemented, Log::Dispatch::File doesn't support >>> get and set methods on its instance variables, and, more importantly, >>> that the output file is opened as part of the creation of the >>> appender during the init(), so it's then too late to change the file >>> name. >>> >>> Regards, >>> Duncan Cameron >>> >>> >>> >>> >>> >>> >>> >>> ------------------------------------------------------- >>> This sf.net email is sponsored by:ThinkGeek >>> Welcome to geek heaven. >>> http://thinkgeek.com/sf >>> _______________________________________________ >>> log4perl-devel mailing list >>> log...@li... >>> https://lists.sourceforge.net/lists/listinfo/log4perl-devel >> |
From: <log...@pe...> - 2002-12-10 23:31:24
|
Welcome to the Log::Log4perl recipe of the week. Today: ============================================================ Log::Log4perl Recipe of the Week (#7): How can I hook up the LWP library with Log::Log4perl? ============================================================ Or, to put it more generally: How can you utilize a third-party library's embedded logging and debug statements in Log::Log4perl? How can you make them print to configurable appenders, turn them on and off, just as if they were regular Log::Log4perl logging statements? The easiest solution is to map the third-party library logging statements to Log::Log4perl's stealth loggers via a typeglob assignment. As an example, let's take LWP, one of the most popular Perl modules, which makes handling WWW requests and responses a breeze. Internally, LWP uses its own logging and debugging system, utilizing the following calls inside the LWP code (from the LWP::Debug man page): # Function tracing LWP::Debug::trace('send()'); # High-granular state in functions LWP::Debug::debug('url ok'); # Data going over the wire LWP::Debug::conns("read $n bytes: $data"); First, let's assign Log::Log4perl priorities to these functions: I'd suggest that "debug()" messages have priority "INFO", "trace()" uses "DEBUG" and "conns()" also logs with "DEBUG" -- although your mileage may certainly vary. Now, in order to transpartently hook up LWP::Debug with Log::Log4perl, all we have to do is say package LWP::Debug; use Log::Log4perl qw(:easy); *trace = *INFO; *conns = *DEBUG; *debug = *DEBUG; package main; # ... go on with your regular program ... at the beginning of our program. In this way, every time the, say, "LWP::UserAgent" module calls "LWP::Debug::trace()", it will implicitely call INFO(), which is the "info()" method of a stealth logger defined for the Log::Log4perl category "LWP::Debug". Is this cool or what? Here's a complete program: use LWP::UserAgent; use HTTP::Request::Common; use Log::Log4perl qw(:easy); Log::Log4perl->easy_init( { category => "LWP::Debug", level => $DEBUG, layout => "%r %p %M-%L %m%n", }); package LWP::Debug; use Log::Log4perl qw(:easy); *trace = *INFO; *conns = *DEBUG; *debug = *DEBUG; package main; my $ua = LWP::UserAgent->new(); my $resp = $ua->request(GET "http://amazon.com"); if($resp->is_success()) { print "Success: Received ", length($resp->content()), "\n"; } else { print "Error: ", $resp->code(), "\n"; } This will generate the following output on STDERR: 174 INFO LWP::UserAgent::new-164 () 208 INFO LWP::UserAgent::request-436 () 211 INFO LWP::UserAgent::send_request-294 GET http://amazon.com 212 DEBUG LWP::UserAgent::_need_proxy-1123 Not proxied 405 INFO LWP::Protocol::http::request-122 () 859 DEBUG LWP::Protocol::collect-206 read 233 bytes 863 DEBUG LWP::UserAgent::request-443 Simple response: Found 869 INFO LWP::UserAgent::request-436 () 871 INFO LWP::UserAgent::send_request-294 GET http://www.amazon.com:80/exec/obidos/gateway_redirect 872 DEBUG LWP::UserAgent::_need_proxy-1123 Not proxied 873 INFO LWP::Protocol::http::request-122 () 1016 DEBUG LWP::UserAgent::request-443 Simple response: Found 1020 INFO LWP::UserAgent::request-436 () 1022 INFO LWP::UserAgent::send_request-294 GET http://www.amazon.com/exec/obidos/subst/home/home.html/ 1023 DEBUG LWP::UserAgent::_need_proxy-1123 Not proxied 1024 INFO LWP::Protocol::http::request-122 () 1382 DEBUG LWP::Protocol::collect-206 read 632 bytes ... 2605 DEBUG LWP::Protocol::collect-206 read 77 bytes 2607 DEBUG LWP::UserAgent::request-443 Simple response: OK Success: Received 42584 Of course, in this way, the embedded logging and debug statements within LWP can be utilized in any Log::Log4perl way you can think of. You can have them sent to different appenders, block them based on the category and everything else Log::Log4perl has to offer. Only drawback of this method: Steering logging behaviour via category is always based on the "LWP::Debug" package. Although the logging statements reflect the package name of the issuing module properly, the stealth loggers in "LWP::Debug" are all of the category "LWP::Debug". This implies that you can't control the logging behaviour based on the package that's *initiating* a log request (e.g. LWP::UserAgent) but only based on the package that's actually *executing* the logging statement, "LWP::Debug" in this case. To work around this conundrum, we need to write a wrapper function and plant it into the "LWP::Debug" package. It will determine the caller and create a logger bound to a category with the same name as the caller's package: package LWP::Debug; use Log::Log4perl qw(:levels get_logger); sub l4p_wrapper { my($prio, @message) = @_; $Log::Log4perl::caller_depth += 2; get_logger(caller(1))->log($prio, @message); $Log::Log4perl::caller_depth -= 2; } no warnings 'redefine'; *trace = sub { l4p_wrapper($INFO, @_); }; *debug = *conns = sub { l4p_wrapper($DEBUG, @_); }; package main; # ... go on with your main program ... This is less performant than the previous approach, because every log request will request a reference to a logger first, then call the wrapper, which will in turn call the appropriate log function. This hierarchy shift has to be compensated for by increasing $Log::Log4perl::caller_depth by 2 before calling the log function and decreasing it by 2 right afterwards. Also, the "l4p_wrapper" function shown above calls caller(1) which determines the name of the package *two* levels down the calling hierarchy (and therefore compensates for both the wrapper function and the anonymous subroutine calling it). "no warnings 'redefine'" suppresses a warning Perl would generate otherwise upon redefining "LWP::Debug"'s "trace()", "debug()" and "conns()" functions. In case you use a perl prior to 5.6.x, you need to manipulate $^W instead. Have fun! Until next week. -- Mike ################################### # Mike Schilli # # log...@pe... # # http://perlmeister.com # # http://log4perl.sourceforge.net # ################################### |
From: Kevin G. <ke...@go...> - 2002-12-10 17:07:26
|
After working with that a little bit, I see it's still missing something, and I see why log4j was appending items to a buffer, because you really want parts of your log message to end up in different columns in the database. This is the kind of API that's wanted, to be able to call $logger->warn( ['schoolteacher',1732,'employee is underpaid!'] ); being set up like this: =================================================== log4j.appender.DBAppndr.sqlStatement = \ insert into log4perltest \ (date,loglevel, employee_type, emp_id, msg) \ values (?,?,?,?,?) log4j.appender.DBAppndr.params.1 = %d log4j.appender.DBAppndr.params.2 = %p # 3 is employee_type # 4 is emp_id log4j.appender.DBAppndr.params.5 = %m #noop layout to pass the arrayref through log4j.appender.DBAppndr.layout = Log::Log4perl::Layout::NoopLayout ================================================== so can can mix bind vales from custom cspecs with array items from your logger call. Being able to pass an arrayref means PatternLayout and SimpleLayout must check for an arrayref and join it if they find one. The NoopLayout is required to have a layout that will leave the arrayref alone. Any thoughts on that? -- Happy Trails . . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510) 525-5217 |
From: Kevin G. <ke...@go...> - 2002-12-10 17:01:41
|
Erik W. Selberg wrote: > (yes, I'm back from the dead :) > > I'll toss in one... it'd be nice if at least the password (if not the > username) could be obtained from environment variables. What we do > around here is we have a reasonably secure script that sets certain > environment variables and give permission to use said script via sudo. > This lets the DBAs keep their passwords under control. Erik, wazzup? Actually, we do almost the same thing here, but with the addition of a module that maps the environment variable switch to dsn/username/pwd combos, so I approached it like this, log4j.appender.DBAppndr = xx::DBLogger log4j.appender.DBAppndr.sqlStatement = \ insert into log4perltest ...etc.\ ============================================= package xx::DBLogger; use base qw(Log::Log4perl::Appender::DBI); use xx::DB; #subclassing the DBI appender to override _init() sub _init { my $self = shift; my %params = @_; #lookup DSN, username, pwd re: ENV $self->{dbh} = xx::DB->new->getConnection or die $DBI::errstr; $self->{_mine} = 1; $self->{sth} = $self->create_statement($params{sqlStatement}); } ======================================================== What do you think of that? Any other ideas? > Now, granted, I'm from the school whereby username / password security > is just dumb for applications because (a) you gotta bake 'em in > somewhere, which means when that hacker roots your box, they can find > it, No doubt, can you say "cat /proc/$$/environ"? > and (b) you can never change both at the same time and therefore you > end up just screwing yourself, but that's just me. :) > > -e > > Kevin Goess wrote: > >> I needed to add logging to a database, here's a proposed solution. >> >> Log4j has a JDBCAppender with the warning: "This version of >> JDBCAppender is very likely to be completely replaced in the future." >> The API is kind of different, you call append() until the buffer is >> full, at which point the an sth is created and executed on the >> buffer. So the API isn't interchangeable with other appenders. >> >> So I've implemented a DBI appender that's completely controllable from >> the config file, looking something like this: >> >> log4j.category = WARN, DBAppndr >> log4j.appender.DBAppndr = Log::Log4perl::Appender::DBI >> log4j.appender.DBAppndr.datasource = DBI:CSV:f_dir=t/tmp >> log4j.appender.DBAppndr.username = bobjones >> log4j.appender.DBAppndr.password = 12345 >> log4j.appender.DBAppndr.sqlStatement = \ >> insert into log4perltest \ >> (level, message, shortmessage) \ >> values (?,?,?) >> log4j.appender.DBAppndr.params.1 = %p >> log4j.appender.DBAppndr.params.2 = %m >> log4j.appender.DBAppndr.params.3 = %5.5m >> ... >> >> The code is based on Log::Dispatch::DBI by Tatsuhiko Miyagawa. His >> module gets behavior changes via subclassing, but by the time I was >> done I had overridden everything but DESTROY, so I just dropped the >> dependency on his module. >> >> Below is the only change to existing code, the module and a unit test >> are attached. Any comments or suggestions? >> >> >> ============================================================ >> --- lib/Log/Log4perl/Appender.pm 18 Nov 2002 20:03:39 >> -0000 1.17 >> +++ lib/Log/Log4perl/Appender.pm 9 Dec 2002 19:51:31 -0000 >> @@ -120,7 +120,10 @@ >> $level, >> 3 + >> $Log::Log4perl::caller_depth, >> ); >> - $self->{appender}->log(%$p); >> + $self->{appender}->log(%$p, >> + #these are used by our Appender::DBI >> + log4p_category => $category, >> + log4p_level => $level,); >> >> return 1; >> } >> >> >> >> ------------------------------------------------------------------------ >> >> package Log::Log4perl::Appender::DBI; >> >> use Carp; >> >> use strict; >> use Log::Log4perl::Layout::PatternLayout; >> >> use base qw(Log::Dispatch::Output); >> >> >> sub new { >> my($proto, %params) = @_; >> my $class = ref $proto || $proto; >> >> my $self = bless {}, $class; >> >> $self->_basic_init(%params); >> $self->_init(%params); >> >> #e.g. >> #log4j.appender.DBAppndr.params.1 = %p >> #log4j.appender.DBAppndr.params.2 = %5.5m >> foreach my $pnum (keys %{$params{params}}){ >> $self->{bind_value_layouts}{$pnum} = >> Log::Log4perl::Layout::PatternLayout->new( >> {ConversionPattern => {value => >> $params{params}->{$pnum}}}); >> >> } >> >> return $self; >> } >> >> >> sub _init { >> my $self = shift; >> my %params = @_; >> >> # set parameters >> if ($params{dbh}) { >> $self->{dbh} = $params{dbh}; >> } else { >> $self->{dbh} = DBI->connect(@params{qw(datasource username >> password)}) >> or die $DBI::errstr; >> $self->{_mine} = 1; >> } >> $self->{sth} = $self->create_statement($params{sqlStatement}); >> } >> >> sub create_statement { >> my ($self, $stmt) = @_; >> >> $stmt || die "sqlStatement not set in Log4perl::Appender::DBI"; >> >> return $self->{dbh}->prepare($stmt); >> } >> >> >> sub log_message { >> my $self = shift; >> my %p = @_; >> >> #params is >> # { name => \$appender_name, >> # level => \$Log::Log4perl::Level::L4P_TO_LD{\$level}, >> # message => \$message, >> # log4p_category => $category, >> # log4p_level => $level,); >> # }, >> >> my @qmarks = (); >> >> foreach my $pnum (keys %{$self->{bind_value_layouts}}){ >> my $msg = $self->{bind_value_layouts}{$pnum}->render( >> $p{message}, >> $p{log4p_category}, >> $p{log4p_level}, >> 5 + $Log::Log4perl::caller_depth, ); >> >> push @qmarks, $msg; >> } >> >> $self->{sth}->execute(@qmarks); >> } >> >> sub DESTROY { >> my $self = shift; >> if ($self->{_mine} && $self->{dbh}) { >> $self->{dbh}->disconnect; >> } >> } >> >> >> 1; >> >> __END__ >> >> =head1 NAME >> >> Log::Log4perl::Appender::DBI - implements appending to a DB >> >> =head1 SYNOPSIS >> >> $dbh->do('CREATE TABLE log4perltest (level char(9), message >> char(128)); >> >> my $config = <<'EOT'; >> log4j.category = WARN, DBAppndr >> log4j.appender.DBAppndr = Log::Log4perl::Appender::DBI >> log4j.appender.DBAppndr.datasource = DBI:CSV:f_dir=t/tmp >> log4j.appender.DBAppndr.username = bobjones >> log4j.appender.DBAppndr.password = 12345 >> log4j.appender.DBAppndr.sqlStatement = \ >> insert into log4perltest \ >> (level, message, shortmessage, category, millis) \ >> values (?,?,?,?,?) >> log4j.appender.DBAppndr.params.1 = %p >> log4j.appender.DBAppndr.params.2 = %m >> log4j.appender.DBAppndr.params.3 = %5.5m >> log4j.appender.DBAppndr.params.4 = %c >> log4j.appender.DBAppndr.params.5 = %C >> #want the pattern layout so we can avoid the \n >> log4j.appender.DBAppndr.layout = Log::Log4perl::Layout::PatternLayout >> log4j.appender.DBAppndr.layout.ConversionPattern = %m >> >> =head1 DESCRIPTION >> >> This is a specialized Log::Dispatch object customized to work with >> log4perl and its abilities. >> >> The code is based on Log::Dispatch::DBI by Tatsuhiko Miyagawa. I was >> going to subclass it, but after I was done overriding, there >> wasn't anything left in the superclass! >> >> This is an attempted compromise between what Log::Dispatch::DBI was >> doing and what log4j's JDBCAppender does. Since the JDBCAppender >> docs say it "is very likely to be completely replaced in the future" >> and since it looks like it does stuff like prepares the sth each time >> around (bad performance?) I didn't feel too bad about straying from >> its example. And the Log::Dispatch::DBI required subclassing >> to change performance, where log4perl is inspired by the power >> of the config file! >> >> =head1 CHANGING DBH CONNECTIONS (POOLING) >> >> If you want to get your dbh from some place in particular, like >> maybe a pool, subclass and override _init() and/or create_statement(), >> q.v. >> >> =head1 LIFE OF CONNECTIONS >> >> This module creates an sth when it starts and keeps it for the life >> of the program. For long-running processes (e.g. mod_perl) this >> may be a problem, your connections may go stale. >> >> It also holds one connection open for every appender, which might >> be too many. >> >> >> =head1 AUTHOR >> >> Kevin Goess <cp...@go...> December, 2002 >> >> =head1 SEE ALSO >> >> L<Log::Dispatch::DBI> >> >> L<Log::Log4perl::JavaMap> >> >> L<Log::Log4perl::JavaMap::JDBCAppender>. >> >> =cut >> >> >> > > > > > > ------------------------------------------------------- > This sf.net email is sponsored by:ThinkGeek > Welcome to geek heaven. > http://thinkgeek.com/sf > _______________________________________________ > log4perl-devel mailing list > log...@li... > https://lists.sourceforge.net/lists/listinfo/log4perl-devel -- Happy Trails . . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510) 525-5217 |
From: Erik W. S. <er...@se...> - 2002-12-10 07:02:57
|
(yes, I'm back from the dead :) I'll toss in one... it'd be nice if at least the password (if not the username) could be obtained from environment variables. What we do around here is we have a reasonably secure script that sets certain environment variables and give permission to use said script via sudo. This lets the DBAs keep their passwords under control. Now, granted, I'm from the school whereby username / password security is just dumb for applications because (a) you gotta bake 'em in somewhere, which means when that hacker roots your box, they can find it, and (b) you can never change both at the same time and therefore you end up just screwing yourself, but that's just me. :) -e Kevin Goess wrote: > I needed to add logging to a database, here's a proposed solution. > > Log4j has a JDBCAppender with the warning: "This version of > JDBCAppender is very likely to be completely replaced in the future." > The API is kind of different, you call append() until the buffer is > full, at which point the an sth is created and executed on the > buffer. So the API isn't interchangeable with other appenders. > > So I've implemented a DBI appender that's completely controllable from > the config file, looking something like this: > > log4j.category = WARN, DBAppndr > log4j.appender.DBAppndr = Log::Log4perl::Appender::DBI > log4j.appender.DBAppndr.datasource = DBI:CSV:f_dir=t/tmp > log4j.appender.DBAppndr.username = bobjones > log4j.appender.DBAppndr.password = 12345 > log4j.appender.DBAppndr.sqlStatement = \ > insert into log4perltest \ > (level, message, shortmessage) \ > values (?,?,?) > log4j.appender.DBAppndr.params.1 = %p > log4j.appender.DBAppndr.params.2 = %m > log4j.appender.DBAppndr.params.3 = %5.5m > ... > > The code is based on Log::Dispatch::DBI by Tatsuhiko Miyagawa. His > module gets behavior changes via subclassing, but by the time I was > done I had overridden everything but DESTROY, so I just dropped the > dependency on his module. > > Below is the only change to existing code, the module and a unit test > are attached. Any comments or suggestions? > > > ============================================================ > --- lib/Log/Log4perl/Appender.pm 18 Nov 2002 20:03:39 > -0000 1.17 > +++ lib/Log/Log4perl/Appender.pm 9 Dec 2002 19:51:31 -0000 > @@ -120,7 +120,10 @@ > $level, > 3 + > $Log::Log4perl::caller_depth, > ); > - $self->{appender}->log(%$p); > + $self->{appender}->log(%$p, > + #these are used by our Appender::DBI > + log4p_category => $category, > + log4p_level => $level,); > > return 1; > } > > > >------------------------------------------------------------------------ > >package Log::Log4perl::Appender::DBI; > >use Carp; > >use strict; >use Log::Log4perl::Layout::PatternLayout; > >use base qw(Log::Dispatch::Output); > > >sub new { > my($proto, %params) = @_; > my $class = ref $proto || $proto; > > my $self = bless {}, $class; > > $self->_basic_init(%params); > $self->_init(%params); > > #e.g. > #log4j.appender.DBAppndr.params.1 = %p > #log4j.appender.DBAppndr.params.2 = %5.5m > foreach my $pnum (keys %{$params{params}}){ > $self->{bind_value_layouts}{$pnum} = > Log::Log4perl::Layout::PatternLayout->new( > {ConversionPattern => {value => $params{params}->{$pnum}}}); > > } > > return $self; >} > > >sub _init { > my $self = shift; > my %params = @_; > > # set parameters > if ($params{dbh}) { > $self->{dbh} = $params{dbh}; > } else { > $self->{dbh} = DBI->connect(@params{qw(datasource username password)}) > or die $DBI::errstr; > $self->{_mine} = 1; > } > $self->{sth} = $self->create_statement($params{sqlStatement}); >} > >sub create_statement { > my ($self, $stmt) = @_; > > $stmt || die "sqlStatement not set in Log4perl::Appender::DBI"; > > return $self->{dbh}->prepare($stmt); >} > > >sub log_message { > my $self = shift; > my %p = @_; > > #params is > # { name => \$appender_name, > # level => \$Log::Log4perl::Level::L4P_TO_LD{\$level}, > # message => \$message, > # log4p_category => $category, > # log4p_level => $level,); > # }, > > my @qmarks = (); > > foreach my $pnum (keys %{$self->{bind_value_layouts}}){ > my $msg = $self->{bind_value_layouts}{$pnum}->render( > $p{message}, > $p{log4p_category}, > $p{log4p_level}, > 5 + $Log::Log4perl::caller_depth, > ); > > push @qmarks, $msg; > } > > $self->{sth}->execute(@qmarks); >} > >sub DESTROY { > my $self = shift; > if ($self->{_mine} && $self->{dbh}) { > $self->{dbh}->disconnect; > } >} > > >1; > >__END__ > >=head1 NAME > >Log::Log4perl::Appender::DBI - implements appending to a DB > >=head1 SYNOPSIS > > $dbh->do('CREATE TABLE log4perltest (level char(9), message char(128)); > > my $config = <<'EOT'; > log4j.category = WARN, DBAppndr > log4j.appender.DBAppndr = Log::Log4perl::Appender::DBI > log4j.appender.DBAppndr.datasource = DBI:CSV:f_dir=t/tmp > log4j.appender.DBAppndr.username = bobjones > log4j.appender.DBAppndr.password = 12345 > log4j.appender.DBAppndr.sqlStatement = \ > insert into log4perltest \ > (level, message, shortmessage, category, millis) \ > values (?,?,?,?,?) > log4j.appender.DBAppndr.params.1 = %p > log4j.appender.DBAppndr.params.2 = %m > log4j.appender.DBAppndr.params.3 = %5.5m > log4j.appender.DBAppndr.params.4 = %c > log4j.appender.DBAppndr.params.5 = %C > > #want the pattern layout so we can avoid the \n > log4j.appender.DBAppndr.layout = Log::Log4perl::Layout::PatternLayout > log4j.appender.DBAppndr.layout.ConversionPattern = %m > >=head1 DESCRIPTION > >This is a specialized Log::Dispatch object customized to work with >log4perl and its abilities. > >The code is based on Log::Dispatch::DBI by Tatsuhiko Miyagawa. I was >going to subclass it, but after I was done overriding, there >wasn't anything left in the superclass! > >This is an attempted compromise between what Log::Dispatch::DBI was >doing and what log4j's JDBCAppender does. Since the JDBCAppender >docs say it "is very likely to be completely replaced in the future" >and since it looks like it does stuff like prepares the sth each time >around (bad performance?) I didn't feel too bad about straying >from its example. And the Log::Dispatch::DBI required subclassing >to change performance, where log4perl is inspired by the power >of the config file! > >=head1 CHANGING DBH CONNECTIONS (POOLING) > >If you want to get your dbh from some place in particular, like >maybe a pool, subclass and override _init() and/or create_statement(), >q.v. > >=head1 LIFE OF CONNECTIONS > >This module creates an sth when it starts and keeps it for the life >of the program. For long-running processes (e.g. mod_perl) this >may be a problem, your connections may go stale. > >It also holds one connection open for every appender, which might >be too many. > > >=head1 AUTHOR > >Kevin Goess <cp...@go...> December, 2002 > >=head1 SEE ALSO > >L<Log::Dispatch::DBI> > >L<Log::Log4perl::JavaMap> > >L<Log::Log4perl::JavaMap::JDBCAppender>. > >=cut > > > |
From: Kevin G. <ke...@go...> - 2002-12-09 19:58:01
|
I needed to add logging to a database, here's a proposed solution. Log4j has a JDBCAppender with the warning: "This version of JDBCAppender is very likely to be completely replaced in the future." The API is kind of different, you call append() until the buffer is full, at which point the an sth is created and executed on the buffer. So the API isn't interchangeable with other appenders. So I've implemented a DBI appender that's completely controllable from the config file, looking something like this: log4j.category = WARN, DBAppndr log4j.appender.DBAppndr = Log::Log4perl::Appender::DBI log4j.appender.DBAppndr.datasource = DBI:CSV:f_dir=t/tmp log4j.appender.DBAppndr.username = bobjones log4j.appender.DBAppndr.password = 12345 log4j.appender.DBAppndr.sqlStatement = \ insert into log4perltest \ (level, message, shortmessage) \ values (?,?,?) log4j.appender.DBAppndr.params.1 = %p log4j.appender.DBAppndr.params.2 = %m log4j.appender.DBAppndr.params.3 = %5.5m ... The code is based on Log::Dispatch::DBI by Tatsuhiko Miyagawa. His module gets behavior changes via subclassing, but by the time I was done I had overridden everything but DESTROY, so I just dropped the dependency on his module. Below is the only change to existing code, the module and a unit test are attached. Any comments or suggestions? ============================================================ --- lib/Log/Log4perl/Appender.pm 18 Nov 2002 20:03:39 -0000 1.17 +++ lib/Log/Log4perl/Appender.pm 9 Dec 2002 19:51:31 -0000 @@ -120,7 +120,10 @@ $level, 3 + $Log::Log4perl::caller_depth, ); - $self->{appender}->log(%$p); + $self->{appender}->log(%$p, + #these are used by our Appender::DBI + log4p_category => $category, + log4p_level => $level,); return 1; } -- Happy Trails . . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510) 525-5217 |
From: Kevin G. <ke...@go...> - 2002-12-09 19:41:27
|
Ceki's answer is that they did it that way for the sake of simplicity. Here's my proposal, we change log4perl to match log4j's behavior where the appender fires for each category as it climbs back up the tree... ...and then we parameterize it so if for whatever reason someone only wants to see the message once, then they can have the original log4perl behavior of not duplicating the message, with a config line like this: log4j.oneMessagePerAppender = 1 That's already implemented in the v.27 code. Any comments? Duncan Cameron wrote: > On 2002-11-30 Kevin Goess <ke...@go...> wrote: > > >>I finally got a few minutes to think about log4perl today, and was >>looking at my TODO list in the changes file: >> >>* Bug: If the *same* appender is being attached to several loggers, >> appender inheritance doesn't work as expected: Even if the >> appender appears twice in the inheritance tree, it's only executed >>once. >> But it actually needs to be run twice to match log4j. >> >>For our behavior (attached perl) to match the log4j behavior (attached >>java) on the (attached config), I would have to make the change >>(attached diff). >> >>The only unit tests it messes with is 012Deeper.t, which is where it >>would be expected. So this would change the behavior of our libraries, >>in that if you have an appender attached to plant and also to >>plant.tree.leaf, a log message to plant.tree.leaf or below will fire the >>appender twice, currently it only does it once (I believe that behavior >>seemed more appropriate at the time). >> >>Any comments before I make the change to bring us into conformity with >>log4j? > > > I've been trying to understand why firing the appender twice is either > a good thing or not a good thing. In your example, I wonder what the > user is trying to achieve by having the appender attached to both > plant and plant.tree.leaf? > > Firing all appenders, regardless of number of occurences sounds > simple, but equally why would one want a log message to appear > multiple times in the same appender? > > Do you know what the original log4j rationale was? > >>RCS file: /cvsroot/log4perl/Log-Log4perl/lib/Log/Log4perl/Logger.pm,v >>retrieving revision 1.39 >>diff -u -r1.39 Logger.pm >>--- lib/Log/Log4perl/Logger.pm 18 Nov 2002 05:34:47 -0000 1.39 >>+++ lib/Log/Log4perl/Logger.pm 30 Nov 2002 00:09:31 -0000 >>@@ -126,8 +126,9 @@ >> >> foreach my $appender_name (@{$logger->{appender_names}}){ >> >>- #only one message per appender, please >>- next if $seen{$appender_name} ++; >>+ #actually, log4j behavior the appender should >>+ #fire each time it's called >>+ #next if $seen{$appender_name} ++; >> >> push (@appenders, >> [$appender_name, >> > > The %seen hash can be removed entirely. Is it usual to comment out > code rather than remove it? > > Regards, > Duncan Cameron > > > > > > > > ------------------------------------------------------- > This SF.net email is sponsored by: Get the new Palm Tungsten T > handheld. Power & Color in a compact size! > http://ads.sourceforge.net/cgi-bin/redirect.pl?palm0002en > _______________________________________________ > log4perl-devel mailing list > log...@li... > https://lists.sourceforge.net/lists/listinfo/log4perl-devel -- Happy Trails . . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510) 525-5217 |
From: Kevin G. <ke...@go...> - 2002-12-09 19:34:49
|
That looks like a good solution to me, anybody else have any thoughts? Kai Poitschke wrote: > Hi, > how about a construct like this in the config file? > > log4perl.appender.File.filename = sub { return GetLogflleName(); } > > Kai > > > On Thursday 05 December 2002 20:20, Duncan Cameron wrote: > >>On 2002-12-03 Mike Schilli <msc...@ao...> wrote: >> >>>Hi there, >>> >>>Kai Poitschke has brought up an interestingfeature request: Suppose, >>>your application had a configuration "-l logfilename" option to specify >>>the name of the log file to be used. Now, if you have an external >>>configuration file (as opposed to a string ref passed to init()), how >>>would you be able to adapt the config file setting in the code? >>> >>>He suggests to have init() overwrite certain properties of the config >>>file like in: >>> >>>Dump2OWH.conf: >>> >>>log4perl.category.Dump2OWH = INFO, File, Screen >>> >>>log4perl.appender.File = Log::Dispatch::File >>>log4perl.appender.File.filename = Dump2OWH.log >>>log4perl.appender.File.mode = write >>>log4perl.appender.File.layout = Log::Log4perl::Layout::PatternLayout >>>log4perl.appender.File.layout.ConversionPattern = %d: %m%n >>> >>>log4perl.appender.Screen = Log::Dispatch::Screen >>>log4perl.appender.Screen.stderr = 0 >>>log4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayout >>>log4perl.appender.Screen.layout.ConversionPattern = %-5p> %m%n >>> >>> >>>test.pl: >>># Einstellungen z.B. aus Programmflags bestimmt >>>$more_conf = q(log4perl.appender.File.filename = test.log >>> log4perl.appender.File.mode = append); >>> >>>Log::Log4perl::init('Dump2OWH.conf', $more_conf); >>> >>> >>>I can see at least one other way to implement it: a >>>not-yet-implemented-in-Log4perl feature like variables in config files >>>(log4j has something like that but I don't think they can specify the >>>variable replacement values via code) and a mechanism to define the >>>placeholders in init(conf_file, key => value, key => value); >>> >>>Any other ideas? Sounds like a pretty useful feature to me. >> >>Initially I wondered why I couldn't do something like this: >> >>Log::Log4perl::init('Dump2OWH.conf'); >>my $appender = get_appender('File'); >>$appender->filename('test.log'); >> >>but after investigating found that get_appender is part of the log4j >>API which hasn't been implemented, Log::Dispatch::File doesn't support >>get and set methods on its instance variables, and, more importantly, >>that the output file is opened as part of the creation of the >>appender during the init(), so it's then too late to change the file >>name. >> >>Regards, >>Duncan Cameron >> >> >> >> >> >> >> >>------------------------------------------------------- >>This sf.net email is sponsored by:ThinkGeek >>Welcome to geek heaven. >>http://thinkgeek.com/sf >>_______________________________________________ >>log4perl-devel mailing list >>log...@li... >>https://lists.sourceforge.net/lists/listinfo/log4perl-devel > > -- Happy Trails . . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510) 525-5217 |
From: À¯¸Ó³ª¶ó <hum...@ch...> - 2002-12-09 05:27:21
|
<html><head><meta http-equiv="content-type" content="text/html; charset=euc-kr"><title>유머나라(최신호)</title><style><!--a:link,a:visited,a:active {text-decoration:none;} a:hover {text-decoration:underline; color:red;} BODY, TABLE, TD, TR, TH {height:20; font{font-size:10pt; font-weight:normal; font-family:굴림체,Times New Roman} line-heiht:100%; } --> </style></head><body><table cellpadding="3" cellspacing="0"><tr> <td width="600" height="16" valign="top" colspan="3" bgcolor='#cccccc' align="center"> <span style="font-size:14pt;"><b><a href="http://www.humornara.com/index_gate.htm?no=131"><font color="black">유머나라 & 엽기코리아</font></a></b><br></span><span style="font-size:9pt;">(최신호입니다.)</span> </td> </tr> <tr> <td width="600" height="11" valign="top" colspan="3"> <hr noshade size=1 style="line-height:100%; margin-top:0; margin-bottom:0;"> </td> </tr> <tr> <td width="281" height="236" valign="top" rowspan="3"> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://active.macromedia.com/flash4/cabs/swflash.cab#version=4,0,0,0" data="http://flash.lettee.com/data/swf/97_m.swf" width="283" height="202"> <param name="movie" value="http://flash.lettee.com/data/swf/97_m.swf"> <param name="play" value="true"> <param name="loop" value="true"> <param name="quality" value="high"> <embed src="http://flash.lettee.com/data/swf/97_m.swf" play="true" loop="true" quality="high" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="283" height="202"></embed> </object> </td> <td width="0" height="236" valign="top" rowspan="3"> </td> <td width="309" height="64" valign="top" bgcolor='#ebebeb'> * <b><a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm"><font color="black">플래시 애니메이션 more...</font></a></b><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">스틱헌터&샤오샤오</a><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">공포특급 - 폐교에서의 악몽!</a><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">라면보이 - 열라면 편!</a> </td></tr><tr> <td width="309" height="57" valign="top" bgcolor='#ebebeb'> * <b><a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm"><font color="black">플래시 게임 more...</font></a></b><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">[엽기] 달걀공예(스트레스 해소)</a><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">바구니에 과일 담기</a><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">고릴라의 충치 뽑기(치과게임)</a></td></tr><tr> <td width="309" height="80" valign="top" bgcolor='#ebebeb'> * <b><a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm"><font color="black">엽기 플래시 more...</font></a></b><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">[최신]홍스구락부 - 얼랄라 브라더스</a><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">보글보글 패러디</a><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">딩딩 - 으라차차 차력사편</a><br> </td></tr><tr> <td width="600" height="14" valign="top" colspan="3"> <hr noshade size=1 style="line-height:100%; margin-top:0; margin-bottom:0;"> </td></tr><tr> <td width="283" height="27" valign="top" bgcolor='#ebebeb'> <b><a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm"><font color="black">사진 애니 짱!</font></a></b></td> <td width="0" height="27" valign="top"> </td> <td width="309" height="27" valign="top" bgcolor='#ebebeb'> <b><a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm"><font color="black">사랑과 미팅</font></a></b> </td></tr><tr align="left" valign="top"> <td width="283" height="98" valign="top"> * <b><a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm"><font color="black">스타 깜짝방 more...</font></a><br> </b> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">초등생이 그린 앙드레김 그림!</a><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">핑클 효리와 똑같은 만화 주인공</a><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">놀라운 강타 스케치</a><br> - <a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">조폭.. 신은경 등의 문신</a> </td> <td width="0" height="299" valign="top" rowspan="3"> </td> <td width="309" height="299" valign="top" rowspan="3"> * <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black"><b>감동과 사랑 more...</b></font></a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">그녀와 나의 엇갈린 사랑 이야기</a> 1<br> 이건 저의 실제이야기 입니다.. 표현과 어휘구사가 떨어지더라도 이해해주세요..<br>그녀를 처음 알게 된건 중3때 입니다.. 물론 같은 학교였기 때문에 그전에도 얼굴은 본적있지만 친하게 된건 중3때 였습니다.. 반편성을 하고 처음으로 그녀와 같은 반이 되었습니다.. 전 학교생활을 해가면서 그녀에게 관심이 쏠렸구.. 나중에 알게된 사실이지만 그녀두 저에게 관심이 있었답니다.. <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">more..</a><br><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">그녀와 나의 엇갈린 사랑 이야기 2</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">그녀와 나의 엇갈린 사랑 이야기 3</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">그녀와 나의 엇갈린 사랑 이야기 4</a></td> </tr> <tr align="left" valign="top"> <td width="283" height="80" valign="top"> * <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm"><b><font color="black">스타 타임머신</font></b></a><b><a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm"><font color="black"> more...</font></a></b><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">정양의 어린시절</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">토니안의 어린시절 모습</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">하리수의 어린시절 모습</a> </td></tr><tr align="left" valign="top"> <td width="283" height="114" valign="top"> * <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm"><b><font color="black">엽기 사진</font></b></a><b><a href="http://www.humornara.com/ref.php?no=210&cno=85"><font color="black"> more...</font></a><br> </b> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">누가 이런 짓을??</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">길거리에서 마주친 나쁜놈</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">수건일까? 강아지일까??</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/main.htm">넘 넘.. 귀여운 강아지!!</a></p> </td></tr><tr align="left" valign="top"> <td width="283" height="27" valign="top" bgcolor='#ebebeb'> <b><a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black">공포와 미스테리</font></a></b> </td> <td width="0" height="27" valign="top"> </td> <td width="309" height="27" valign="top" bgcolor='#ebebeb'> <b><a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black">엽기캠사진</font></a></b> </td></tr><tr align="left" valign="top"> <td width="283" height="95" valign="top" bgcolor="white"> * <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><b><font color="black">엽기나라 UFO more...</font></b></a><b><font color="black"><br> </font></b><font color="black"> - </font><A href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">9월 4일은 외계인 한국 방문의 날</A><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">고대벽화의 UFO</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">한반도 크기만 한 UFO</a></p> </td> <td width="0" height="170" valign="top" rowspan="2"> </td> <td width="309" height="170" valign="top" bgcolor="white" rowspan="2"> *<a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"> <font color="black"><b>여자 엽기짱 포토게시판 more...</b></font></a> <table border="0" width="304"> <tr><td width="65" height="30" align="right"> <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black"><img src="http://photoimg.naver.com/view/14/25/camjjang_3/5546_s.jpg" width="45" height="35" border="0"></font></a> </td><td width="223" height="30" align="left"> <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">쬐끔 귀엽군...</a> </td></tr><tr><td width="65" height="32" align="right"> <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><img src="http://photoimg.naver.com/view/14/25/camjjang_3/5545_s.jpg" width="45" height="35" border="0"></a> </td><td width="223" height="32"><a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">김민희 닮았다 열라 이뿌당..</a> </td></tr><tr><td width="65" height="2" align="right"> <A href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><img src="http://photoimg.naver.com/view/14/25/camjjang_3/5544_s.jpg" width="45" height="35" border="0"></A> </td><td width="223" height="2"><A href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">어서 차즌건데.. 적어두 이정둔 되이지~~</A> </td></tr></table></td></tr> <tr align="left" valign="top"> <td width="283" height="72" valign="top" bgcolor="white"> * <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><b><font color="black">명랑엽기 공포 사진 more...</font></b></a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">생명 탄생</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">발바닥에 손가락이..</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">사람은 없는데..</a> </td> </tr> <tr align="left" valign="top"> <td width="283" height="19" valign="top" bgcolor="#ebebeb"> <font color="black"> </font><b><a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black">어랑 영화방</font></a></b></td> <td width="0" height="19" valign="top"> </td> <td width="309" height="19" valign="top" bgcolor="#ebebeb"> <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black"><b>뮤직비디오 & 엽기송</b></font></a></td></tr> <tr align="left" valign="top"> <td width="283" height="127" valign="top" bgcolor="white"> * <b><a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black">무료 영화방 more...</font></a><font color="black"><br> </font></b><font color="black"> - </font><a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">생활의 발견(김상경,추상미,예지원)</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">친구(장동건,유오성)</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">박하사탕(설경구)</a><br> * <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black"><b>쐬주천사 영화감상실</b></font></a><font color="black"><b><br> </b> * </font><a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black"><b>빈후니 영화감상실</b></font></a></td> <td width="0" height="127" valign="top"> </td> <td width="309" height="127" valign="top" bgcolor="white" bgcolor="white"> * <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black"><b>바부코랴 똥꼬라됴</b></font><b><font color="black"> more...</font></b></a><font color="black"><b><br> </b> - </font><a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">'콩가' 성인 버전</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">보신탕되기 전 강아지의 절규</a><br> - <a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm">[고전명작] 좆도 이야기</a><br> * <b><a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black">CCM 쥬크박스</font></a><font color="black"><br> </font></b><font color="black"> * </font><a href="http://humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><font color="black"><b>엽기나라 엽기송</b></font></a></td></tr></table> <table cellspacing='0' cellpadding='0' width="600"><tr><td align=center><br> <hr noshade size=1 style="line-height:100%; margin-top:0; margin-bottom:0;"> 이후에 메일을 받지 않으시려면 메일수신거부 버튼을 눌러주세요.<br> </td></tr><tr><td align='center'><a href='http://www.humornara.com/reject_mail.htm'><b>수신 거부</b></a></td> </tr><img src="http://www.humornara.com/receive_cnt.htm?s=131" border=0> <tr align="left" valign="top"> <td width="612" height="7" valign="top" bgcolor="white" colspan="3"> <hr noshade size=1 style="line-height:100%; margin-top:0; margin-bottom:0;"> <p style="line-height:100%; margin-top:0; margin-bottom:0;" align="center"><a href="http://www.humornara.com/index_gate.htm?no=131"><span style="font-size:8pt;">유머나라</span></a><span style="font-size:8pt;"> & </span><a href="http://www.humornara.com/index_gate.htm?no=131&redir=http://www.humornara.com/yupgikorea/main.htm"><span style="font-size:8pt;">엽기나라</span></a></p></td></tr></table></body></html> |
From: ÀÌȨÇÇ <eh...@ch...> - 2002-12-09 05:23:01
|
<html><head><style type='text/css'><!--td {font-size:9pt}A:link {text-decoration: none; color:0D0D0D;}A:visited {text-decoration: none; color:0D0D0D;} A:active {text-decoration: none; color:F9B014;} A:hover {text-decoration: underline; color:F9B014;} .unnamed1 { line-height: 18px; color: #333333} --> </style><meta http-equiv='Content-Type' content='text/html; charset=euc-kr'></head> <body bgcolor='#CCCCCC' text='#000000' background='http://mailling.skywebhosting.co.kr/img/020514/back.gif'> <table width='604' cellspacing='2' cellpadding='0' bgcolor='A0A0A0'><tr> <td bgcolor='#FFFFFF'> <table width='600' cellspacing='0' cellpadding='0'><tr> <td><img src='http://mailling.skywebhosting.co.kr/img/020514/img_01.gif' width='600' height='40' usemap='#Map2' border='0'></td> </tr><tr><td height='210'><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219'><img src='http://mailling.skywebhosting.co.kr/img/020514/title3.gif' width='600' height='183' border=0></a></td> </tr><tr><td> <font color=red><b>다음카페/프리챌에서 이전</b>하시는 경우에는 <b>게시판을 무료</b>로 이전해 드립니다.<br></b></font><br> <a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219'><img src='http://mailling.skywebhosting.co.kr/img/020514/title1.gif' width='370' height='30' border=0></a></td> </tr></table> <table width='600' cellspacing='0' cellpadding='0'><tr><td> <table width='100%' cellspacing='0' cellpadding='0' height='40'> <tr><td width='10%'> </td> <td width='84%' class='unnamed1'>홈페이지는 만들어야 하는데 시간도 없고, 돈도 없고 . . .<br>걱정하지 마세요~<b><br><font color='#973E78'>월 만원</font></b>이면 <b><font color='#973E78'>홈페이지 제작</font></b>과 <b><font color='#973E78'>200M 웹호스팅</font></b>이 한번에 해결됩니다.</td> <td width='6%'> </td> </tr></table></td></tr></table> <table width='600' cellspacing='0' cellpadding='0'> <tr><td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219'><img src='http://mailling.skywebhosting.co.kr/img/020514/title2.gif' width='370' height='30' border=0></a></td> </tr><tr><td><table width='100%' cellspacing='0' cellpadding='0' height='40'><tr> <td width='10%'> </td> <td width='84%'><span class='unnamed1'>거품을 뺀 실속 있는 쇼핑몰 구축, 강력한 <font color='#973E78'>커뮤니티 기능 + 쇼핑몰</font>을 <b><font color='#973E78'>월 2만2천원</font></b> 에 운영 할 수 있습니다</span><br> </td><td width='6%'> </td> </tr></table></td> </tr><tr><td align='center'><table width='82%' cellspacing='0' cellpadding='0' bgcolor='#F3F3F3'> <tr><td colspan='4' height='8'></td></tr> <tr height='18'> <td width='16'> </td><td width='179'>■ 상품등록/관리</td><td width='162'>■ 매 출 관 리</td><td width='133'>■ 전 자 결 제</td> </tr><tr height='18'><td></td><td>■ 주문/배송관리</td><td>■ 마일리지 관리</td><td>■ 상 품 검 색</td></tr> <tr height='18'><td> </td><td colspan='3'>■ 커뮤니티 기능 (<u>아래 기능 소개의 모든 기능을 쇼핑몰에서 기본 제공합니다.</u>)</td></tr> <tr><td colspan='4' height='8'></td></tr></table></td></tr></table> <table width='600' cellspacing='0' cellpadding='0'><tr> <td colspan=2><img src='http://mailling.skywebhosting.co.kr/img/020514/img_06.gif' width='600' height='40'></td></tr> <tr><td width=30> </td><td align='left' height='95'> <table width='98%' cellspacing='1' cellpadding='0' bgcolor='#CCCCCC'><tr bgcolor='#FFFFFF' align='center' height='20'> <td width='25%'><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_13.htm'>회원관리 기능</a></td> <td width='25%'><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_02.htm'>게시판 생성 무제한</a></td> <td width='25%'><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_04.htm'>자료실 생성 무제한</a></td> <td width='25%'><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_04.htm'>링크자료실 생성 무제한</a></td> </tr><tr bgcolor='#FFFFFF' align='center' height='20'> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_15.htm'>소모임 개설기능</a></td> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_12.htm'>실시간 쪽지기능</a></td> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_09.htm'>일 정 관 리</a></td> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219'>팝업창/공지기능</a></td></tr> <tr bgcolor='#FFFFFF' align='center' height='20'> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_10.htm'>설문조사</a> / <a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_03.htm'>토론실</a></td> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_07.htm'>대화방 (채팅)</a></td> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_05.htm'>미디어자료실</a></td> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_08.htm'>앨 범</a></td></tr> <tr bgcolor='#FFFFFF' align='center' height='20'> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_11.htm'>주 소 록</a></td> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://www.ehomp.com/service/service_program_14.htm'>전체메일보기</a></td> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219'>현재 접속자 보기</a></td> <td> </td></tr></table></td></tr></table> <table width='600' cellspacing='0' cellpadding='0'> <tr><td align='center'><br> <table width='95%' cellspacing='0' cellpadding='0'><tr> <td><img src='http://mailling.skywebhosting.co.kr/img/020514/pic_7.gif' width='323' height='42'></td></tr></table> <table width='98%' cellspacing='0' cellpadding='2'><tr> <td colspan=6> * 아래는 eHomp 를 이용해서 만들고 현재 운영중인 사이트입니다.</td> </tr><tr><td width=30> </td> <td width='17%' bgcolor='EFEFEF'><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://lespor.co.kr/' target='_blank'><img src='http://mailling.skywebhosting.co.kr/img/020514/pic_1.gif' width='95' height='71' border='0'></a></td> <td width='17%' bgcolor='EFEFEF'><font color='18566A'><b><span class='unnamed1'>기업홍보/사업</span></b></font><span class='unnamed1'><br> LeSpor</span></td> <td bgcolor='EFEFEF'><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://class66.org' target='_blank'><img src='http://mailling.skywebhosting.co.kr/img/020514/pic_2.gif' width='95' height='71' border='0'></a></td> <td width='18%' bgcolor='EFEFEF'><b><font color='18566A'><span class='unnamed1'>동창/동문모임</span></font></b><span class='unnamed1'><br> 쌍육회</span></td> <td width='17%' bgcolor='EFEFEF'><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://calvarychapel.or.kr' target='_blank'><img src='http://mailling.skywebhosting.co.kr/img/020514/pic_3.gif' width='95' height='71' border='0'></a></td> <td width='17%' bgcolor='EFEFEF'><font color='18566A'><b><span class='unnamed1'>종교활동</span></b></font><span class='unnamed1'><br> 갈보리 채플</span></td></tr> <tr><td colspan='6' height='3'></td></tr> <tr bgcolor='D2E5EC'><td bgcolor=white> </td> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://suwonphoto.com' target='_blank'><img src='http://mailling.skywebhosting.co.kr/img/020514/pic_4.gif' width='95' height='71' border='0'></a></td> <td><font color='18566A'><b><span class='unnamed1'>학교/학원</span></b></font><span class='unnamed1'><br>수원 사진학원</span></td> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://missmrkorando.net/' target='_blank'><img src='http://mailling.skywebhosting.co.kr/img/020514/pic_5.gif' width='95' height='71' border='0'></a></td> <td><font color='18566A'><b><span class='unnamed1'>엔터테인먼트</span></b></font><span class='unnamed1'><br> 미스미스터<br>코란도 클럽</span></td> <td><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219&redir=http://shopping.ehomp.com' target='_blank'><img src='http://mailling.skywebhosting.co.kr/img/020514/pic_6.gif' width='95' height='71' border='0'></a></td> <td> <font color='18566A'><b><span class='unnamed1'>쇼핑몰</span></b></font><span class='unnamed1'><br>샘플 사이트</span></td> </tr></table></td></tr> <tr><td align='center' height='40'><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219' target='_blank'><img src='http://mailling.skywebhosting.co.kr/img/020514/button2.gif' width='180' height='30' border='0'></a></td></tr> </table></td></tr></table> <table width='604' cellspacing='0' cellpadding='0'> <tr><td bgcolor='18566A' align='center' height='50'> <table width='95%' cellspacing='0' cellpadding='0'><tr height='16'><td> </td> <td><font color='#FFFFFF'><b>서비스 신청</b> :<a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219' target='_blank'> </a></font><a href='http://www.ehomp.com/index_gate.htm?agency=58&no=219' target='_blank'><font color='#FFFFFF'>www.ehomp.com</font></a></td></tr> <tr height='16'><td> </td> <td><font color='#FFFFFF'><b>문 의 사 항</b> : (02) 749 -0717 ~8 / <b>E-mail</b> : </font><a href='mailto:in...@eh...'><font color='#FFFFFF'>in...@eh...</font></a></td></tr> </table></td></tr></table> <map name='Map2'><area shape='rect' coords='-1,1,141,38' href='http://www.ehomp.com' target='_blank' onfocus='this.blur()'></map> <img src="http://mailling.skywebhosting.co.kr/receive_cnt.htm?s=219" border=0> <table width='604' cellspacing='0' cellpadding='0'><tr><td><br> 이 전자우편은 (주)킴스넷의 홈페이지 제작서비스를 광고할 목적으로 발송되어지는 메일입니다.<br> 이후에 메일을 받지 않으시려면 메일수신거부 버튼을 눌러주세요.<br> 감사합니다.<br> </td></tr><tr> <td align='center'><a href='http://mailling.skywebhosting.co.kr/reject_mail.htm'><img src='http://mailling.skywebhosting.co.kr/img/020514/button.gif' width='101' height='23' border='0'></a></td> </tr></table></body></html> |
From: <msc...@ao...> - 2002-12-08 04:11:33
|
Hi all, 0.27 just hit CPAN, here's what has changed from the last release: 0.27 11/12/2002 * (ms) Added Log::Log4perl::NDC (Nested Diagnostic Contexts) and Log::Log4perl::MDC (Mapped Diagnostic Contexts) * (kg) User-defined conversion specifiers for PatternLayout in configuration file and as C API * (ms) LOGDIE and LOGWARN added to stealth loggers * (ms) Logging methods ($lo->debug(), $lo->info() ...) now return a value, indicating the number of appenders that the message was propagated to. If the message was suppressed due to level constraints, undef is returned. Updated manpage (new section "return values"). * (ms) Fixed bug reported by Francisco Olarte Sanz. <fo...@pe...>: ISO date format and documentation mixed up MM with mm in the simple date format * (kg) implementing map to log4j.RollingFileAppender * (kg) trying out oneMessagePerAppender parameter * (kg) changed unit tests to use File::Spec * (ms) Updated FAQ with "Recipes of the Week" Have fun! -- -- Mike ############################ # Mike Schilli # # log...@pe... # # http://perlmeister.com # # log4perl.sourceforge.net # ############################ |
From: Kai P. <ka...@po...> - 2002-12-06 09:10:58
|
Hi, how about a construct like this in the config file? log4perl.appender.File.filename = sub { return GetLogflleName(); } Kai On Thursday 05 December 2002 20:20, Duncan Cameron wrote: > On 2002-12-03 Mike Schilli <msc...@ao...> wrote: > >Hi there, > > > >Kai Poitschke has brought up an interestingfeature request: Suppose, > >your application had a configuration "-l logfilename" option to specify > >the name of the log file to be used. Now, if you have an external > >configuration file (as opposed to a string ref passed to init()), how > >would you be able to adapt the config file setting in the code? > > > >He suggests to have init() overwrite certain properties of the config > >file like in: > > > > Dump2OWH.conf: > > > >log4perl.category.Dump2OWH = INFO, File, Screen > > > >log4perl.appender.File = Log::Dispatch::File > >log4perl.appender.File.filename = Dump2OWH.log > >log4perl.appender.File.mode = write > >log4perl.appender.File.layout = Log::Log4perl::Layout::PatternLayout > >log4perl.appender.File.layout.ConversionPattern = %d: %m%n > > > >log4perl.appender.Screen = Log::Dispatch::Screen > >log4perl.appender.Screen.stderr = 0 > >log4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayout > >log4perl.appender.Screen.layout.ConversionPattern = %-5p> %m%n > > > > > >test.pl: > > # Einstellungen z.B. aus Programmflags bestimmt > > $more_conf = q(log4perl.appender.File.filename = test.log > > log4perl.appender.File.mode = append); > > > > Log::Log4perl::init('Dump2OWH.conf', $more_conf); > > > > > >I can see at least one other way to implement it: a > >not-yet-implemented-in-Log4perl feature like variables in config files > >(log4j has something like that but I don't think they can specify the > >variable replacement values via code) and a mechanism to define the > >placeholders in init(conf_file, key => value, key => value); > > > >Any other ideas? Sounds like a pretty useful feature to me. > > Initially I wondered why I couldn't do something like this: > > Log::Log4perl::init('Dump2OWH.conf'); > my $appender = get_appender('File'); > $appender->filename('test.log'); > > but after investigating found that get_appender is part of the log4j > API which hasn't been implemented, Log::Dispatch::File doesn't support > get and set methods on its instance variables, and, more importantly, > that the output file is opened as part of the creation of the > appender during the init(), so it's then too late to change the file > name. > > Regards, > Duncan Cameron > > > > > > > > ------------------------------------------------------- > This sf.net email is sponsored by:ThinkGeek > Welcome to geek heaven. > http://thinkgeek.com/sf > _______________________________________________ > log4perl-devel mailing list > log...@li... > https://lists.sourceforge.net/lists/listinfo/log4perl-devel -- Finding out what goes on in the C.I.A. is like performing acupuncture on a rock. -- New York Times, Jan. 20, 1981 Unix, WinNT and MS-DOS. The Good, The Bad and The Ugly. Kai Poitschke MailTo:kai[_at_]poitschke[_dot_]de Date/Time: Fri Dec 6 10:06:05 MET 2002 |
From: <msc...@ao...> - 2002-12-05 21:26:14
|
Hi all, welcome to the Log::Log4perl Recipe of the Week. Today: ============================================================ How can I make sure my application logs a message when it dies unexpectedly? ------------------------------------------------------------ Whenever you encounter a fatal error in your application, instead of saying something like open FILE, "<blah" or die "Can't open blah -- bailing out!"; just use Log::Log4perl's fatal functions instead: my $log = get_logger("Some::Package"); open FILE, "<blah" or $log->logdie("Can't open blah -- bailing out!"); This will both log the message with priority FATAL according to your current Log::Log4perl configuration and then call Perl's "die()" afterwards to terminate the program. It works the same with stealth loggers (see "Stealth Loggers" in the Log::Log4perl documentation), all you need to do is call use Log::Log4perl qw(:easy); open FILE, "<blah" or LOGDIE "Can't open blah -- bailing out!"; What can you do if you're using some library which doesn't use Log::Log4perl and calls "die()" internally if something goes wrong? Use a $SIG{__DIE__} pseudo signal handler: use Log::Log4perl qw(get_logger); $SIG{__DIE__} = sub { $Log::Log4perl::caller_depth++; my $logger = get_logger(""); $logger->fatal(@_); exit 1; }; This will catch every "die()"-Exception of your application or the modules it uses. It will fetch a root logger and pass on the "die()"-Message to it. If you make sure you've configured with a root logger like this: Log::Log4perl->init(\q{ log4perl.category = FATAL, Logfile log4perl.appender.Logfile = Log::Dispatch::File log4perl.appender.Logfile.filename = fatal_errors.log log4perl.appender.Logfile.layout = \ Log::Log4perl::Layout::PatternLayout log4perl.appender.Logfile.layout.ConversionPattern = \ %F{1}-%L (%M)> %m%n }); then all "die()" messages will be routed to a file properly. The line $Log::Log4perl::caller_depth++; in the pseudo signal handler above merits a more detailed explanation. With the setup above, if a module calls "die()" in one of its functions, the fatal message will be logged in the signal handler and not in the original function -- which will cause the %F, %L and %M placeholders in the pattern layout to be replaced by the filename, the line number and the function/method name of the signal handler, not the error-throwing module. To adjust this, Log::Log4perl has the $caller_depth variable, which defaults to 0, but can be set to positive integer values to offset the caller level. Increasing it by one will cause it to log the calling function's parameters, not the ones of the signal handler. See "Using Log::Log4perl from wrapper classes" in the Log::Log4perl manpage for more details. Have fun! -- Mike ############################ # Mike Schilli # # log...@pe... # # http://perlmeister.com # # log4perl.sourceforge.net # ############################ |
From: Duncan C. <dca...@bc...> - 2002-12-05 19:21:13
|
On 2002-12-03 Mike Schilli <msc...@ao...> wrote: >Hi there, > >Kai Poitschke has brought up an interestingfeature request: Suppose, >your application had a configuration "-l logfilename" option to specify >the name of the log file to be used. Now, if you have an external >configuration file (as opposed to a string ref passed to init()), how >would you be able to adapt the config file setting in the code? > >He suggests to have init() overwrite certain properties of the config >file like in: > > Dump2OWH.conf: > >log4perl.category.Dump2OWH = INFO, File, Screen > >log4perl.appender.File = Log::Dispatch::File >log4perl.appender.File.filename = Dump2OWH.log >log4perl.appender.File.mode = write >log4perl.appender.File.layout = Log::Log4perl::Layout::PatternLayout >log4perl.appender.File.layout.ConversionPattern = %d: %m%n > >log4perl.appender.Screen = Log::Dispatch::Screen >log4perl.appender.Screen.stderr = 0 >log4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayout >log4perl.appender.Screen.layout.ConversionPattern = %-5p> %m%n > > >test.pl: > # Einstellungen z.B. aus Programmflags bestimmt > $more_conf = q(log4perl.appender.File.filename = test.log > log4perl.appender.File.mode = append); > > Log::Log4perl::init('Dump2OWH.conf', $more_conf); > > >I can see at least one other way to implement it: a >not-yet-implemented-in-Log4perl feature like variables in config files >(log4j has something like that but I don't think they can specify the >variable replacement values via code) and a mechanism to define the >placeholders in init(conf_file, key => value, key => value); > >Any other ideas? Sounds like a pretty useful feature to me. > Initially I wondered why I couldn't do something like this: Log::Log4perl::init('Dump2OWH.conf'); my $appender = get_appender('File'); $appender->filename('test.log'); but after investigating found that get_appender is part of the log4j API which hasn't been implemented, Log::Dispatch::File doesn't support get and set methods on its instance variables, and, more importantly, that the output file is opened as part of the creation of the appender during the init(), so it's then too late to change the file name. Regards, Duncan Cameron |
From: Mike S. <msc...@ao...> - 2002-12-02 23:13:22
|
Hi there, Kai Poitschke has brought up an interestingfeature request: Suppose, your application had a configuration "-l logfilename" option to specify the name of the log file to be used. Now, if you have an external configuration file (as opposed to a string ref passed to init()), how would you be able to adapt the config file setting in the code? He suggests to have init() overwrite certain properties of the config file like in: Dump2OWH.conf: log4perl.category.Dump2OWH = INFO, File, Screen log4perl.appender.File = Log::Dispatch::File log4perl.appender.File.filename = Dump2OWH.log log4perl.appender.File.mode = write log4perl.appender.File.layout = Log::Log4perl::Layout::PatternLayout log4perl.appender.File.layout.ConversionPattern = %d: %m%n log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.stderr = 0 log4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayout log4perl.appender.Screen.layout.ConversionPattern = %-5p> %m%n test.pl: # Einstellungen z.B. aus Programmflags bestimmt $more_conf = q(log4perl.appender.File.filename = test.log log4perl.appender.File.mode = append); Log::Log4perl::init('Dump2OWH.conf', $more_conf); I can see at least one other way to implement it: a not-yet-implemented-in-Log4perl feature like variables in config files (log4j has something like that but I don't think they can specify the variable replacement values via code) and a mechanism to define the placeholders in init(conf_file, key => value, key => value); Any other ideas? Sounds like a pretty useful feature to me. -- -- Mike Mike Schilli log...@pe... |
From: <msc...@ao...> - 2002-12-01 23:36:15
|
In a message dated 12/1/2002 6:26:50 PM Eastern Standard Time, msc...@ao... writes: > I think you > have a bug in the ISO8601 Date specification, which reads 'YYYY-mm-dd >HH:mm:ss,SSS' in the docs. The first mm should be MM for month. Hi Francisco, your're certainly correct, you've discovered a bug in Log4perl, the ISO format was incorrect. I've fixed it and patched the pending 0.27 release. Please check the 0.27 tarball on log4perl.sourceforge.net, it should behave correctly now. Thanks so much for your help, Francisco! Kevin, I've rolled in your changes, too, ok with you? -- -- Mike ############################ # Mike Schilli # # log...@pe... # # http://perlmeister.com # # log4perl.sourceforge.net # ############################ |
From: <msc...@ao...> - 2002-12-01 23:26:24
|
From: Duncan C. <dca...@bc...> - 2002-11-30 23:05:51
|
On 2002-11-30 Kevin Goess <ke...@go...> wrote: >I finally got a few minutes to think about log4perl today, and was >looking at my TODO list in the changes file: > > * Bug: If the *same* appender is being attached to several loggers, > appender inheritance doesn't work as expected: Even if the > appender appears twice in the inheritance tree, it's only executed >once. > But it actually needs to be run twice to match log4j. > >For our behavior (attached perl) to match the log4j behavior (attached >java) on the (attached config), I would have to make the change >(attached diff). > >The only unit tests it messes with is 012Deeper.t, which is where it >would be expected. So this would change the behavior of our libraries, >in that if you have an appender attached to plant and also to >plant.tree.leaf, a log message to plant.tree.leaf or below will fire the >appender twice, currently it only does it once (I believe that behavior >seemed more appropriate at the time). > >Any comments before I make the change to bring us into conformity with >log4j? I've been trying to understand why firing the appender twice is either a good thing or not a good thing. In your example, I wonder what the user is trying to achieve by having the appender attached to both plant and plant.tree.leaf? Firing all appenders, regardless of number of occurences sounds simple, but equally why would one want a log message to appear multiple times in the same appender? Do you know what the original log4j rationale was? >RCS file: /cvsroot/log4perl/Log-Log4perl/lib/Log/Log4perl/Logger.pm,v >retrieving revision 1.39 >diff -u -r1.39 Logger.pm >--- lib/Log/Log4perl/Logger.pm 18 Nov 2002 05:34:47 -0000 1.39 >+++ lib/Log/Log4perl/Logger.pm 30 Nov 2002 00:09:31 -0000 >@@ -126,8 +126,9 @@ > > foreach my $appender_name (@{$logger->{appender_names}}){ > >- #only one message per appender, please >- next if $seen{$appender_name} ++; >+ #actually, log4j behavior the appender should >+ #fire each time it's called >+ #next if $seen{$appender_name} ++; > > push (@appenders, > [$appender_name, > The %seen hash can be removed entirely. Is it usual to comment out code rather than remove it? Regards, Duncan Cameron |
From: Kevin G. <ke...@go...> - 2002-11-30 00:14:46
|
I finally got a few minutes to think about log4perl today, and was looking at my TODO list in the changes file: * Bug: If the *same* appender is being attached to several loggers, appender inheritance doesn't work as expected: Even if the appender appears twice in the inheritance tree, it's only executed once. But it actually needs to be run twice to match log4j. For our behavior (attached perl) to match the log4j behavior (attached java) on the (attached config), I would have to make the change (attached diff). The only unit tests it messes with is 012Deeper.t, which is where it would be expected. So this would change the behavior of our libraries, in that if you have an appender attached to plant and also to plant.tree.leaf, a log message to plant.tree.leaf or below will fire the appender twice, currently it only does it once (I believe that behavior seemed more appropriate at the time). Any comments before I make the change to bring us into conformity with log4j? -- Happy Trails. . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510)525-5217 |
From: <msc...@ao...> - 2002-11-27 06:15:42
|
Welcome to the Log::Log4perl recipe of the week. Today: My application is already logging to a file. How can I duplicate all messages to also go to the screen? Assuming that you already have a Log4perl configuration file like log4perl.logger = DEBUG, FileApp log4perl.appender.FileApp = Log::Dispatch::File log4perl.appender.FileApp.filename = test.log log4perl.appender.FileApp.layout = PatternLayout log4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n and log statements all over your code, it's very easy with Log4perl to have the same messages both printed to the logfile and the screen. No reason to change your code, of course, just add another appender to the configuration file and you're done: log4perl.logger = DEBUG, FileApp, ScreenApp log4perl.appender.FileApp = Log::Dispatch::File log4perl.appender.FileApp.filename = test.log log4perl.appender.FileApp.layout = PatternLayout log4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n log4perl.appender.ScreenApp = Log::Dispatch::Screen log4perl.appender.ScreenApp.stderr = 0 log4perl.appender.ScreenApp.layout = PatternLayout log4perl.appender.ScreenApp.layout.ConversionPattern = %d> %m%n The configuration file above is assuming that both appenders are active in the same logger hierarchy, in this case the "root" category. But even if you've got file loggers defined in several parts of your system, belonging to different logger categories, each logging to different files, you can gobble up all logged messages by defining a root logger with a screen appender, which would duplicate messages from all your file loggers to the screen due to Log4perl's appender inheritance. Check http://www.perl.com/pub/a/2002/09/11/log4perl.html for details. Have fun! -- -- Mike ############################ # Mike Schilli # # log...@pe... # # http://perlmeister.com # # log4perl.sourceforge.net # ############################ |
From: Kevin G. <ke...@go...> - 2002-11-25 17:41:23
|
msc...@ao... wrote: > BTW, on first glance, I haven't found the Perl API to the > appender-specific cspec definition yet -- is there such a thing? I held off on that pending the discussion on our thread 'Log::Log4perl::NDC' regarding the problems around giving the user a reference to an object that might be invalidated. But once we give the user a reference to a a layout, they can call add_layout_cspec('Z', sub {return 'bleargh'}); That's already taken care of. -- Happy Trails . . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510) 525-5217 |
From: mark p. <mar...@ed...> - 2002-11-24 23:29:56
|
On Sat, 23 Nov 2002 15:25:08 -0800 Kevin Goess's good news was: > > Mark, thanks for fixing that, but when I run 'make test' for version > 1.05 the test runs for at least 8 minutes before I get bored and kill > it. Looking at the test script, you don't actually seem to be testing > anything, you're just running it for a long time, all the files could be > ending up in /dev/null for all the test can tell. Might I be so bold as > to suggest > It is testing time based rotation. Which takes time not bytes to tickle. But you are right, it is boring and provides little feedback. > 1) If the test really needs to run for longer than about five seconds > then tell the user in advance how long the test is expected to take. > Nobody's going to want to run the test if it takes 10 minutes. But what > are you actually testing with all those iterations? > Time based rotation. I left the granularity up too high. > 2) To actually test the functionality, log enough bytes so that the > logfile rolls and then check the contents of "file.log" and > "file.log.1". You might take a look at the test I wrote to test the > interface to FileRotate, attached, and do something like that (although > Mike S. says he's seen it misbehave, so it might not be the best thing > to steal from). > I'll look at it. > 3) You should really test the file locking, there' enought code there > that it should be tested. This would involve refactoring the module so > that the test script can pause a logging operation right after it locks > the file and then launch another logging operation to see if it does the > right thing. > Once again I'll look into it. > 4) The test script sleeps for 180 seconds, so for 3 minutes + run time. > I gave up running it after about 8 minutes, so that would imply there's > some horrible runtime inefficiency going on? Could you check that out? > Hmm, ran it on my box and it took 3m0.639s. Not sure what you were seeing when you ran it. The sleep was so that I could run multiple "make test"'s from multiple xterms, so I could watch the time rotation and locking happening. Simple and crude but an effective way of watching what was going on. It is probably not what potential users want to see. I guess there needs to be a way of turning long running tests off or shortening them significantly - whilst making sure all aspects are being tested. The unfortunate issue is that there are branches in the code that will never get tested until someone wants a log rotated at greater than a yearly period. I guess I could trick time_to_rotate() into thinking it's time when it isn't really. > mark pfeiffer wrote: > > > > Oops ;-( typo! > > > ... snip ... cheers mark (who is not an idiot.... Just reeaaallllyyyyy sllooowwww :-) ) |
From: <msc...@ao...> - 2002-11-24 03:57:16
|
In a message dated 11/23/2002 8:10:53 PM Eastern Standard Time, Kevin Goess <ke...@go...> writes: >If you're an API kind of person, there's also this call: > > Log::Log4perl::Layout::PatternLayout:: > add_global_cspec('Z', sub {'zzzzzzzz'}); #snooze? Awesome, thanks Kevin! Defining the cspecs in the config file definitely makes sense, having them next to where they're actually used (in the layout defs), and for them to be defined by the same person editing the conf file sold me on the idea. The security aspects you've found are a good catch and valid, having separate access rights for config files vs. programs is not that uncommon (or at least there might be different rules for QA/deployment), so we might have an issue there. But empowering the application to prevent defining code snippets in the config file, like you've done it, should do the trick, I think. Regarding the default, one could really argue both ways: Having it disabled by default is probably a minor hurdle, having it enabled by default might catch some people by surprise who haven't read the entire manual. BTW, on first glance, I haven't found the Perl API to the appender-specific cspec definition yet -- is there such a thing? Again, great work, thanks! -- -- Mike ############################ # Mike Schilli # # log...@pe... # # http://perlmeister.com # # log4perl.sourceforge.net # ############################ |
From: <msc...@ao...> - 2002-11-24 03:40:34
|
In a message dated 11/23/2002 7:08:31 PM Eastern Standard Time, Kevin Goess <ke...@go...> writes: >Mike, after further review, if we do something like this: > > sub Log::Log4perl::appender_by_name { > return $Log::Log4perl::Logger::APPENDER_BY_NAME{shift}; > } > >then we might create problems where the user code has a reference to an >appender, then init_and_watch() reloads everything and the user's >reference is no longer connected to anything, but the user doesn't know >it. That's an interesting case. Maybe we should have something like the log4j folks: Their appenders can be marked "closed" which allows them to keep them around after a config reload. Actually, this is a general problem with our implementation -- having a Perl API in parallel with a configuration file which can be reloaded and render any appender references obtained via the Perl API (even as simple as Log::Log4perl::Appender->new()) invalid. This is most likely why the reason the log4j folks have this weird notion of config file reloading, keeping then useless appenders around (but marking them 'closed' I think). Anyway, I think that it's ok if you put appenders_by_name() in there, it's no worse than Log::Log4perl::Appender->new(). Long term we probably need to re-think the config file reloading, I think I understand now why Ceki did it the way he did it :). -- Mike ############################ # Mike Schilli # # log...@pe... # # http://perlmeister.com # # log4perl.sourceforge.net # ############################ |
From: Kevin G. <ke...@go...> - 2002-11-24 01:13:23
|
> One more thought: Is adding Perl code to the conf file the > right approach or should this be a perl API along the same lines > as Eric's create_custom_level() which has to be called before > init()? Good question. I gave this some serious thought, and the only guidelines I can think of that apply to the question are: 1) Partitioning: Highly interrelated parts of the problem should be in the same piece of the system, i.e., things that belong together should go together 2) Log4perl logging can be completely controlled from the config file, without touching your application code So since the user is using their custom conversion specifiers (cspecs) in the config file, it would be handy to have them defined right next to where they're using them. This might suggest we should also offer a way to define custom *levels* from the config file, but there's a difference in that custom levels *are* referenced from the code ($logger->litewarn(..)) while the use and impact of custom cspec's are confined to the config file. But for flexibility I'll include a method anyway. So with all that in mind, I've implemented and checked in custom cspec's, so you can do this in your config: #'U' a global user-defined cspec log4j.PatternLayout.cspec.U = sub { return "UID: $< "} #'K' cspec local to appndr1 (pid in hex) log4j.appender.appndr1.layout.cspec.K = sub { return sprintf "%1x", $$} #and now you can use them log4j.appender.appndr1.layout.ConversionPattern = %K %U %m%n The benefit of this approach is that you can define and use the cspecs right next to each other in the config file. If you're an API kind of person, there's also this call: Log::Log4perl::Layout::PatternLayout:: add_global_cspec('Z', sub {'zzzzzzzz'}); #snooze? The appender-specific was implied by the config file syntax, so I implemented both the global and the appender-specific ones. Incompatability with log4j? This stuff possibly doesn't mesh with the log4j proposal. But their proposal is just that, a proposal, which might change anyway. It should be pretty obvious that perl code in a conifg file isn't going to go anywhere with a java logger. If the log4j people do implement something, our implementation is pretty much at the surface, so it wouldn't be hard to rip out. Security Issue: it occurred to me that some people might have a problem with their config files all of a sudden becoming a place where perl code gets eval'd and executed. If there's some installation where some group of users has permission to edit the config file but shouldn't have permission to run code then that might cause a problem. They can set $Log::Log4perl::DONT_ALLOW_USER_DEFINED_CSPECS = 1; before calling init(), which turns off the feature. I'm wondering if this is good enough, should we default not allowing user-defined cspecs? I've checked the code in, attached is a diff (may not work as a patch) if you want to see what I've done. Please let me know any comments or concerns. -- Happy Trails. . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510)525-5217 |