Log :: Dispatch :: FileRotate是否将旋转文件的新名称/当前名称提供给post_rotate回调? [英] Does Log::Dispatch::FileRotate provide the new/current name of the rotated file to the post_rotate callback?

查看:36
本文介绍了Log :: Dispatch :: FileRotate是否将旋转文件的新名称/当前名称提供给post_rotate回调?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是在@ikegami的建议下发布此帖子的,他在如何为我提供了帮助用:: FileRotate替换Log :: Dispatch :: File?并注意到一些意外行为.

I'm posting this at the suggestion of @ikegami, who helped me in How to replace Log::Dispatch::File with ::FileRotate? and noted some unexpected behavior.

要点是Perl的 Log :: Dispatch :: FileRotate 根据不同的限制(时间,大小等)自动移动日志文件,并具有 post_rotate 构造函数中的回调,因此您可以在文件旋转完成后执行操作.在我认为最明显的用例中,这种方式的表现并不明显:当您不想创建多个名为 filename.1 filename.2 等,而是当您想立即将备份移动到其他位置时.文档确实说明,当您处理第一个旋转文件时,传递给回调的 filename 是新的,空的,日志文件",但可能是您想要的(至少在某个地方)是刚旋转过的文件的名称.

The main point is that Perl's Log::Dispatch::FileRotate automatically moves log files according to different constraints (time, size, etc.), and has a post_rotate callback in the constructor so you can perform actions after the file rotation is complete. This does not behave in an obvious way in what I consider to be the most obvious use case: when you don't want to create multiple backup logs called filename.1, filename.2, etc., but rather when you want to immediately move the backup somewhere else. The docs do explain that when you're dealing with the first rotated file, the filename passed to the callback is "the new, empty, log file", but what you probably want (at least somewhere) is the name of the just-rotated file.

下面是显示此行为的MCVE: log1 操作,这似乎是一种应该"执行的方式.编码这个,不要以明智的方式工作.

Below is a MCVE showing this behavior: the log1 actions, which would seem to be the way one "should" code this, do not work in a sensible way.

为了获得预期"的结果,结果,您需要使用 log2 操作来重新创建刚旋转的文件的名称.这没有真正记录,并且重新生成文件名也不是很干净.这是唯一的方法,还是有更好的方法呢?

In order to get the "expected" result, you need to use the log2 actions to recreate the name of the just-rotated file. This is not really documented, and it's not very clean to regenerate the name of the file. Is this the only way, or is there a better way of doing this?

#!/usr/bin/env perl

use strict;
use warnings;

use Log::Dispatch::FileRotate;

my $rotate_size = 1_000;

##### setup code

my $file1 = "log-one.log";
my $backupdir1 = "Old1";

my $log1 = Log::Dispatch->new(
    outputs => [
    [ 'FileRotate',
      min_level => 'debug',
      mode => '>>',
      newline => 1,
      filename => $file1,
      size => $rotate_size,
      post_rotate => sub {
          my ($filename, $index, $fileRotate ) = @_;
          print "ONE: filename: [$filename]; fileRotate filename: [". $fileRotate->filename()."]\n";
          mkdir $backupdir1 unless -e $backupdir1;
          my $new_filename = $backupdir1 . "/" . $filename . "-" . time();
          rename($filename, $new_filename) or die "Can't move first logfile: $!";
          
      },
      ],
    ],
);

my $file2 = "log-two.log";
my $backupdir2 = "Old2";

my $log2 = Log::Dispatch->new(
    outputs => [
    [ 'FileRotate',
      min_level => 'debug',
      mode => '>>',
      newline => 1,
      filename => $file2,
      size => $rotate_size,
      post_rotate => sub {
          my ($filename, $index, $fileRotate ) = @_;
          print "TWO: filename: [$filename]; fileRotate filename: [". $fileRotate->filename()."]\n";
          mkdir $backupdir2 unless -e $backupdir2;
          my $old_file = $filename . ".1"; # already-rotated file
          my $new_filename = $backupdir2 . "/" . $file2 . "-" . time();
          rename($old_file, $new_filename) or die "Can't move second logfile: $!";
          
      },
      ],
    ],
);

##### We do stuff here

$log1->info("starting!");

open(my $fh, '>>', $file1) or die "Could not open file '$file1' $!\n";
print $fh "x" x $rotate_size;
close $fh;

$log1->info("finished!");

# "Sensible" result: a 1010-byte file called Old1/log-one.log-160134[etc].
# consisting of "starting!\n" plus 1,000 "x"s; a 10-byte file called test.log
# consisting of "finished!\n"
#
# Actual result: a 10-byte file called Old1/log-one.log-160134[etc], consisting
# of "finished!\n"; a 1010-byte file called log.one-log.1 consisting of "starting!\n"
# plus 1,000 "x"s.

$log2->info("starting!");

open($fh, '>>', $file2) or die "Could not open file '$file2' $!\n";
print $fh "x" x $rotate_size;
close $fh;

$log2->info("finished!");

# This is the desired result: the old, rotated log is archived as
# Old2/log-two.log-160134[etc], consisting of "starting!\n" plus 1,000 "x"s;
# the "current" log is "log-two.log", consisting of "finished!\n". But this
# requires some non-obvious stuff in post_rotate, where we have to recreate
# the filename of the just-rotated file.

推荐答案

我已经调查了这个问题,并且可以确认旋转文件的当前名称不可用.我有已报告此问题.

I have looked into the issue, and I can confirm the current name of the rotated file is not available. I have reported this issue.

同时,可以使用以下解决方法:

In the meantime, the following workaround is available:

sub post_rotate {
   my (undef, $index, $fileRotate) = @_;

   # Current path to the rotated file.
   my $current_qfn = $fileRotate->filename() . "." . ($index+1);

   # Handle the situation where this callback is called too many times.
   return if !-e $current_qfn;

   ...
}

即使 max 大于 1 ,也可以使用此选项.检查的原因是,当 max 大于1时,回调可能被调用一次!同一票证中也有报告.

This can be used even if max is a greater than 1. The check is because the callback can be called once too many when max is greater than 1! This was also reported in the same ticket.

这篇关于Log :: Dispatch :: FileRotate是否将旋转文件的新名称/当前名称提供给post_rotate回调?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