Search code examples
perllogfilelog4perl

Can I write some results to a file using Log::Log4perl without depending on the default levels?


I want to log some results into a file withot messing with the leves of my logs. Is it possible to do that with Log::Log4perl. I have tried to follow the documentation, but I only was able to find that it depends on the log level to printo a file? as in here :

og::Log4perl->easy_init( { level    => $DEBUG,
                            file     => ">>test.log",
                            layout   => '%F{1}-%L-%M: %m%n' },
                          { level    => $DEBUG,
                            file     => "STDOUT",
                            layout   => '%m%n' },
                        );

But I want to keep logging my stuff in screen and only put another messages into the log file. But I have not been able to find a way to put the result to the log:

use strict;
use warnings;
use Log::Log4perl;
use Win32::Console::ANSI;

my $results = "result.txt";
my $conf = q(
  log4perl.appender.SCREEN         = Log::Log4perl::Appender::ScreenColoredLevels
  log4perl.appender.SCREEN.layout  = Log::Log4perl::Layout::PatternLayout
  log4perl.appender.SCREEN.color.INFO = bright_white    
  log4perl.appender.SCREEN.color.WARN = bright_yellow    
  log4perl.appender.SCREEN.color.ERROR = bright_red    
  log4perl.appender.SCREEN.layout.ConversionPattern = [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5p] %m  %50C::%L %n
);

my $log_level = "TRACE";
my $log_level_conf = "log4perl.category.".__FILE__." = ".$log_level.", SCREEN\n";   
$conf = $log_level_conf.$conf;
    
Log::Log4perl::init( \$conf );

my $log = Log::Log4perl::get_logger(__FILE__);

$log->info("INFO");
$log->debug("DEBUG");
$log->error("error");
$log->fatal("FATAL");
$log->trace("TRACE");

print "\n\n";

$log->info("Im doing foo");
$log->debug( "doing foo");
$log->trace( "crap from foo");
$log->info( "Im doing bar");
$log->debug( "Im doing foo");
$log->trace( "crap from bar");

# $log->result "Foo and bar done";

The line where it says result is the one that I´m looking for, some way to have a diferent function to write into the log using the same $log.

Is this possible?

Edit: Following the suggestion by @amit bhosale I'm still not able to make it work:

use strict;
use warnings;
use Log::Log4perl;
use Win32::Console::ANSI;


my $conf = q(

    log4perl.category = TRACE, AppResult

    log4perl.appender.SCREEN         = Log::Log4perl::Appender::ScreenColoredLevels
    log4perl.appender.SCREEN.layout  = Log::Log4perl::Layout::PatternLayout
    log4perl.appender.SCREEN.color.INFO = bright_white    
    log4perl.appender.SCREEN.color.WARN = bright_yellow    
    log4perl.appender.SCREEN.color.ERROR = bright_red    
    log4perl.appender.SCREEN.layout.ConversionPattern = [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5p] %m  %50C::%L %n
    
    
    # Custom RESULT logs
    log4perl.filter.ResultsFilter  = Log::Log4perl::Filter::LevelMatch
    log4perl.filter.ResultsFilter.LevelToMatch  = RESULT
    log4perl.filter.ResultsFilter.AcceptOnMatch = true  
     
    log4perl.appender.AppResult = Log::Log4perl::Appender::File
    log4perl.appender.AppResult.filename = results.log
    log4perl.appender.AppResult.mode=append  
    log4perl.appender.AppResult.Filter   = ResultsFilter
    log4perl.appender.AppResult.layout  = Log::Log4perl::Layout::PatternLayout
    log4perl.appender.AppResult.layout.ConversionPattern = [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5p] %m  %50C::%L %n


);

my $log_level = "TRACE";
my $log_level_conf = "log4perl.category.".__FILE__." = ".$log_level.", SCREEN\n";   
$conf = $log_level_conf.$conf;

Log::Log4perl::Logger::create_custom_level("RESULT", "WARN");
Log::Log4perl::init( \$conf );

my $log = Log::Log4perl::get_logger(__FILE__);

