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...> - 2003-02-27 18:30:55
|
ke...@go... wrote: > Mike, are there any negative ramifications to changing it from a > number to a string? Is there anything else that expects it to be a > number? > Should be fine, the test suite passes and I'm not aware of any appenders insisting on the numbers. But, ideally, I'd like Log::Dispatch::ApacheLog to adhere to the Log::Dispatch spec (or, alternatively, the Log::Dispatch spec needs to be updated). -- -- Mike Mike Schilli log...@pe... |
From: Dave R. <au...@ur...> - 2003-02-27 18:21:07
|
On Thu, 27 Feb 2003, Kevin Goess wrote: > Dave, is this a deficiency in ApacheLog.pm, or are we misunderstanding > something? It's a bug for sure. -dave /*======================= House Absolute Consulting www.houseabsolute.com =======================*/ |
From: Kevin G. <ke...@go...> - 2003-02-27 16:57:35
|
Back in December, I quietly released the DOMConfigurator module, adding the ability to initialize log4perl via an XML file rather than a properties config file. This lets you validate the config syntax against a DTD, for instance using Xerces' "StdInParse -v -ns < yourconfig.xml". That release supported the log4j dtd, at least where the features had been implemented in log4perl. But we've added config options in log4perl that log4j doesn't have: #1) oneMessagePerAppender global setting log4perl.oneMessagePerAppender=1 #2) globally defined user conversion specifiers log4perl.PatternLayout.cspec.G=sub { return "UID $< GID $("; } #3) appender-local custom conversion specifiers log4j.appender.appndr1.layout.cspec.K = sub {return sprintf "%1x", $$ } #4) nested options log4j.appender.jabbender = Log::Dispatch::Jabber #(note how these are nested under 'login') log4j.appender.jabbender.login.hostname = a.jabber.server log4j.appender.jabbender.login.port = 5222 log4j.appender.jabbender.login.username = bobjones #5) not to mention Mike's new filter stuff!! So we needed to extend the log4j dtd to cover these additions. Now I could have just taken a 'steal this code' approach and mixed parts of the log4j dtd into a log4perl dtd, but that would be cut-n-paste programming. So I've used namespaces and *) replaced three elements: <log4perl:configuration> handles #1) and accepts <PatternLayout> <log4perl:appender> accepts <param-nested> and <param-text> <log4perl:layout> accepts custom cspecs for #3) *) added a <param-nested> element (complementing the <param> element) to handle #4) *) added a root <PatternLayout> element to handle #2) *) added <param-text> which lets you put things like perl code into escaped CDATA between the tags, so you don't have to worry about escaping characters and quotes *) added <cspec> In the name of code re-use the log4perl dtd links to the log4j dtd, which I've named "log4j-1.2.dtd" to protect us from changes on the log4j side. The benefit of this approach over cut-n-paste is that it re-uses the log4j dtd in situ. The drawback is that it requires an extra namespace prefix in the config--if you want to use log4perl features in an appender then you have to say <log4perl:appender...> instead of just <appender...>. Though that could also be a benefit--if you're in a situation where you're managing both log4j and log4perl configs (god forbid!) it would help to keep them straight. Now the parser I'm using, XML::DOM, isn't namespace aware, it's only DOM Level 1. XML::GDOME, on the other hand, is DOM Level 2 (with namespaces) but depends on libgdome, a requirement which sounds unecessarily cumbersome to me. So the namespace handling in the parser is pretty primitive and it presumes log4perl is the working prefix, as opposed to whatever prefix the URI is bound to. But since DTD's aren't really namespace URI aware either and a DTD is what's supplied to validate against, I don't see that as a huge problem. Attached for your convenience are the log4perl dtd the relevant parts of the log4j dtd a sample xml config The log4perl code in CVS is updated to handle all the new stuff. I'd be interesting in hearing about anything that looks like bad practice or not being flexible/scalable enough. Thanks. -- Happy Trails . . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510) 525-5217 |
From: Kevin G. <ke...@go...> - 2003-02-27 16:16:54
|
msc...@ao... wrote: > In a message dated 2/26/2003 7:24:28 PM Eastern Standard Time, Kevin > Goess <ke...@go...> writes: > >> but there is another problem in Log4perl. Log::Dispatch expects >> the 'level' param to be a word, we are passing an integer, which >> suggests that the hash %Log::Log4perl::Levels::L4P_TO_LD should >> have values that are words not integers, and that this stuff in >> Levels.pm > > > Hmm. The Log::Dispatch man page seems to say integers are okay: > > "Alternately, the numbers 0 through 7 may be used (debug is 0 and > emergency is 7)." > > Is the Apache logger different? If yes, we can certainly add the > change as you suggested, patch is attached. Well, you're right, the Log::Dispatch docs do say that. But the guts of ApacheLog.pm are doing stuff like this elsif( $p{level} eq 'warning' ) { $method = 'warn'; } else { $method = $p{level}; } $self->{apache_log}->$method( $p{message} ); which is where it fails trying to call $log->7() if you pass it a number. Mike, are there any negative ramifications to changing it from a number to a string? Is there anything else that expects it to be a number? Dave, is this a deficiency in ApacheLog.pm, or are we misunderstanding something? -- Happy Trails . . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510) 525-5217 |
From: <Sag...@ub...> - 2003-02-27 13:39:16
|
Kevin/Mike, Thanks very much for your help, at least I now know I wasn't doing = anything silly. I look forward to these fixes in a future Log4perl release. In the = meantime I'm going to implement my own subclass of = Log::Dispatch::ApacheLog with a) hard code the numbers temporarily (unfortunately I can't just patch = the Log4perl, large organisations like mine have lots of rules) b) replace the need for the $r apache argument. I really don't see why Log::Dispatch::ApacheLog requires the user to = pass it an Apache::Request or Apache::Server object since it could = simply do: use Apache; use Apache::Log; if($r and not $r->isa('Apache::Server') and not $r->('Apache::Request')) = { $r =3D Apache->request->server; } I guess one for me to ponder for a bit longer/ push to the Log::Dispatch = author/team. Thanks again for your help and for producing log4perl in the first = place! Best Regards Sagar >-----Original Message----- >From: msc...@ao... [mailto:msc...@ao...] >Sent: 27 February 2003 08:24 >To: ke...@go...; Shah, Sagar >Cc: log...@li... >Subject: Re: [log4perl-devel] Log4perl / Log::Dispatch::ApacheLog >problem > > >In a message dated 2/26/2003 7:24:28 PM Eastern Standard Time,=20 >Kevin Goess <ke...@go...> writes: > >>Sagar, it looks like log4perl is taking the values from your=20 >config hash=20 >>and converting them into text strings: > >Aha! Thanks for the great detective work!=20 > >>but there is another problem in Log4perl. Log::Dispatch expects the=20 >>'level' param to be a word, we are passing an integer, which suggests=20 >>that the hash %Log::Log4perl::Levels::L4P_TO_LD should have=20 >values that=20 >>are words not integers, and that this stuff in Levels.pm > >Hmm. The Log::Dispatch man page seems to say integers are okay: > > "Alternately, the numbers 0 through 7 may be used (debug is=20 >0 and emergency is 7)." > >Is the Apache logger different? If yes, we can certainly add=20 >the change as you suggested, patch is attached.=20 > >--=20 >-- Mike > >############################ ># Mike Schilli # ># log...@pe... # ># http://perlmeister.com # ># log4perl.sourceforge.net # >############################ > +ANYTHING+BELOW+THIS+LINE+WAS+ADDED+AFTER+I+HIT+SEND+ Visit our website at http://www.ubswarburg.com This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. E-mail transmission cannot be guaranteed to be secure or error-free as information could be intercepted, corrupted, lost, destroyed, arrive late or incomplete, or contain viruses. The sender therefore does not accept liability for any errors or omissions in the contents of this message which arise as a result of e-mail transmission. If verification is required please request a hard-copy version. This message is provided for informational purposes and should not be construed as a solicitation or offer to buy or sell any securities or related financial instruments. |
From: <msc...@ao...> - 2003-02-27 08:24:30
|
In a message dated 2/26/2003 7:24:28 PM Eastern Standard Time, Kevin Goess <ke...@go...> writes: >Sagar, it looks like log4perl is taking the values from your config hash >and converting them into text strings: Aha! Thanks for the great detective work! >but there is another problem in Log4perl. Log::Dispatch expects the >'level' param to be a word, we are passing an integer, which suggests >that the hash %Log::Log4perl::Levels::L4P_TO_LD should have values that >are words not integers, and that this stuff in Levels.pm Hmm. The Log::Dispatch man page seems to say integers are okay: "Alternately, the numbers 0 through 7 may be used (debug is 0 and emergency is 7)." Is the Apache logger different? If yes, we can certainly add the change as you suggested, patch is attached. -- -- Mike ############################ # Mike Schilli # # log...@pe... # # http://perlmeister.com # # log4perl.sourceforge.net # ############################ |
From: Kevin G. <ke...@go...> - 2003-02-27 00:26:05
|
Sagar, it looks like log4perl is taking the values from your config hash and converting them into text strings: Log::Log4perl::Config.pm @text = map { $_ . '=' . $config->{$_} } keys %{$config}; so $r is being munged into a string. We can look into fixing that. I was going to suggest you could use the other older method of init and do something like this $stash_package::r = $r; Log::Log4perl::init( \<<'EOL' log4perl.logger.Main = INFO, apache_log log4perl.appender.apache_log = Log::Dispatch::ApacheLog log4perl.appender.apache_log.apache = sub {$stash_package::r } ... EOL ); but there is another problem in Log4perl. Log::Dispatch expects the 'level' param to be a word, we are passing an integer, which suggests that the hash %Log::Log4perl::Levels::L4P_TO_LD should have values that are words not integers, and that this stuff in Levels.pm add_priority("WARN", WARN_INT, 4, 3); should actually be add_priority("WARN", WARN_INT, 4, 'warning'); Mike, you added that fourth parameter as part of "log dispatch level fix" back on 11/8/2002, can you take a look at that when you get a minute? Sag...@ub... wrote: > Hi, > > I'm having a problem trying to use Log4perl with the Log::Dispatch::ApacheLog appender. I haven't managed to get it down to a simple test case yet, but i'm wondering whether the error i'm getting is something that twigs with anyone on this list. > > The configuration i'm using is: > > > 'log4perl.logger.Main' => 'WARN, apache_log', > 'log4perl.logger.Screen' => 'WARN, apache_log', > 'log4perl.logger' => 'WARN, apache_log', > 'log4perl.appender.apache_log' => 'Log::Dispatch::ApacheLog', > 'log4perl.appender.apache_log.apache' => $r, > 'log4perl.appender.apache_log.Threshold' => 'WARN', > 'log4perl.appender.apache_log.layout' => 'Log::Log4perl::Layout::PatternLayout', > 'log4perl.appender.apache_log.layout.ConversionPattern' => '[%d] %m', > > > > Where $r is either Apache->request or Apache->request->server (i.e. i get the problem in both cases). > > The error i get when trying to create my logger is: > > > [Wed Feb 26 18:09:34 2003] [error] The 'apache' parameter to Log::Dispatch::ApacheLog::new does not have the method: 'log' > Params::Validate::__ANON__('The \'apache\' parameter to Log::Dispatch::ApacheLog::new doe...') called at /home/shahsag/my_tree/links/cpan/lib/Params/Validate.pm line 415 > Params::Validate::_validate_one_param('Apache::Server=SCALAR(0x1c77f20)','HASH(0xa266b4)','The \'apache\' parameter') called at /home/shahsag/my_tree/links/cpan/lib/Params/Validate.pm line 258 > Params::Validate::validate('ARRAY(0xa26510)','HASH(0xa264ec)') called at /home/shahsag/my_tree/links/cpan/lib/Log/Dispatch/ApacheLog.pm line 25 > Log::Dispatch::ApacheLog::new('undef','min_level','debug','apache','Apache::Server=SCALAR(0x1c77f20)','Threshold','WARN','name','apache_log',...) called at /home/shahsag/my_tree/links/cpan/lib/Log/Log4perl/Appender.pm line 68 > Log::Log4perl::Appender::new('Log::Log4perl::Appender','Log::Dispatch::ApacheLog','name','apache_log','apache','Apache::Server=SCALAR(0x1c77f20)','Threshold','WARN') called at /home/shahsag/my_tree/links/cpan/lib/Log/Log4perl/Config.pm line 209 > Log::Log4perl::Config::_init('Log::Log4perl::Config','HASH(0x1c99dd4)') called at /home/shahsag/my_tree/links/cpan/lib/Log/Log4perl/Config.pm line 35 > Log::Log4perl::Config::init('Log::Log4perl::Config','HASH(0x1c99dd4)') called at /home/shahsag/my_tree/links/cpan/lib/Log/Log4perl.pm line 142 > Log::Log4perl::init('Log::Log4perl','HASH(0x1c99dd4)') called at /home/shahsag/my_tree/links/CORE/lib/Log/OPG.pm line 705 > > > > However i run a $r->can('log') before trying to create my logger and it's all okay. Am i doing something wrong with my configuration? If not, any ideas about why/how my Apache object is becomming mangled? > > thanks > > Sagar > > Visit our website at http://www.ubswarburg.com > > This message contains confidential information and is intended only > for the individual named. If you are not the named addressee you > should not disseminate, distribute or copy this e-mail. Please > notify the sender immediately by e-mail if you have received this > e-mail by mistake and delete this e-mail from your system. > > E-mail transmission cannot be guaranteed to be secure or error-free > as information could be intercepted, corrupted, lost, destroyed, > arrive late or incomplete, or contain viruses. The sender therefore > does not accept liability for any errors or omissions in the contents > of this message which arise as a result of e-mail transmission. If > verification is required please request a hard-copy version. This > message is provided for informational purposes and should not be > construed as a solicitation or offer to buy or sell any securities or > related financial instruments. > > > > ------------------------------------------------------- > This SF.net email is sponsored by: Scholarships for Techies! > Can't afford IT training? All 2003 ictp students receive scholarships. > Get hands-on training in Microsoft, Cisco, Sun, Linux/UNIX, and more. > www.ictp.com/training/sourceforge.asp > _______________________________________________ > 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: Mike S. <msc...@ao...> - 2003-02-26 21:22:14
|
Sag...@ub... wrote: >I'm having a problem trying to use Log4perl with the Log::Dispatch::ApacheLog appender. I haven't managed to get it down to a simple test case yet, but i'm wondering whether the error i'm getting is something that twigs with anyone on this list. > >The configuration i'm using is: > > > 'log4perl.logger.Main' => 'WARN, apache_log', > > I'm suspecting that it is related to the underscore used in the appender name "apache_log", maybe a bug in Log4perl, I'll investigate it tonight. For now, just try using a name without an underscore (like "apachelog") and let me know if it fixes the problem ... -- -- Mike Mike Schilli log...@so... |
From: <Sag...@ub...> - 2003-02-26 18:33:18
|
Hi, I'm having a problem trying to use Log4perl with the = Log::Dispatch::ApacheLog appender. I haven't managed to get it down to a = simple test case yet, but i'm wondering whether the error i'm getting is = something that twigs with anyone on this list. The configuration i'm using is: 'log4perl.logger.Main' =3D> = 'WARN, apache_log', 'log4perl.logger.Screen' =3D> = 'WARN, apache_log', 'log4perl.logger' =3D> = 'WARN, apache_log', 'log4perl.appender.apache_log' =3D> = 'Log::Dispatch::ApacheLog', 'log4perl.appender.apache_log.apache' =3D> = $r, 'log4perl.appender.apache_log.Threshold' =3D> = 'WARN', 'log4perl.appender.apache_log.layout' =3D> = 'Log::Log4perl::Layout::PatternLayout', 'log4perl.appender.apache_log.layout.ConversionPattern' =3D> = '[%d] %m', Where $r is either Apache->request or Apache->request->server = (i.e. i get the problem in both cases). The error i get when trying to create my logger is: [Wed Feb 26 18:09:34 2003] [error] The 'apache' parameter to = Log::Dispatch::ApacheLog::new does not have the method: 'log' Params::Validate::__ANON__('The \'apache\' parameter to = Log::Dispatch::ApacheLog::new doe...') called at = /home/shahsag/my_tree/links/cpan/lib/Params/Validate.pm line 415 = Params::Validate::_validate_one_param('Apache::Server=3DSCALAR(0x1c77f20)= ','HASH(0xa266b4)','The \'apache\' parameter') called at = /home/shahsag/my_tree/links/cpan/lib/Params/Validate.pm line 258 Params::Validate::validate('ARRAY(0xa26510)','HASH(0xa264ec)') called = at /home/shahsag/my_tree/links/cpan/lib/Log/Dispatch/ApacheLog.pm line = 25 = Log::Dispatch::ApacheLog::new('undef','min_level','debug','apache','Apach= e::Server=3DSCALAR(0x1c77f20)','Threshold','WARN','name','apache_log',...= ) called at = /home/shahsag/my_tree/links/cpan/lib/Log/Log4perl/Appender.pm line 68 = Log::Log4perl::Appender::new('Log::Log4perl::Appender','Log::Dispatch::Ap= acheLog','name','apache_log','apache','Apache::Server=3DSCALAR(0x1c77f20)= ','Threshold','WARN') called at = /home/shahsag/my_tree/links/cpan/lib/Log/Log4perl/Config.pm line 209 Log::Log4perl::Config::_init('Log::Log4perl::Config','HASH(0x1c99dd4)') = called at /home/shahsag/my_tree/links/cpan/lib/Log/Log4perl/Config.pm = line 35 Log::Log4perl::Config::init('Log::Log4perl::Config','HASH(0x1c99dd4)') = called at /home/shahsag/my_tree/links/cpan/lib/Log/Log4perl.pm line 142 Log::Log4perl::init('Log::Log4perl','HASH(0x1c99dd4)') called at = /home/shahsag/my_tree/links/CORE/lib/Log/OPG.pm line 705 However i run a $r->can('log') before trying to create my logger and = it's all okay. Am i doing something wrong with my configuration? If = not, any ideas about why/how my Apache object is becomming mangled? thanks Sagar Visit our website at http://www.ubswarburg.com This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. E-mail transmission cannot be guaranteed to be secure or error-free as information could be intercepted, corrupted, lost, destroyed, arrive late or incomplete, or contain viruses. The sender therefore does not accept liability for any errors or omissions in the contents of this message which arise as a result of e-mail transmission. If verification is required please request a hard-copy version. This message is provided for informational purposes and should not be construed as a solicitation or offer to buy or sell any securities or related financial instruments. |
From: Dintelmann, P. <Pet...@Dr...> - 2003-02-24 08:07:33
|
> Mike Schilli wrote: > > Pet...@Dr... wrote: > > > > > I prefer to define constants for the return values (and put > > > > > Nice. Definitely the correct way of defining it and being > flexible to > > add stuff in the future. On the other hand, I really like > constructs like > > > > sub { /x/ and /y/ } > > I agree with Mike on this one. I think booleans are a feature of the > language, Agreed. The proposed constants "OK" and "DECLINED" should therefore be 0 and 1 respectively which makes the whole thing dwimmy. But for future features constants may be helpful (see Mike's comment above). > where constants are something added on by the > programmer, you > don't really gain that much by redefining booleans and it > would clutter > the syntax. > > > > > > 3. What a about message redirection? Are there plans for the > > > future that a filter (or whatever) can forward a message to > > > another appender? > > > > > Interesting feature, I haven't thought of that yet (neither have the > > log4j folks). I gotta think about that. Can you imagine a use case? > > Also, we could implement that either as a Log4perl-centric > feature based > > on filter return code (as you suggested) or as a > function/method call > > inside the filter (redir_to_appender(blah)). > > Interesting indeed, but I forsee that as being really hairy. > Do we want > to write our own JMX api? why not ;-)? I am really jealous of that feature... > You have to deal with things like circular > routes, appenders not being defined/avaliable. Ugh. Two ways to circumvent this: 1. Every appender has a "level" and forwarding is only allowed to appenders with a higer level (not specifying a "level" is the the same as specifying the minimum level). 2. Every message carries a TTL field which is decremented and the message is discarded if the counter drops to 0. I prefer the first option. Mike asked for the use cases. An appender is a kind of output channels and the reasons to change an output channel is a moving or changing message recipient. This is helpful for - multiple support groups (e.g. applications are administered by another group during weekends) - message escalation - travelling recipient (get log messages via email from 8h-18h and on your mobile from 18h-22h) Regards, Peter -- Dr. Peter Dintelmann Dresdner Bank AG CC IT MIS - MIS@ Products Theodor-Heuss-Allee 110 D-60301 Frankfurt Germany Tel.: +49-(0)69-263-19722 Email: Pet...@dr... http://www.dresdner-bank.com http://mis.dresdner-bank.com |
From: <Msc...@ao...> - 2003-02-23 22:16:37
|
In a message dated 2/22/03 9:05:04 AM Pacific Standard Time, ke...@go... writes: > Some observations: Kevin, you've made some excellent points, see details inline ... > 1) Regarding log4j compatibility, if someone implements log4j-style > filters it's just a matter of specifying a different implementation > class in the config, right? Hmm, except for the chaining thing, and > that log4j filters return ACCEPT/DENY/NEUTRAL instead of true/false. The Log4j folks don't have a notion of defining filters in the Property-style config files, and probably won't have one in the forseeable future, so we're exploring unchartered waters. No matter how we're implementing it, it'll always be incompatible with Log4j. But, you're right, maybe some day we'll need a notion of a "chained" filter set. It can be accomplished by employing a strategy similar to the "Bool"ean filter: A "Chained" filter, taking a chain of filters. And the chain defines what it means (block/neutral/accept) if filter X returns true or false (note that the chain can base its decision on the same parameters as the filter has available, because the chain calls the filter in turn). The current design is simple: An appender has only one filter attached (returning true or false), but it's up to this filter to be smart and use the services of other filters in creative ways. > > Is there any way to differentiate? Is it worth calling our filters > "pfilters" or "bfilter" (b for boolean)? We can make the distinction at the filter level, see above. > 2) As I was writing those examples, I wondered if it's worthwhile > setting up to allow defining a filter per-appender as well as global, > like we do for the cspec's? (see t/033UsrCspec.t). Then you can use > them close to where they're defined. Interesting thought. With cspecs, I can clearly see the importance: You've got a very limited namespace (one-letter words) and local settings could pollute the global namespace quickly if they weren't separated. However, the filter case is different, their namespace is virtually unlimited. Kind of like loggers reference appenders -- there's no localized namespace. And it's OK to define them close to where they're used: # Error appender log4perl.appender.AppError = Log::Dispatch::File log4perl.appender.AppError.filename = /tmp/app.err log4perl.appender.AppError.layout = SimpleLayout log4perl.filter.MatchError = Log::Log4perl::Filter::LevelMatch log4perl.filter.MatchError.LevelToMatch = WARN log4perl.appender.AppError.Filter = MatchError What we could do, though (without too much effort, I hope) is shorten the definition by cutting out the filter name: # Error appender log4perl.appender.AppError = Log::Dispatch::File log4perl.appender.AppError.filename = /tmp/app.err log4perl.appender.AppError.layout = SimpleLayout log4perl.appender.AppError.Filter = Log::Log4perl::Filter::LevelMatch log4perl.appender.AppError.Filter.LevelToMatch = WARN This way, there's no name pollution -- but on the other hand you're limited because filters like Bool(ean) expect named filters. > 3) There seems to be a typo in the email, under "Attaching a filter to > an appender" it says > log4perl.appender.MyAppender = MyFilter > s/b > log4perl.appender.MyAppender.Filter = MyFilter > right? Good catch! Fixed in the docs now. > > 4) Tiny point: do you really want to call it Bool.pm instead of > Boolean.pm? What's a Bool? The name of the guy who invented it was "George Boole", so "Bool" doesn't make any sense, you're right :). I'll change it to Boolean (hope not too many people have read this week's recipe :). If you have, use "Boolean.pm" from now on! :) > > 5) Why is "f" capitalized in "log4perl.appender.Screen.Filter" but not > in "log4perl.filter.Match1"? (I'm as guilty as anyone of inconistency > here, but it's never to late to reform!) Good point. It's "log4perl.filter" because it's "log4perl.appender". All that's lower-cased, by log4j standards. On the other hand, the situation with appender or other properties/attributes is less clear: Seems like they're uppercase if they're local to the current object and lowercase if they're property "keywords" (compare log4j.appender.X.threshold vs. log4j.appender.X.File). In log4perl, we haven't made that distinction so far, properties are typically lowercase for the perl appenders (Java appenders conform to log4j, though) -- mainly because Log::Dispatch has lowercase attributes. I was just concerned about an appender in the Log::Dispatch hierarchy accidently defining a "filter" attribute. If our "Filter" keyword is uppercase, it's less likely to clash (although still ambiguous), although, you're right about it being inconsistent. > > 6) log4j's decide() method returns a constant ACCEPT/DENY/NEUTRAL, but > our decide() returns a boolean. Wouldn't it be better to name our > method let_pass() or is_loggable() or something that implies how the > boolean will be treated? ("Hmm, I can't remember, does decide()==true > mean decides to filter it out, or decides to log it?"). I think a hint > to the developer might be appreciated some day. Yep, makes sense. I'll put on my thinking cap ... :) Thanks for the feedback, changes are checked in (BTW in case I haven't mentioned it, it's all implemented/documented already, check t/040Filter.t for more or less typical use cases). -- Mike Mike Schilli log...@pe... |
From: Kevin G. <ke...@go...> - 2003-02-22 17:04:57
|
Mike Schilli wrote: > Pet...@Dr... wrote: > > > I prefer to define constants for the return values (and put > > > Nice. Definitely the correct way of defining it and being flexible to > add stuff in the future. On the other hand, I really like constructs like > > sub { /x/ and /y/ } I agree with Mike on this one. I think booleans are a feature of the language, where constants are something added on by the programmer, you don't really gain that much by redefining booleans and it would clutter the syntax. > > > 3. What a about message redirection? Are there plans for the > > future that a filter (or whatever) can forward a message to > > another appender? > > > Interesting feature, I haven't thought of that yet (neither have the > log4j folks). I gotta think about that. Can you imagine a use case? > Also, we could implement that either as a Log4perl-centric feature based > on filter return code (as you suggested) or as a function/method call > inside the filter (redir_to_appender(blah)). Interesting indeed, but I forsee that as being really hairy. Do we want to write our own JMX api? You have to deal with things like circular routes, appenders not being defined/avaliable. Ugh. -- Happy Trails. . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510)525-5217 |
From: Kevin G. <ke...@go...> - 2003-02-22 17:04:52
|
Crimeny, sorry about the delay. Brutal couple of weeks, am finally reading the RFC and it rocks!! All right, Mike! It's very clean, and it puts a lot more control into the config file does than the log4j filters do. Some observations: 1) Regarding log4j compatibility, if someone implements log4j-style filters it's just a matter of specifying a different implementation class in the config, right? Hmm, except for the chaining thing, and that log4j filters return ACCEPT/DENY/NEUTRAL instead of true/false. Is there any way to differentiate? Is it worth calling our filters "pfilters" or "bfilter" (b for boolean)? It looks like the xml for a log4j filter is set up like this <appender name="UDPVENUS" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.SimpleLayout"/> <filter class="org.apache.log4j.filters.PriorityRangeFilter"> <param name="PriorityMin" value="WARN" /> </filter> <filter class="org.apache.log4j.filters.StringMatchFilter"> <param name="StringToMatch" value="security violation" /> </filter> </appender> so they're making filter definitions local to an appender instead of global to a config. That would imply that *if* log4j filters were available in a config they might look like this: log4j.appender.Screen = org.apache.log4j.ConsoleAppender log4j.appender.Screen.Layout = org.apache.log4j.SimpleLayout log4j.appender.Screen.Filter.prf = org.apache.log4j.filters.PriorityRangeFilter log4j.appender.Screen.Filter.prf.PriorityMin = WARN log4j.appender.Screen.Filter.sm = org.apache.log4j.filters.StringMatchFilter log4j.appender.Screen.Filter.sm.StringToMatch = security violation Which implies a set of per-appender filters, chained. Whereas in our scheme chaining would be accomplished via a Bool filter. So we might have filters returning two sets of things, and one kind of filters link together in different ways. Is it worthwhile renaming ours to head off incompatability with the mother ship? It definitely shows the attraction of namespaces in XML! 2) As I was writing those examples, I wondered if it's worthwhile setting up to allow defining a filter per-appender as well as global, like we do for the cspec's? (see t/033UsrCspec.t). Then you can use them close to where they're defined. 3) There seems to be a typo in the email, under "Attaching a filter to an appender" it says log4perl.appender.MyAppender = MyFilter s/b log4perl.appender.MyAppender.Filter = MyFilter right? 4) Tiny point: do you really want to call it Bool.pm instead of Boolean.pm? What's a Bool? 5) Why is "f" capitalized in "log4perl.appender.Screen.Filter" but not in "log4perl.filter.Match1"? (I'm as guilty as anyone of inconistency here, but it's never to late to reform!) 6) log4j's decide() method returns a constant ACCEPT/DENY/NEUTRAL, but our decide() returns a boolean. Wouldn't it be better to name our method let_pass() or is_loggable() or something that implies how the boolean will be treated? ("Hmm, I can't remember, does decide()==true mean decides to filter it out, or decides to log it?"). I think a hint to the developer might be appreciated some day. msc...@ao... wrote: > > Hey Kevin and all, > > here's a design proposal for the soon-to-come "custom filters" Log4perl feature. Let me know how if you like it! To be clear, nothing of what's mentioned below has been implemented yet (it's checked in under Log/Log4perl/Filter.pm, though) -- just wanted to run this by you to make sure I haven't overlooked anything. Comments, questions, counter-proposal welcome, as always :) > > -- > -- Mike > > ############################ > # Mike Schilli # > # log...@pe... # > # http://perlmeister.com # > # log4perl.sourceforge.net # > ############################ > > NAME > > Log::Log4perl::Filter - Log4perl Custom Filter Base Class > > SYNOPSIS > use Log::Log4perl; > > Log::Log4perl->init(<<'EOT'); > log4perl.logger = INFO, Screen > log4perl.filter.MyFilter = sub { /let this through/ } > log4perl.appender.Screen = Log::Dispatch::Screen > log4perl.appender.Screen.Filter = MyFilter > log4perl.appender.Screen.layout = Log::Log4perl::Layout::SimpleLayout > EOT > > # Define a logger > my $logger = Log::Log4perl->get_logger("Some"); > > # Let this through > $logger->info("Here's the info, let this through!"); > > # Suppress this > $logger->info("Here's the info, suppress this!"); > > DESCRIPTION > Log4perl allows the use of customized filters in its appenders to > control the output of messages. These filters might grep for certain > text chunks in a message, verify that its priority matches or exceeds a > certain level or that this is the 10th time the same message has been > submitted -- and come to a log/no log decision based upon these > circumstantial facts. > > Filters carry names and can be specified in two different ways in the > Log4perl configuration file: As subroutines or as filter classes. Here's > a simple filter named "MyFilter" which just verifies that the oncoming > message matches the regular expression "/let this through/i": > > log4perl.filter.MyFilter = sub { /let this through/i } > > It exploits the fact that when the filter is called on a message, Perl's > special $_ variable will be set to the (rendered) message to be logged. > The filter subroutine is expected to return a true value if it wants the > message to be logged or a false value if doesn't. Also, Log::Log4perl > will pass the same arguments to the filter function as it would to the > corresponding appender. Here's an example of a filter checking the > priority of the oncoming message: > > log4perl.filter.MyFilter = sub { \ > my %p = @_; \ > (%p{log4p_level} == WARN) ? 1 : 0; \ > } > > If the message priority equals "WARN", it returns a true value, causing > the message to be logged. For common tasks like this, there's already a > set of predefined filters available. To perform a level match, it's much > cleaner to use Log4perl's "LevelMatch" filter instead: > > log4perl.filter.MyFilter = Log::Log4perl::Filter::LevelMatch > log4perl.filter.MyFilter.LevelToMatch = WARN > > Once a filter has been defined by name and class, its values can be > assigned to its attributes, just as the "WARN" value to the > "LevelToMatch" attribute above. > > Attaching a filter to an appender > Attaching a filter to an appender is as easy as assigning its name to > the appender's "Filter" attribute: > > log4perl.appender.MyAppender = MyFilter > > This will cause "Log::Log4perl" to call the filter subroutine/method > every time a message is supposed to be passed to the appender. Depending > on the filter's return value, "Log::Log4perl" will either continue as > planned or withdraw. > > Combining filters with Log::Log4perl::Filter::Bool > Sometimes, it's useful to combine the output of various filters to > arrive at a log/no log deciscion. While Log4j, Log4perl's mother ship, > chose to implement this feature as a filter chain, similar to Linux' IP > chains, Log4perl tries a different approach. > > Typically, filter results will not need to be passed along in chains but > combined in a programmatic manner using boolean logic. "Log if this > filter says 'yes' and that filter says 'no'" is a fairly common > requirement but hard to implement as a chain. > > "Log::Log4perl::Filter::Bool" is a special predefined custom filter for > Log4perl which combines the results of other custom filters in arbitrary > ways, using boolean expressions: > > log4perl.logger = WARN, AppWarn, AppError > > log4perl.filter.Match1 = sub { /let this through/ } > log4perl.filter.Match2 = sub { /and that, too/ } > log4perl.filter.MyBool = Log::Log4perl::Filter::Bool > log4perl.filter.MyBool.logic = Match1 || Match2 > > log4perl.appender.Screen = Log::Dispatch::Screen > log4perl.appender.Screen.Filter = MyBool > log4perl.appender.Screen.layout = Log::Log4perl::Layout::SimpleLayout > > "Log::Log4perl::Filter::Bool"'s boolean expressions allow for combining > different appenders by name using AND (&& or &), OR (|| or |) and NOT > (!) as logical expressions. Parentheses are used for grouping. > Precedence follows standard Perl. Here's a bunch of examples: > > Match1 && !Match2 # Match1 and not Match2 > !(Match1 || Match2) # Neither Match1 nor Match2 > (Match1 && Match2) || Match3 # Both Match1 and Match2 or Match3 > > Writing your own filter classes > If none of Log::Log4perl's predefined filter classes fits your needs, > you can easily roll your own: Just define a new class, derive it from > the base class "Log::Log4perl::Filter" and define its "decide" method: > > package Log::Log4perl::Filter::MyFilter; > use base Log::Log4perl::Filter; > > sub decide { > my ($self, %p) = @_; > > # ... decide and return 1 or 0 > } > > 1; > > Values you've defined for its attributes in Log4perl's configuration > file, it will receive through its "new" method: > > log4perl.filter.MyFilter = Log::Log4perl::Filter::MyFilter > log4perl.filter.MyFilter.color = red > > will cause "Log::Log4perl::Filter::MyFilter"'s constructor to be called > like this: > > Log::Log4perl::Filter::MyFilter->new( color => "red" ); > > which in turn should be used by the custom filter class to set the > object's attributes, which later on can be consulted inside the "decide" > call. > > A Practical Example: Level Matching > Let's assume you wanted to have each logging statement written to a > different file, based on the statement's priority. Messages with > priority "WARN" are supposed to go to "/tmp/app.warn", events > prioritized as "ERROR" should end up in "/tmp/app.error", and so forth. > > Now, if you define two appenders "AppWarn" and "AppError" and assign > them both to the root logger, messages bubbling up from any loggers > below will be logged by both appenders because of Log4perl's message > propagation feature. If you limit their exposure via the appender > threshold mechanism and set "AppWarn"'s threshold to "WARN" and > "AppError"'s to "ERROR", you'll still get "ERROR" messages in "AppWarn", > because "AppWarn"'s "WARN" setting will just filter out messages with a > *lower* priority than "WARN" -- "ERROR" is higher and will be allowed to > pass through. > > What we need is a custom filter for both appenders verifying that the > priority of the oncoming messages exactly *matches* the priority the > appender is supposed to log messages of: > > log4perl.logger = WARN, AppWarn, AppError > > # Filter to match level ERROR > log4perl.filter.MatchError = Log::Log4perl::Filter::LevelMatch > log4perl.filter.MatchError.LevelToMatch = ERROR > > # Filter to match level WARN > log4perl.filter.MatchWarn = Log::Log4perl::Filter::LevelMatch > log4perl.filter.MatchWarn.LevelToMatch = WARN > > # Error appender > log4perl.appender.AppError = Log::Dispatch::File > log4perl.appender.AppError.filename = /tmp/app.err > log4perl.appender.AppError.layout = SimpleLayout > log4perl.appender.AppError.Filter = MatchError > > # Warning appender > log4perl.appender.AppWarn = Log::Dispatch::File > log4perl.appender.AppWarn.filename = /tmp/app.warn > log4perl.appender.AppWarn.layout = SimpleLayout > log4perl.appender.AppWarn.Filter = MatchWarn > > This will direct WARN messages and /tmp/app.warn and ERROR messages to > /tmp/app.error without overlaps. > > SEE ALSO > AUTHOR > Mike Schilli, <log...@pe...>, 2003 > > ------------------------------------------------------- > 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: <log...@pe...> - 2003-02-21 18:28:42
|
Welcome to the Log::Log4perl recipe of the week. Today: ============================================================ Log::Log4perl Recipe of the Week (#17): I want to log ERROR and WARN messages to different files! How can I do that? ============================================================ Let's assume you wanted to have each logging statement written to a different file, based on the statement's priority. Messages with priority "WARN" are supposed to go to "/tmp/app.warn", events prioritized as "ERROR" should end up in "/tmp/app.error". Now, if you define two appenders "AppWarn" and "AppError" and assign them both to the root logger, messages bubbling up from any loggers below will be logged by both appenders because of Log4perl's message propagation feature. If you limit their exposure via the appender threshold mechanism and set "AppWarn"'s threshold to "WARN" and "AppError"'s to "ERROR", you'll still get "ERROR" messages in "AppWarn", because "AppWarn"'s "WARN" setting will just filter out messages with a *lower* priority than "WARN" -- "ERROR" is higher and will be allowed to pass through. What we need for this is a Log4perl *Custom Filter*, newly available with Log::Log4perl 0.30, which, at the time of this writing, is available as a development release. Both appenders need to verify that the priority of the oncoming messages exactly *matches* the priority the appender is supposed to log messages of. To accomplish this task, let's define two custom filters, "MatchError" and "MatchWarn", which, when attached to their appenders, will limit messages passed on to them to those matching a given priority: log4perl.logger = WARN, AppWarn, AppError # Filter to match level ERROR log4perl.filter.MatchError = Log::Log4perl::Filter::LevelMatch log4perl.filter.MatchError.LevelToMatch = ERROR log4perl.filter.MatchError.AcceptOnMatch = true # Filter to match level WARN log4perl.filter.MatchWarn = Log::Log4perl::Filter::LevelMatch log4perl.filter.MatchWarn.LevelToMatch = WARN log4perl.filter.MatchWarn.AcceptOnMatch = true # Error appender log4perl.appender.AppError = Log::Dispatch::File log4perl.appender.AppError.filename = /tmp/app.err log4perl.appender.AppError.layout = SimpleLayout log4perl.appender.AppError.Filter = MatchError # Warning appender log4perl.appender.AppWarn = Log::Dispatch::File log4perl.appender.AppWarn.filename = /tmp/app.warn log4perl.appender.AppWarn.layout = SimpleLayout log4perl.appender.AppWarn.Filter = MatchWarn The appenders "AppWarn" and "AppError" defined above are logging to "/tmp/app.warn" and "/tmp/app.err" respectively and have the custom filters "MatchWarn" and "MatchError" attached. This setup will direct all WARN messages, issued anywhere in the system, to /tmp/app.warn (and ERROR messages to /tmp/app.error) -- without any overlaps. Have fun! Until next week. -- Mike ################################### # Mike Schilli # # log...@pe... # # http://perlmeister.com # # http://log4perl.sourceforge.net # ################################### |
From: Mike S. <msc...@ao...> - 2003-02-19 19:38:49
|
Pet...@Dr... wrote: > I prefer to define constants for the return values (and put > all constants in a common class Log::Log4per::Constants). > A filter may return > > Log::Log4perl::Constants::OK > Log::Log4perl::Constants::DECLINED > > The constants may be imported by default so that you can write > > log4perl.filter.MyFilter = sub { \ > my %p = @_; \ > (%p{log4p_level} == WARN) ? OK : DECLINED; \ > Nice. Definitely the correct way of defining it and being flexible to add stuff in the future. On the other hand, I really like constructs like sub { /x/ and /y/ } which gets really hairy/lengthy with constants. > 2. Can we have a sub here as well? Maybe I want to make my > logic dependent on localtime() or the moon phases or have a > switch() on hostnames to have development and production > logic in one config file or... > You can do that in two different ways: Define the "advanced" logic in the filters used by the Bool filter (which I think I would prefer) but, since yesterday, the "logic" field in the Bool filter just gets "eval"ed as regular Perl code, so you can put in there whatever you like. The latest version from CVS sports almost everything already, please check it out! > 3. What a about message redirection? Are there plans for the > future that a filter (or whatever) can forward a message to > another appender? > Interesting feature, I haven't thought of that yet (neither have the log4j folks). I gotta think about that. Can you imagine a use case? Also, we could implement that either as a Log4perl-centric feature based on filter return code (as you suggested) or as a function/method call inside the filter (redir_to_appender(blah)). -- -- Mike Mike Schilli log...@pe... |
From: <log...@pe...> - 2003-02-17 04:01:11
|
Welcome to the Log::Log4perl recipe of the week. Today: ============================================================ Log::Log4perl Recipe of the Week (#16): How can I bundle several log messages into one? ============================================================ Would you like to tally the messages arriving at your appender and dump out a summary once they're exceeding a certain threshold? So that something like $logger->error("Blah"); $logger->error("Blah"); $logger->error("Blah"); won't be logged as Blah Blah Blah but as [3] Blah instead? If you'd like to hold off on logging a message until it has been sent a couple of times, you can roll that out by creating a buffered appender. Let's define a new appender like package Log::Dispatch::Tally; use Log::Dispatch::Output; use base qw( Log::Dispatch::Output ); sub new { my($class, %options) = @_; my $self = { maxcount => 5, %options }; bless $self, $class; $self->_basic_init( %options ); $self->{last_message} = ""; $self->{last_message_count} = 0; return $self; } with two additional instance variables "last_message" and "last_message_count", storing the content of the last message sent and a counter of how many times this has happened. Also, it features a configuration parameter "maxcount" which defaults to 5 in the snippet above but can be set in the Log4perl configuration file like this: log4perl.logger = INFO, A log4perl.appender.A=Log::Dispatch::Tally log4perl.appender.A.maxcount = 3 The main tallying logic lies in the appender's "log_message" method, which is called every time Log4perl thinks a message needs to get logged by our appender: sub log_message { my($self, %params) = @_; # Message changed? Print buffer. if($self->{last_message} and $params{message} ne $self->{last_message}) { print "[$self->{last_message_count}]: " . "$self->{last_message}"; $self->{last_message_count} = 1; $self->{last_message} = $params{message}; return; } $self->{last_message_count}++; $self->{last_message} = $params{message}; # Threshold exceeded? Print, reset counter if($self->{last_message_count} >= $self->{maxcount}) { print "[$self->{last_message_count}]: " . "$params{message}"; $self->{last_message_count} = 0; $self->{last_message} = ""; return; } } We basically just check if the oncoming message in $param{message} is equal to what we've saved before in the "last_message" instance variable. If so, we're increasing "last_message_count". We print the message in two cases: If the new message is different than the buffered one, because then we need to dump the old stuff and store the new. Or, if the counter exceeds the threshold, as defined by the "maxcount" configuration parameter. Please note that the appender always gets the fully rendered message and just compares it as a whole -- so if there's a date/timestamp in there, that might confuse your logic. You can work around this by specifying %m %n as a layout and add the date later on in the appender. Or, make the comparison smart enough to omit the date. At last, don't forget what happens if the program is being shut down. If there's still messages in the buffer, they should be printed out at that point. That's easy to do in the appender's DESTROY method, which gets called at object destruction time: sub DESTROY { my($self) = @_; if($self->{last_message_count}) { print "[$self->{last_message_count}]: " . "$self->{last_message}"; return; } } This will ensure that none of the buffered messages are lost. Happy buffering! Have fun! Until next week. -- Mike ################################### # Mike Schilli # # log...@pe... # # http://perlmeister.com # # http://log4perl.sourceforge.net # ################################### |
From: <msc...@ao...> - 2003-02-16 03:13:26
|
Hey Kevin and all, here's a design proposal for the soon-to-come "custom filters" Log4perl feature. Let me know how if you like it! To be clear, nothing of what's mentioned below has been implemented yet (it's checked in under Log/Log4perl/Filter.pm, though) -- just wanted to run this by you to make sure I haven't overlooked anything. Comments, questions, counter-proposal welcome, as always :) -- -- Mike ############################ # Mike Schilli # # log...@pe... # # http://perlmeister.com # # log4perl.sourceforge.net # ############################ NAME Log::Log4perl::Filter - Log4perl Custom Filter Base Class SYNOPSIS use Log::Log4perl; Log::Log4perl->init(<<'EOT'); log4perl.logger = INFO, Screen log4perl.filter.MyFilter = sub { /let this through/ } log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.Filter = MyFilter log4perl.appender.Screen.layout = Log::Log4perl::Layout::SimpleLayout EOT # Define a logger my $logger = Log::Log4perl->get_logger("Some"); # Let this through $logger->info("Here's the info, let this through!"); # Suppress this $logger->info("Here's the info, suppress this!"); DESCRIPTION Log4perl allows the use of customized filters in its appenders to control the output of messages. These filters might grep for certain text chunks in a message, verify that its priority matches or exceeds a certain level or that this is the 10th time the same message has been submitted -- and come to a log/no log decision based upon these circumstantial facts. Filters carry names and can be specified in two different ways in the Log4perl configuration file: As subroutines or as filter classes. Here's a simple filter named "MyFilter" which just verifies that the oncoming message matches the regular expression "/let this through/i": log4perl.filter.MyFilter = sub { /let this through/i } It exploits the fact that when the filter is called on a message, Perl's special $_ variable will be set to the (rendered) message to be logged. The filter subroutine is expected to return a true value if it wants the message to be logged or a false value if doesn't. Also, Log::Log4perl will pass the same arguments to the filter function as it would to the corresponding appender. Here's an example of a filter checking the priority of the oncoming message: log4perl.filter.MyFilter = sub { \ my %p = @_; \ (%p{log4p_level} == WARN) ? 1 : 0; \ } If the message priority equals "WARN", it returns a true value, causing the message to be logged. For common tasks like this, there's already a set of predefined filters available. To perform a level match, it's much cleaner to use Log4perl's "LevelMatch" filter instead: log4perl.filter.MyFilter = Log::Log4perl::Filter::LevelMatch log4perl.filter.MyFilter.LevelToMatch = WARN Once a filter has been defined by name and class, its values can be assigned to its attributes, just as the "WARN" value to the "LevelToMatch" attribute above. Attaching a filter to an appender Attaching a filter to an appender is as easy as assigning its name to the appender's "Filter" attribute: log4perl.appender.MyAppender = MyFilter This will cause "Log::Log4perl" to call the filter subroutine/method every time a message is supposed to be passed to the appender. Depending on the filter's return value, "Log::Log4perl" will either continue as planned or withdraw. Combining filters with Log::Log4perl::Filter::Bool Sometimes, it's useful to combine the output of various filters to arrive at a log/no log deciscion. While Log4j, Log4perl's mother ship, chose to implement this feature as a filter chain, similar to Linux' IP chains, Log4perl tries a different approach. Typically, filter results will not need to be passed along in chains but combined in a programmatic manner using boolean logic. "Log if this filter says 'yes' and that filter says 'no'" is a fairly common requirement but hard to implement as a chain. "Log::Log4perl::Filter::Bool" is a special predefined custom filter for Log4perl which combines the results of other custom filters in arbitrary ways, using boolean expressions: log4perl.logger = WARN, AppWarn, AppError log4perl.filter.Match1 = sub { /let this through/ } log4perl.filter.Match2 = sub { /and that, too/ } log4perl.filter.MyBool = Log::Log4perl::Filter::Bool log4perl.filter.MyBool.logic = Match1 || Match2 log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.Filter = MyBool log4perl.appender.Screen.layout = Log::Log4perl::Layout::SimpleLayout "Log::Log4perl::Filter::Bool"'s boolean expressions allow for combining different appenders by name using AND (&& or &), OR (|| or |) and NOT (!) as logical expressions. Parentheses are used for grouping. Precedence follows standard Perl. Here's a bunch of examples: Match1 && !Match2 # Match1 and not Match2 !(Match1 || Match2) # Neither Match1 nor Match2 (Match1 && Match2) || Match3 # Both Match1 and Match2 or Match3 Writing your own filter classes If none of Log::Log4perl's predefined filter classes fits your needs, you can easily roll your own: Just define a new class, derive it from the base class "Log::Log4perl::Filter" and define its "decide" method: package Log::Log4perl::Filter::MyFilter; use base Log::Log4perl::Filter; sub decide { my ($self, %p) = @_; # ... decide and return 1 or 0 } 1; Values you've defined for its attributes in Log4perl's configuration file, it will receive through its "new" method: log4perl.filter.MyFilter = Log::Log4perl::Filter::MyFilter log4perl.filter.MyFilter.color = red will cause "Log::Log4perl::Filter::MyFilter"'s constructor to be called like this: Log::Log4perl::Filter::MyFilter->new( color => "red" ); which in turn should be used by the custom filter class to set the object's attributes, which later on can be consulted inside the "decide" call. A Practical Example: Level Matching Let's assume you wanted to have each logging statement written to a different file, based on the statement's priority. Messages with priority "WARN" are supposed to go to "/tmp/app.warn", events prioritized as "ERROR" should end up in "/tmp/app.error", and so forth. Now, if you define two appenders "AppWarn" and "AppError" and assign them both to the root logger, messages bubbling up from any loggers below will be logged by both appenders because of Log4perl's message propagation feature. If you limit their exposure via the appender threshold mechanism and set "AppWarn"'s threshold to "WARN" and "AppError"'s to "ERROR", you'll still get "ERROR" messages in "AppWarn", because "AppWarn"'s "WARN" setting will just filter out messages with a *lower* priority than "WARN" -- "ERROR" is higher and will be allowed to pass through. What we need is a custom filter for both appenders verifying that the priority of the oncoming messages exactly *matches* the priority the appender is supposed to log messages of: log4perl.logger = WARN, AppWarn, AppError # Filter to match level ERROR log4perl.filter.MatchError = Log::Log4perl::Filter::LevelMatch log4perl.filter.MatchError.LevelToMatch = ERROR # Filter to match level WARN log4perl.filter.MatchWarn = Log::Log4perl::Filter::LevelMatch log4perl.filter.MatchWarn.LevelToMatch = WARN # Error appender log4perl.appender.AppError = Log::Dispatch::File log4perl.appender.AppError.filename = /tmp/app.err log4perl.appender.AppError.layout = SimpleLayout log4perl.appender.AppError.Filter = MatchError # Warning appender log4perl.appender.AppWarn = Log::Dispatch::File log4perl.appender.AppWarn.filename = /tmp/app.warn log4perl.appender.AppWarn.layout = SimpleLayout log4perl.appender.AppWarn.Filter = MatchWarn This will direct WARN messages and /tmp/app.warn and ERROR messages to /tmp/app.error without overlaps. SEE ALSO AUTHOR Mike Schilli, <log...@pe...>, 2003 |
From: Kevin G. <ke...@go...> - 2003-02-11 17:05:34
|
That's an interesting point, return codes. If init() has any problems=20 it will die, otherwise the program might continue with a=20 half-initialized logger, with undefined results. Not everybody is as=20 conscientous as yourself in checking return codes, and we didn't see any=20 point in failing init() but continuing the program. So the answer to your question is don't check the return code from init.=20 If you want to catch init() in the act of dying, you can use the=20 try/catch paradigm eval { Log::Log4perl->init($LogConfFile)=09 }; if ($@){ die "Log4perl died with this message: $@"; } Tim M=FCller-Seydlitz wrote: > Hi, > please allow this newbie question. >=20 > I am trying to run the following initialization with log4perl. >=20 > use Log::Log4perl qw(get_logger); > Log::Log4perl->init($LogConfFile) or die "Log configuration cannot be=20 > read from file $LogConfFile!"; > my $logger =3D get_logger("MD::NetScheduler"); >=20 > Unfortunately init does not return true, even though the $LogConfFile=20 > definitely exists. > Its content is here: >=20 > log4perl.rootLogger=3DDEBUG, LOGFILE >=20 > log4perl.appender.LOGFILE=3DLog::Dispatch::File > log4perl.appender.LOGFILE.filename=3D/home/mdnet/log/myerrs.log > log4perl.appender.LOGFILE.mode=3Dappend >=20 > log4perl.appender.LOGFILE.layout=3DPatternLayout > log4perl.appender.LOGFILE.layout.ConversionPattern=3D%d %6p %20c=20 > %15F{1}:%5L - %m %n >=20 > Your help is very much appreciated. > I am running Log4perl 0.29 >=20 > Regards > Tim >=20 >=20 >=20 > ------------------------------------------------------- > This SF.NET email is sponsored by: > SourceForge Enterprise Edition + IBM + LinuxWorld =3D Something 2 See! > http://www.vasoftware.com > _______________________________________________ > log4perl-devel mailing list > log...@li... > https://lists.sourceforge.net/lists/listinfo/log4perl-devel --=20 Happy Trails . . . Kevin M. Goess (and Anne and Frank) 904 Carmel Ave. Albany, CA 94706 (510) 525-5217 |
From: <tm...@na...> - 2003-02-11 14:45:07
|
Hi, please allow this newbie question. I am trying to run the following initialization with log4perl. use Log::Log4perl qw(get_logger); Log::Log4perl->init($LogConfFile) or die "Log configuration cannot be read from file $LogConfFile!"; my $logger = get_logger("MD::NetScheduler"); Unfortunately init does not return true, even though the $LogConfFile definitely exists. Its content is here: log4perl.rootLogger=DEBUG, LOGFILE log4perl.appender.LOGFILE=Log::Dispatch::File log4perl.appender.LOGFILE.filename=/home/mdnet/log/myerrs.log log4perl.appender.LOGFILE.mode=append log4perl.appender.LOGFILE.layout=PatternLayout log4perl.appender.LOGFILE.layout.ConversionPattern=%d %6p %20c %15F{1}:%5L - %m %n Your help is very much appreciated. I am running Log4perl 0.29 Regards Tim |
From: Mike S. <msc...@ao...> - 2003-02-11 00:33:49
|
... forwarded ... |
From: Mike S. <msc...@ao...> - 2003-02-11 00:32:48
|
... forwarded ... |
From: <log...@pe...> - 2003-02-10 07:37:30
|
Welcome to the Log::Log4perl recipe of the week. Today: ============================================================ Log::Log4perl Recipe of the Week (#15): How can I collect all FATAL messages in an extra log file? ============================================================ Suppose you have employed Log4perl all over your system and you've already activated logging in various subsystems. On top of that, without disrupting any other settings, how can you collect all FATAL messages all over the system and send them to a separate log file? If you define a root logger like this: log4perl.logger = FATAL, File log4perl.appender.File = Log::Dispatch::File log4perl.appender.File.filename = /tmp/fatal.txt log4perl.appender.File.layout = PatternLayout log4perl.appender.File.layout.ConversionPattern= %d %m %n # !!! Something's missing ... you'll be surprised to not only receive all FATAL messages issued anywhere in the system, but also everything else -- gazillions of ERROR, WARN, INFO and even DEBUG messages will end up in your fatal.txt logfile! Reason for this is Log4perl's (or better: Log4j's) appender additivity. Once a lower-level logger decides to fire, the message is going to be forwarded to all appenders upstream -- without further priority checks with their attached loggers. There's a way to prevent this, however: If your appender defines a minimum threshold, only messages of this priority or higher are going to be logged. So, just add log4perl.appender.File.Threshold = FATAL to the configuration above, and you'll get what you wanted in the first place: An overall system FATAL message collector. Have fun! Until next week. -- Mike ################################### # Mike Schilli # # log...@pe... # # http://perlmeister.com # # http://log4perl.sourceforge.net # ################################### |
From: Roger P. <rog...@ea...> - 2003-02-06 13:29:05
|
Mike Schilli wrote: > rog...@ea... wrote: > >> >> PPM interactive shell (2.1.5) - type 'help' for available commands. >> PPM> install "http://log4perl.sourceforge.net/ppm/Log-Log4perl.ppd" >> Install package >> '"http://log4perl.sourceforge.net/ppm/Log-Log4perl.ppd"?' (y/N): > > > Just tried the same thing with ppm 2.1.6 (latest with Activestate > 5.6.1) and it works fine. Could it be that ppm 2.1.5 is buggy? > I've just tried it (after a reboot) on the first machine that had problems with Log-Log4perl.tar.gz. It works now, no problem. Strange because yesterday I tried it several times on two different machines. Most likely some internal network related problem. Thanks! Roger P |
From: Mike S. <msc...@ao...> - 2003-02-05 23:02:31
|
rog...@ea... wrote: > > PPM interactive shell (2.1.5) - type 'help' for available commands. > PPM> install "http://log4perl.sourceforge.net/ppm/Log-Log4perl.ppd" > Install package > '"http://log4perl.sourceforge.net/ppm/Log-Log4perl.ppd"?' (y/N): Just tried the same thing with ppm 2.1.6 (latest with Activestate 5.6.1) and it works fine. Could it be that ppm 2.1.5 is buggy? -- -- Mike Mike Schilli log...@pe... |
From: Jim C. <jc...@di...> - 2003-02-05 20:01:34
|
I just discovered that Log4perl, at least when used in perl debugger, will truncate open logs, rather than close and reopen. This means that `tail -f` on your logfiles will continue to work ! [14:49:33.069] Screen.Match.debug: try match against eqpa Mask tail: rootlog: file truncated [14:51:31.364] Screen.import.info: loading screens: eqpa eqph eqpu fa gcpost VERY COOL ! |