[Perl]Log::Dispatch系モジュールとuse utf8の併存


要旨

use utf8プラグマの影響下でLog::Dispatch(あるいはLog::Dispatch::Config)を使おうとすると"Wide character in print ~"なwarningが出る件について調査しました。

結論

configファイルに数行書き加えるだけでしたが、filescreenで指定方法が違います。

実装

sample.psgi
use strict;
use warnings;
use Encode;

use Log::Dispatch::Config;
Log::Dispatch::Config->configure('./log.conf');
my $dispatcher = Log::Dispatch::Config->instance();
$dispatcher->info( decode_utf8 "再起動" );
# ↑全ての出力をencodeするため、use utf8されていないスコープではdecode_utf8が必須

use Plack::Request;

sub {
    use utf8;
    my $req = Plack::Request->new(shift);

    unless( $req->path eq '/') {
        $dispatcher->warning("ルート以外へのアクセス");
        return [404, [], ['Not Found']];
    }
    # 必要な処理を書く

    $dispatcher->info("正常な処理の完了");
    return [200, [], ["OK"]];
};
log.conf
dispatchers = file screen

file.class = Log::Dispatch::File
file.min_level = notice
file.filename = ./log/error_log         
file.mode = append
file.format = [%d] [%p] %m at %F line %L %n
file.binmode = :utf8

screen.class = Log::Dispatch::Screen
screen.min_level = debug
screen.stderr = 1
screen.format = [%p] %m %n
screen.utf8 = 1

fileのプロパティの定義にfile.binmode = :utf8、screenのプロパティの定義にscreen.utf8 = 1と書き加えることでLog::Dispatchが全ての出力をencode_utf8してくれるようです。

ちなみにこれがわかるまでは、

sample2.psgi
sub {
    use utf8;
    my $req = Plack::Request->new(shift);

    unless( $req->path eq '/') {
        $dispatcher->warning( encode_utf8("ルート以外へのアクセス") );
        return [404, [], ['Not Found']];
    }
    # 必要な処理を書く

    $dispatcher->info( encode_utf8("正常な処理の完了") );
    return [200, [], ["OK"]];
};

のように逐一encodeを挿入してて辛かったです。

参考文献