$log->info("INFO");
$log->debug("DEBUG");
$log->error("ERROR");
$log->warn("WARN");
$log->fatal("FATAL");
$log->trace("TRACE");

print "\n\n";

$log->info("Im doing foo");
$log->debug( "doing foo");
$log->trace( "crap from foo");
$log->info( "Im doing bar");
$log->debug( "Im doing foo");
$log->trace( "crap from bar");

$log->log('RESULT', "Foo and bar done");  

I´m getting a priority RESULT isn't numeric at test_logs.pl line 60. exception


Solution

  • Another way to achieve (without creating custom level). (above solution is valid this is just another way)

    Created log.conf file

    ############################################################
    # A simple root logger with a Log::Log4perl::Appender::File 
    # file appender in Perl.
    ############################################################
    #There are six predefined log levels: FATAL, ERROR, WARN, INFO, DEBUG, and TRACE
    # (in descending priority). Your configured logging level has to at least match 
    #the priority of the logging message.
    
    #If your configured logging level is TRACE, then messages logged with info(), 
    #debug(), and trace() fatal(), error() and warn() will make their way through, 
    #because their priority is higher or equal than the configured setting.
    
    #This enables messages of priority TRACE or higher in the root hierarchy
    # if a function/method wants a reference to the logger, it just calls the Logger's static get_logger($category) 
    #method to obtain a reference to the one and only possible logger object 
    #of a certain category.
    log4perl.category.My.SCREEN = TRACE, Screen
    #Appenders will be triggered whenever the configured logging 
    #level requires a message to be logged
    # log a message (display) on screen
    log4perl.appender.Screen        = Log::Log4perl::Appender::ScreenColoredLevels
    log4perl.appender.Screen.layout  = Log::Log4perl::Layout::PatternLayout
    log4perl.appender.Screen.color.INFO = bright_white    
    log4perl.appender.Screen.color.WARN = bright_yellow    
    log4perl.appender.Screen.color.ERROR = bright_red    
    log4perl.appender.Screen.layout.ConversionPattern = [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5p] %m  %50C::%L %n
    
    # RESULT appender
    log4perl.category.My.Result= INFO, resultlog
    # log a message to log file (in this case app.result file)
    log4perl.appender.resultlog= Log::Log4perl::Appender::File
    log4perl.appender.resultlog.filename = app.result
    log4perl.appender.resultlog.mode=append
    log4perl.appender.resultlog.layout=PatternLayout
    log4perl.appender.resultlog.layout.ConversionPattern=[%p] %F %L %c - %m%n 
    

    Main perl script

    use strict;
    use warnings;
    use Log::Log4perl;
    use Win32::Console::ANSI;
    
    #configuration file is saved as log.conf, you need to read it in the startup section of your code
    # After this done somewhere in the code, you can retrieve logger objects anywhere in the code.
    # provide log configuration file path
    Log::Log4perl->init("log.conf");
    
    #Log::Log4perl uses categories to determine if a log statement 
    #in a component should be executed or suppressed at the current logging level. 
    #Most of the time, these categories are just the classes the log statements
    my $log_screen = Log::Log4perl->get_logger("My::SCREEN");
    my $log_result = Log::Log4perl->get_logger("My::Result");
    # sample logging statement
    $log_screen->info("INFO");
    $log_screen->debug("DEBUG");
    $log_screen->error("ERROR");
    $log_screen->warn("WARN");
    $log_screen->fatal("FATAL");
    $log_screen->trace("TRACE");
    # result
    $log_result->info("this is a result message1");
    

    Output to file (example)

    [INFO] log.pl 24 My.Result - this is a result message1
    

    Output to Screen (different colour)

    [2020-08-16 20:52:40.721] [INFO ] INFO                                                main::16
    [2020-08-16 20:52:40.723] [DEBUG] DEBUG                                                main::17
    [2020-08-16 20:52:40.723] [ERROR] ERROR                                                main::18
    [2020-08-16 20:52:40.725] [WARN ] WARN                                                main::19
    [2020-08-16 20:52:40.726] [FATAL] FATAL                                                main::20
    [2020-08-16 20:52:40.727] [TRACE] TRACE                                                main::21