これがシナリオです。大量のレガシー スクリプトがあり、すべてが共通のライブラリを使用しています。上記のスクリプトは、診断出力に「print」ステートメントを使用します。スクリプトの変更は許可されていません。スクリプトは広範囲に及ぶものであり、承認を得ており、監督と管理の実りある谷から長い間離れています。
ここで、新たな必要性が生じました。ロギングをライブラリに追加する必要があります。これは、標準ライブラリのユーザーがスクリプトを変更する必要なく、自動的かつ透過的に行う必要があります。共通ライブラリ メソッドには、ロギング呼び出しを追加するだけです。それは簡単な部分です。難しいのは、これらのスクリプトからの診断出力が常に「print」ステートメントを使用して表示されていたことです。この診断出力は保存する必要がありますが、同様に重要なのは処理することです。
この処理の例として、ライブラリは、「警告」、「エラー」、「通知」、または「注意」という単語を含む出力行のみを記録する必要があります。以下の非常に些細で不自然なコード例 (tm) は、上記の出力の一部を記録します。
sub CheckPrintOutput
{
my @output = @_; # args passed to print eventually find their way here.
foreach my $value (@output) {
Log->log($value) if $value =~ /warning|error|notice|attention/i;
}
}
(「実際にログに記録すべきもの」、「print を診断に使用すべきではない」、「perl はひどい」、「この例には xy と z に欠陥がある」などの問題は避けたいと思います...これは簡潔さと明確さのために大幅に簡略化されています。)
基本的な問題は、print に渡されたデータをキャプチャして処理することです (または、これらの推論に沿った任意の perl ビルトイン)。出来ますか?きれいにする方法はありますか?それを可能にするフックを備えたログモジュールはありますか? それとも、ペストのように避けるべきものであり、印刷出力をキャプチャして処理することをあきらめるべきですか?
追加: これは、クロスプラットフォームで実行する必要があります (Windows と *nix の両方)。スクリプトを実行するプロセスは、スクリプトからの出力と同様に、同じままにする必要があります。
追加の追加:codelogicの回答のコメントで行われた興味深い提案:
http://perldoc.perl.org/IO/Handle.htmlをサブクラス化し、ロギング作業を行う独自のファイル ハンドルを作成できます。– カミル・キシエル
これでうまくいくかもしれませんが、2 つの注意点があります。
1) この機能を共通ライブラリを使用する人にエクスポートする方法が必要です。STDOUT とおそらく STDERR にも自動的に適用する必要があります。
2) IO::Handle のドキュメントには、サブクラス化できないと書かれており、これまでの私の試みは無駄でした。サブクラス化 IO::Handle を機能させるために特別に必要なものはありますか? 標準の 'use base 'IO::Handle' を使用してから、new/print メソッドをオーバーライドしても何も起こらないようです。
最終編集: IO::Handle は行き止まりのように見えますが、Tie::Handle はそれを行う可能性があります。すべての提案に感謝します。彼らはすべて本当に良いです。Tie::Handle ルートを試してみます。問題が発生した場合は、戻ってきます。
補遺: これを少し使ってみたところ、何もトリッキーなことをしなければ Tie::Handle が機能することがわかりました。結合された STDOUT または STDERR で IO::Handle の機能のいずれかを使用する場合、基本的にそれらを確実に動作させるためのクラップシュートです。扱う。ハンドルを結ぶ前に自動フラッシュを有効にすると、機能します。それがうまくいく場合は、 Tie::Handle ルートが受け入れられるかもしれません。