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 |