1

My goal is, to log "debug"-messages (and subsequent levels: info,warning, fatal,...) to a file but only "warnings"/fatal/error to the screen. Both at the same time.

I tried with easy_init ("stealth logging"):

Log::Log4perl->easy_init(
    { level => $DEBUG, file => ":utf8> ./log_" . basename($0) . "_.log" },
    { level => $WARN, file => 'STDOUT' },
);

... BUT the level of the second definition overwrites general loglevel.

if (false){
    WARN "some bad thing";  # print this to the screen AND to the file
}else{
    do_something;
    DEBUG "doing something";    # print this just to the file
    if (bla){WARN "another bad thing"}
}

In this case the warning goes to the screen and the file correctly, BUT the "DEBUG" message will not get printed (perl 5.26)

Putting the { level => $DEBUG ...-line after the {level => $WARN ...-line, then all warn- and debug-messages are printed on the screen and to the file.

Can someone please guide me, how to do this (if even possible)? Do I need to clarify?

MacMartin
  • 2,366
  • 1
  • 24
  • 27

1 Answers1

2

The following perl minimal working example:

  • prints to file DEBUG and higher levels
  • prints to screen WARN and higher levels

I didn't use easy_init as the detailed configuration is more detailed. I have comments in the script that describe what the configuration is doing. Let me know if it needs more detail.

use strict;
use Log::Log4perl qw(:easy);

# rootlogger prints to "Logfile" and "Screen"
# "Logfile" and "Screen" are then defined with the proper appender (File and Screen)
# and the proper Threshold is used to limit what goes in each appender

my $conf = q(
log4perl.rootLogger=DEBUG,Logfile,Screen

log4perl.appender.Logfile           = Log::Log4perl::Appender::File
log4perl.appender.Logfile.filename  = /home/USER/test.log
log4perl.appender.Logfile.mode      = append
log4perl.appender.Logfile.utf8      = 1
log4perl.appender.Logfile.Threshold = DEBUG
log4perl.appender.Logfile.recreate  = 1
log4perl.appender.Logfile.layout    = Log::Log4perl::Layout::SimpleLayout

log4perl.appender.Screen            = Log::Log4perl::Appender::Screen
log4perl.appender.Screen.stderr     = 0
log4perl.appender.Screen.Threshold  = WARN
log4perl.appender.Screen.layout     = Log::Log4perl::Layout::SimpleLayout
);
Log::Log4perl::init( \$conf );

my $logger = Log::Log4perl->get_logger( 'foo' );

WARN "some bad thing";      # print this to the screen AND to the file
DEBUG "doing something";    # print this just to the file
~ $ perl log4perl.pl
WARN - some bad thing

~ $ cat test.log 
WARN - some bad thing
DEBUG - doing something

Versions

I tested with:

  • OS: Ubuntu 14.04.5 LTS
  • perl: v5.18.2
  • Log::Log4perl: 1.49 (and 1.41)
vkats
  • 469
  • 1
  • 4
  • 14
  • this is great, thank you. I have tried with the detailed method before, but didn't really got it working. But nevertheless I still wait, if there is/someone has an `easy_init` solution (less typing/less memorizing/better readability (<- that may be subjective) ). – MacMartin Mar 05 '19 at 08:17
  • Thanks @eli I added the versions I ran the MWE on to avoid any confusion (I should have done it in the first place). What kind of problems did you ran into? – vkats Mar 05 '19 at 10:48
  • sorry for the confusion. When I tried this in the past, it didn't work - but your answer is working correctly and I gave it an upvote – MacMartin Mar 05 '19 at 11:48