4

我有一个应用程序在 DBI 调用期间随机死亡的问题。我们无法在我们的测试或验收环境中可靠地重现这一点,因此我需要在我们的生产系统上对其进行监控,以试图找出正在发生的事情。

我正在通过环境变量记录所有DBI流量。DBI_TRACE

DBI_TRACE=3=dbi.log script.pl

然而,问题是 DBI 日志文件中没有时间戳,因此很难通过它们来查找在死机时发生的情况。

有没有办法启用带有时间戳的 DBI 日志记录?

4

6 回答 6

3

您可以使用File::Tee重定向 STDERR 并添加带有时间戳的前缀。

例如:

use strict;
use warnings;

use File::Tee 'tee';

my $logfile = "/path/to/timestamped/logfile.log";
my $filter  = sub { return localtime() . ' ' . $_[0] };

my $pid = tee STDERR, { preprocess => $filter, reopen => $logfile };

print STDERR "something bad happened.";

这里的优点是它不会干扰您现有的 STDERR——所有错误消息将继续发送到同一个地方。但是流被复制并写入$logfile,通过$filter钩子进行任何您想要的转换。

于 2009-08-19T00:58:09.950 回答
2

如果覆盖STDERR不是一个选项,并且如果您使用的是 UNIXy 系统(各种帖子都建议您这样做),您可以将跟踪输出定向​​到fifo并在那里运行时间戳过滤器:

$ mkfifo /tmp/fifo
$ perl -MTime::HiRes=time -npe 's/^/time . " "/e' < /tmp/fifo > /tmp/timestamped.log &
[1] 12345
$ DBI_TRACE=1=/tmp/fifo script.pl

该过滤程序可以是任何东西,甚至是logger ,它在我的系统上添加了由syslogd提供的时间戳。

于 2009-08-19T03:48:15.393 回答
2

DBI 文档包含如何使用分层文件句柄启用时间戳日志的代码。缺点是您失去了使用环境变量的奢侈,并且必须在代码中设置跟踪参数:

$dbh->trace('SQL', $fh);

其中 $fh 包含对PerlIO::Via的“子类”对象的引用

于 2009-08-19T04:10:13.867 回答
2

我建议看看DBI::Log

默认情况下,它会打印到 STDERR,因此要复制您的使用情况,您可以这样称呼它:

perl -MDBI::Log script.pl 2> dbi.log

通过以下方式,输出可以让您更好地了解基于 DBI 的 SQL 访问中发生的情况:

  • 包含时间戳
  • 用实际值替换占位符(又名绑定参数),这使得直接在 SQL 中重新运行查询更容易调试,并且
  • 包含导致相应 SQL 查询的 Perl 代码的调用跟踪。
于 2018-01-29T15:27:27.810 回答
1

尽管有可能,但我怀疑 DBI 本身是否存在问题。尽管我看到您使用的是跟踪级别 3,但 DBI 的跟踪可能非常冗长。使用 DBIx::Log4perl,您将获得可配置的时间戳、方法调用、SQL、绑定等跟踪,您需要做的就是更改连接调用。

于 2011-05-03T08:04:06.977 回答
0

我写了一个简约的perl 记录器,带有可配置的动态日志记录,为您提供以下 API:

        use strict ; use warnings ; use Exporter;
        use Configurator ; 
        use Logger ; 


        #   anonymous hash !!!
        our $confHolder = () ; 

        sub main {

                # strip the remote path and keep the bare name
                $0=~m/^(.*)(\\|\/)(.*)\.([a-z]*)/; 
                my $MyBareName = $3; 
                my $RunDir= $1 ; 

                # create the configurator object 
                my $objConfigurator = new Configurator($RunDir , $MyBareName ); 
                # get the hash having the vars 
                $confHolder = $objConfigurator ->getConfHolder () ; 
                # pring the hash vars 
                print $objConfigurator->dumpIni();  

                my $objLogger = new Logger (\$confHolder) ; 
                $objLogger->LogMsg  (   " START MAIN " ) ;  

                $objLogger->LogMsg  (   "my \$RunDir is $RunDir" ) ; 
                $objLogger->LogMsg  (   "this is a simple message" ) ; 
                $objLogger->LogErrorMsg (   "This is an error message " ) ; 
                $objLogger->LogWarningMsg   (   "This is a warning message " ) ; 
                $objLogger->LogInfoMsg  (   "This is a info message " ) ; 
                $objLogger->LogDebugMsg (   "This is a debug message " ) ; 
                $objLogger->LogTraceMsg (   "This is a trace message " ) ; 
                $objLogger->LogMsg  (   "using the following log file " .  "$confHolder->{'LogFile'}" ) ; 
                $objLogger->LogMsg  (   " STOP MAIN \n\n" ) ; 

        } #eof main 



        #Action !!!
        main(); 

        1 ; 

        __END__
于 2011-04-21T20:32:57.533 回答