Log::Dispatch::FileRotate のローテートサイズではまった件

ここ7ヶ月ほど、とある業務アプリをひたすら書き続けてテストし続けていました。ソースコードは 100,000 step ほど。先日無事にリリースでき、その後のトラブルに追われる日が続きましたが、ようやく落ち着いてきました。精も根も尽き果てました・・・。

さて、その巨大なアプリで Log::Dispatch::FileRotate 使ってるのですが、デフォルト設定ではファイルサイズが 10MB でのローテートだと知らなかったので、どんどんローテートされて全然ロギングの意味がないじゃん!なんて罠にはまりました・・・orz

ちゃんとドキュメントを読んでおくべきでした。

Log::Dispatch::FileRotate - Log to files that archive/rotate themselves - search.cpan.org

The arguments size and max specify the maximum size and maximum number of log files created. The size defaults to 10M and the max number of files defaults to 1. If DatePattern is not defined then we default to working in size mode. That is, use size values for deciding when to rotate.
Once DatePattern is defined FileRotate will move into time mode. Once this happens file rotation ignores size constraints and uses the defined date pattern
- スポンサーリンク -

それはそうと、使い方のところがこんな感じになってるんですけど・・・これじゃファイルサイズの指定を間違えちゃいそうです。

img01.jpg

デフォルトは 10MB と書いてあるので、このサンプル中の size => 10, は思わず MB 単位なんだ!と思ってしまいそうですが、実は size は byte 単位です。このサンプルだと 10 byte でローテートしてしまいます。サンプルとしては 1024*1024*10 としてあると、ユーザに優しいかなっと。

結論として Log::Dispatch::FileRotate 使うときは、10MB 以下の場合だとして、インスタンス生成時に size 引数をちゃんと指定すること!それで幸せに慣れるはずです。

10MB 以上のサイズが予想される場合場合は、size => 指定のバイト数 を new 時に必ず指定しましょう! → 自分。

ちなみに Log::Dispatch::FileRotate のソースコードはこんな感じ。赤字の部分がファイルサイズの処理です。ローテートサイズは 1 〜 2GB までです。

sub new
{
    my $proto = shift;
    my $class = ref $proto || $proto;
    my %p = @_;
    my $self = bless {}, $class;

    $self->{'debug'} = 0;
    $self->_basic_init(%p);
    $self->{'LDF'} =  Log::Dispatch::File->new(%p);  # Our log
    $self->{'timer'} = sub { time() } unless defined $self->{'timer'};

    # Keep a copy of interesting stuff as well
    $self->{params} = \%p;

    # Turn ON/OFF debugging as required
    $p{'DEBUG'} ? $self->debug(1) : $self->debug(0);
    
    # Size defaults to 10meg in all failure modes, hopefully
    my $ten_meg = 1024*1024*10;
    my $two_gig = 1024*1024*1024*2;
    my $size = $ten_meg;
    $size = $p{size} if defined $p{size};
    $size = $ten_meg unless $size =~ /^\d+$/ && $size < $two_gig && $size > 0;
    $self->{size} = $size;

    # Max number of files defaults to 1. No limit enforced here. Only
    # positive whole numbers allowed
    $self->{max}  = $p{max};
    $self->{max}  = 1 unless defined $self->{max} && $self->{max} =~ /^\d+$/ && $self->{max} > 0 ;

    # Get a name for our Lock file
    my $name = $self->{params}->{filename};
    my ($vol, $dir, $f) = File::Spec->splitpath($name);
    $dir = '.' unless $dir;
    $f = $name unless $f;

    my $lockfile = File::Spec->catpath($vol, $dir, ".".$f.".LCK");
    warn "Lock file is $lockfile\n" if $self->{'debug'};
    $self->{'lf'} = $lockfile;

    # Have we been called with a time based rotation pattern then setup
    # timebased stuff. TZ is important and must match current TZ or all
    # bets are off!
    if(defined $p{'TZ'})
    {
        Date_Init("TZ=".$p{'TZ'});  # EADT or EAST when not in daylight savings
    }
    if(defined $p{'DatePattern'})
    {
        $self->setDatePattern($p{'DatePattern'});
    }

    # Flag this as first creation point
    $self->{'new'} = 1;

    return $self;
}

最後に自分への戒め。
やっぱ使う前には、POD を最低限読んで、可能な限りソースも一読しておくと、後で幸せになれますよ!

- スポンサーリンク -

関連する記事&スポンサーリンク