http://www.perlmonks.org?node_id=1033823

fritz1968 has asked for the wisdom of the Perl Monks concerning the following question:

Hello

I am trying to setup a logging using log4perl where the filename can be set dynamically. Of course I am having troubles. Here is my current code:

my $logFile="$logDir/$logfileName"; $logConf = q( log4perl.category.Foo.Bar = INFO, Logfile, Screen log4perl.appender.Logfile = log::Log4perl::Appender::File log4perl.appender.Logfile.filename = logs/frank.txt log4perl.appender.Logfile.layout = Log::Log4perl::Layou +t::PatternLayout log4perl.appender.Logfile.layout.ConversionPattern = %d + %-25M %X{logref} %p %m %n log4perl.appender.Screen = Log::Log4perl::Appende +r::Screen log4perl.appender.Screen.stderr = 0 log4perl.appender.Screen.layout = Log::Log4perl::Layout:: +SimpleLayout ); Log::Log4perl->init(\$logConf);

The problem is that I don't want each file name to be named "logs/frank.txt". I would rather have something like:

logs/frank.<date>.txt

Any help would be greatly appreciated.
Thanks,
Frank

Replies are listed 'Best First'.
Re: log4Perl dynamic filename
by stefbv (Curate) on May 16, 2013 at 12:46 UTC

    Use a sub reference function to return the file name, like this:

    log4perl.appender.Logfile.filename = sub { get_log_filename(); }

    Regards, Stefan

    Updated.

Re: log4Perl dynamic filename
by Anonymous Monk on May 16, 2013 at 13:23 UTC
Re: log4Perl dynamic filename
by dd-b (Monk) on May 16, 2013 at 22:47 UTC

    I do it like this:

    use Log::Log4perl; my $logfile = 'clean.log'; unlink $logfile; # ignore errors do { # Isolate # Log configuration. # If you go for interpolation, escape the {} in the pattern or use # different delimiters or something. my $lconf = q{ log4perl.logger = TRACE, ap1 log4perl.appender.ap1 = Log::Log4perl::Appender::File log4perl.appender.ap1.filename = } . $logfile . q' log4perl.appender.ap1.layout = Log::Log4perl::Layout::PatternLayou +t log4perl.appender.ap1.layout.ConversionPattern = %d{yyyyMMdd HH:mm +:ss.SSSS} %5p %F{1} %L: %m %n log4perl.appender.ap2 = Log::Log4perl::Appender::Screen log4perl.appender.ap2.layout = Log::Log4perl::Layout::PatternL +ayout log4perl.appender.ap2.layout.ConversionPattern = %d{yyyyMMdd H +H:mm:ss.SSSS} %5p %F{1} %L: %m %n '; # unclear, but this MIGHT mean something. Log::Log4perl::init ( \$lconf ) or die "Log init failed"; }; # Isolate my $logger = Log::Log4perl->get_logger('Test');
    That is, by using substitution within the quoted string config.

    You could also do it using function-call config, and possibly by doing a string config and then overriding that one thing with a function call, I believe, but I haven't done that, so I won't give you fake example code.

      Hello fritz1968, I personally prefer to use config files for configuration purposes, so I have a file pllog.conf:
      log4perl.rootLogger = TRACE, FileApp, XMLAppender, ScreenApp log4perl.appender.FileApp = Log::Log4perl::Appender::File log4perl.appender.FileApp.filename = sub { my $Me=$0; $Me =~ s/^.*\\// +; $Me =~ s/\..*//; return "$Me.log" } log4perl.appender.FileApp.layout = PatternLayout log4perl.appender.FileApp.layout.ConversionPattern = %d{ISO8601} (%- +13F: %04L) %m%n
      And somewhere in perl code:
      use Log::Log4perl qw(get_logger); Log::Log4perl->init("pllog.conf"); my $logger = get_logger("My_Tools.$Me");
      Used in this way, you get a logfile with the same name as your perl file but with .log instead of .pl. I only showed the file appender path, as you requsted. You can change this approach easily to fit your needs. And you can change the whole log4perl thing without changing your code.
Re: log4Perl dynamic filename
by periapt (Hermit) on May 20, 2013 at 12:24 UTC
    For many projects, I like to define a simple functional logging configuration.
    sub InitLogger { my $logfile = shift; my $logconf = q| log4perl.logger.[package_name] = INFO, Log +File log4perl.appender.LogFile = Log::Log4perl::Appende +r::File log4perl.appender.LogFile.filename = LOGFILE log4perl.appender.LOG.mode = append log4perl.appender.LogFile.layout = PatternLa +yout log4perl.appender.LogFile.layout.ConversionPattern = %d %5p> % +m%n |; $logconf =~ s/LOGFILE/$logfile/; Log::Log4perl->init( \$logconf ); return Log::Log4perl::get_logger("[package_name"); } # end InitLogger();
    I set the log4perl.appender.LogFile.filename option to an arbitrary value 'LOGNAME' so that I can replace it in the string later. Not sure why but I've found this to be more stable than using variable substitution inside the config string itself.

    If my projects grows to encompass several program files with almost identical log specs (except maybe for filename), I can pull the function into a library and share

    PJ
    use strict; use warnings; use diagnostics;