Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

log4perl dbi appender argument formatting

by quixadhal (Novice)
on Apr 08, 2014 at 14:20 UTC ( #1081511=perlquestion: print w/replies, xml ) Need Help??
quixadhal has asked for the wisdom of the Perl Monks concerning the following question:

I've recently revisited an old project that uses Log::Log4perl, and decided it would be good to have it log to both a file and an SQL database. In future, it will also want to send output to sockets, but that's another story. So, I happily poked around the internet and found out how to use the DBI Appender, and all was working fine until I made an actual complex logging statement. Then, I ran into the dread Log4perl: DBI appender error: 'called with 6 bind variables when 5 are needed' Of course! As suggested, I had set the layout to NoopLayout and used bound parameters... which works just fine when using a single fixed string as your logged data, but of course most of my real logging is done using the logger as if it were sprintf.
$log->info("Data directory: %s", $options->{'dir'});
My naive through was to pass a coderef in as the warp_message parameter, hoping I could just have it do the sprintf conversion to flatten things into a single argument that would become the last bound parameter passed...
my $spr = sub { my $fmt = shift; return sprintf $fmt, @_; };
and then...
my $conf = qq! log4perl.rootLogger = TRACE, DBAppndr log4perl.appender.DBAppndr = Log::Log4perl::Appender::DBI log4perl.appender.DBAppndr.datasource = $dsn log4perl.appender.DBAppndr.username = $db_user log4perl.appender.DBAppndr.password = $db_passwd log4perl.appender.DBAppndr.sql = INSERT INTO log (level, ti +mestamp, method, line, message) VALUES (?,?,?,?,?) log4perl.appender.DBAppndr.params.1 = %p log4perl.appender.DBAppndr.params.2 = %d{yyyy-MM-dd HH:mm:ss.SSS +} log4perl.appender.DBAppndr.params.3 = %M log4perl.appender.DBAppndr.params.4 = %L log4perl.appender.DBAppndr.usePreparedStmt = 1 log4perl.appender.DBAppndr.layout = Log::Log4perl::Layou +t::NoopLayout log4perl.appender.DBAppndr.warp_message = $spr !; Log::Log4perl::init( \$conf );
This resulted in the unfortunate Can't use string ("Can't use string ("Data director"...) as a HASH ref while "strict refs" in use at /usr/local/share/perl/5.14.2/Log/Log4perl/ line 281. I also have loggers to the screen and file, but the DBI one is the problem child, and while he's having a tantrum, the others don't even get to run. Obviously, things would work fine if I used sprintf myself at the caller level, but that defeats the purpose of having a nice clean logging statement. Any suggestions?

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1081511]
Approved by Bloodnok
Front-paged by Bloodnok
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (7)
As of 2018-01-22 18:22 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (235 votes). Check out past polls.