我可以使用 Log::Log4perl 将一些结果写入文件而不依赖于默认级别吗?
Can I write some results to a file using Log::Log4perl without depending on the default levels?
我想将一些结果记录到一个文件中,而不会弄乱我的日志级别。是否可以使用 Log::Log4perl
来做到这一点。我试图按照文档进行操作,但我只能发现它取决于日志级别来打印文件?如 here :
og::Log4perl->easy_init( { level => $DEBUG,
file => ">>test.log",
layout => '%F{1}-%L-%M: %m%n' },
{ level => $DEBUG,
file => "STDOUT",
layout => '%m%n' },
);
但我想继续在屏幕上记录我的东西,只将其他消息放入日志文件。但是我一直没能找到将结果写入日志的方法:
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";
显示结果的那一行就是我要找的那一行,某种方法可以让不同的函数使用相同的方法写入日志 $log
。
这可能吗?
编辑:按照@amit bhosale 的建议,我仍然无法让它工作:
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");
我收到 priority RESULT isn't numeric at test_logs.pl line 60.
异常
感谢@amit bhosale 的建议,我终于能够让它工作了。由于他没有发送回复,如果有人需要,我会放这个测试示例:
use strict;
use warnings;
use Log::Log4perl;
use Win32::Console::ANSI;
my $result_file = "results.log";
my $conf = <<EOT;
log4perl.category = FATAL, 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
# Filter to match RESULT
log4perl.filter.MatchResult = Log::Log4perl::Filter::LevelMatch
log4perl.filter.MatchResult.LevelToMatch = RESULT
log4perl.filter.MatchResult.AcceptOnMatch = true
# Custom RESULT logs
log4j.appender.AppResult = Log::Log4perl::Appender::File
log4j.appender.AppResult.filename = $result_file
log4j.appender.AppResult.Filter = MatchResult
log4j.appender.AppResult.layout = Log::Log4perl::Layout::SimpleLayout
log4j.category.result = RESULT, AppResult
log4j.additivity.result = 0
);
EOT
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", "FATAL");
Log::Log4perl::init( $conf );
my $log = Log::Log4perl::get_logger(__FILE__);
my $result = Log::Log4perl->get_logger("result");
$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->error( "error in foo");
$log->trace( "crap from foo");
$log->info( "Im doing bar");
$log->debug( "Im doing foo");
$log->trace( "crap from bar");
$result->result("this is a result message");
我不太了解这个库,但似乎在配置中将类别设置为最低级别,我写了 FATAL。
然后您为新过滤器创建过滤器以仅显示自定义级别。然后 appender 使用该自定义级别,然后创建一个子类别,您调用该子类别而不是主要 $log
仅用于结果。
我通过使用此测试作为参考使其工作:
https://github.com/apple-opensource-mirror/CPANInternal/blob/35e8475f777c3c6eb7d4629f37daac0a1d2ea10e/Log-Log4perl-1.44/t/025CustLevels.t
另一种实现方式(不创建自定义关卡)。 (以上解决方案有效,这只是另一种方式)
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
我想将一些结果记录到一个文件中,而不会弄乱我的日志级别。是否可以使用 Log::Log4perl
来做到这一点。我试图按照文档进行操作,但我只能发现它取决于日志级别来打印文件?如 here :
og::Log4perl->easy_init( { level => $DEBUG,
file => ">>test.log",
layout => '%F{1}-%L-%M: %m%n' },
{ level => $DEBUG,
file => "STDOUT",
layout => '%m%n' },
);
但我想继续在屏幕上记录我的东西,只将其他消息放入日志文件。但是我一直没能找到将结果写入日志的方法:
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";
显示结果的那一行就是我要找的那一行,某种方法可以让不同的函数使用相同的方法写入日志 $log
。
这可能吗?
编辑:按照@amit bhosale 的建议,我仍然无法让它工作:
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");
我收到 priority RESULT isn't numeric at test_logs.pl line 60.
异常
感谢@amit bhosale 的建议,我终于能够让它工作了。由于他没有发送回复,如果有人需要,我会放这个测试示例:
use strict;
use warnings;
use Log::Log4perl;
use Win32::Console::ANSI;
my $result_file = "results.log";
my $conf = <<EOT;
log4perl.category = FATAL, 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
# Filter to match RESULT
log4perl.filter.MatchResult = Log::Log4perl::Filter::LevelMatch
log4perl.filter.MatchResult.LevelToMatch = RESULT
log4perl.filter.MatchResult.AcceptOnMatch = true
# Custom RESULT logs
log4j.appender.AppResult = Log::Log4perl::Appender::File
log4j.appender.AppResult.filename = $result_file
log4j.appender.AppResult.Filter = MatchResult
log4j.appender.AppResult.layout = Log::Log4perl::Layout::SimpleLayout
log4j.category.result = RESULT, AppResult
log4j.additivity.result = 0
);
EOT
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", "FATAL");
Log::Log4perl::init( $conf );
my $log = Log::Log4perl::get_logger(__FILE__);
my $result = Log::Log4perl->get_logger("result");
$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->error( "error in foo");
$log->trace( "crap from foo");
$log->info( "Im doing bar");
$log->debug( "Im doing foo");
$log->trace( "crap from bar");
$result->result("this is a result message");
我不太了解这个库,但似乎在配置中将类别设置为最低级别,我写了 FATAL。
然后您为新过滤器创建过滤器以仅显示自定义级别。然后 appender 使用该自定义级别,然后创建一个子类别,您调用该子类别而不是主要 $log
仅用于结果。
我通过使用此测试作为参考使其工作: https://github.com/apple-opensource-mirror/CPANInternal/blob/35e8475f777c3c6eb7d4629f37daac0a1d2ea10e/Log-Log4perl-1.44/t/025CustLevels.t
另一种实现方式(不创建自定义关卡)。 (以上解决方案有效,这只是另一种方式)
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