guttally.net

PSR-3 日本語版

 ロギングライブラリのインタフェースに関する規約である PSR-3 を和訳してみました。 原文はこちらです。 誤記・語訳などありましたらご指摘いただけると幸いです。


ロガーインタフェース

 この文書では,ロギングライブラリのための共通インタフェースについて記述します。

 主なゴールは,ライブラリが Psr\Log\LoggerInterface を受け取れるようにすることで,シンプルかつ一般的な方法でログを記録することです。 フレームワークや CMS は必要に応じてその目的のためにインタフェースを拡張することができますが (MAY),それでもこの文書との互換性を維持するべきです (SHOULD)。 そうすることで,アプリケーションが使用するサードパーティ製ライブラリが集中化したアプリケーションログに書き込めることを保証します。

 この文書における 「MUST」,「MUST NOT」,「REQUIRED」,「SHALL」,「SHALL NOT」,「SHOULD」,「SHOULD NOT」,「RECOMMENDED」,「MAY」および「OPTIONAL」のキーワードは,RFC 2119 (和訳) で述べられているように解釈されるべきものです。

 本文書に置ける実装者という語は,ログに関連するライブラリやフレームワークに LoggerInterface を実装する人のことを指します。 ロガーの利用者はユーザと表記します。

1. 仕様

1.1 基礎

  • LoggerInterface はログを RFC 5424 の 8 種類のレベル (debug, info, notice, warning, error, critical, alert, emergency) で記録するための 8 個のメソッドを公開します。

  • log という 9 個目のメソッドは,最初の引数にログレベルを受け取ります。 メソッド呼び出し時に本仕様でも定義されていないレベルが指定され,実装側でもそのレベルが 定義されていない場合,Psr\Log\InvalidArgumentException が スローされなければなりません (MUST)。 ユーザは実装側でサポートされていることが確認できていないカスタムレベルを使用するべきではありません (SHOULD NOT)。

1.2 メッセージ

  • 各メソッドは文字列または __toString() メソッドを持つオブジェクトを メッセージとして受け取ります。 実装者は渡されたオブジェクトに特別な操作を行うことが できます (MAY)。 そうでない場合,実装者はオブジェクトを文字列に キャストしなければなりません (MUST)。

  • メッセージには,実装者がコンテキスト配列の値に置換することができる (MAY) プレースホルダを含めることができます (MAY)。

    プレースホルダ名はコンテキスト配列のキーと一致していなければなりません (MUST)。

    プレースホルダ名は左中括弧 { と右中括弧 } で境界を 明示しなければなりません (MUST)。 これらのデリミタの間やプレースホルダ名に空白文字を 使用してはいけません (MUST NOT)。

    プレースホルダ名を構成する文字は A-Za-z0-9, アンダースコア _およびピリオド . のみとするべきです (SHOULD)。 他の文字の使用は,将来のプレースホルダの仕様変更のために予約されます。

    実装者は種々のエスケープの実装やログを表示用に変換するためにプレースホルダを 使うことができます (MAY)。 ユーザは,データがどのコンテキストに表示されるかを 知ることができないため,プレースホルダの値を事前にエスケープするべきではありません。

    プレースホルダへの書き込みの実装例を以下に示します。 これは参考としての目的のみに提供されます。

/**
* Interpolates context values into the message placeholders.
*/
function interpolate($message, array $context = array())
{
    // build a replacement array with braces around the context keys
    $replace = array();
    foreach ($context as $key => $val) {
        $replace['{' . $key . '}'] = $val;
    }

    // interpolate replacement values into the message and return
    return strtr($message, $replace);
}

// a message with brace-delimited placeholder names
$message = "User {username} created";

// a context array of placeholder names => replacement values
$context = array('username' => 'bolivar');

// echoes "User bolivar created"
echo interpolate($message, $context);

1.3 Context

  • 各メソッドは配列をコンテキストデータとして受け取ります。 これは,文字列にフィットしない外部の情報も保持できるようにすることが目的です。 配列には何でも含めることができます。 実装者はできる限り寛容にコンテキストデータを扱わなければなりません (MUST)。 コンテキスト内の値が例外をスローしたり,php のエラーや警告,通知を発生させることがあってはなりません (MUST NOT)。

  • コンテキストデータに Exception オブジェクトを渡す場合,その連想配列キーは 'exception' でなければなりません (MUST)。 例外のロギングを共通なパターンにすることで,ログのバックエンドが対応している場合に,実装者が例外からスタックトレース抽出することが可能になります。 ただし,'exception' キーには何でも含めることができる (MAY) ため,実装者はそれが本当に Exception であるかを,使う前に確認しなければなりません (MUST)。

1.4 ヘルパークラスとインタフェース

  • Psr\Log\AbstractLogger クラスを拡張して汎用の log メソッドを実装することで,簡単に LoggerInterface を実装することができます。

  • 同様に Psr\Log\LoggerTrait でも,実装が必要なのは汎用の log メソッドだけです。 ただし,トレイトはインタフェースを実装できないため,この場合には別途 LoggerInterface を実装してください。

  • Psr\Log\NullLogger は LoggerInterface とともに提供されます。 LoggerInterface のユーザはその実装が提供されない時に NullLogger を 「ブラックホール」 のような代替実装として利用することができます (MAY)。 しかしながら,コンテキストデータの生成コストが大きい場合には,条件付きでロギングする方が良いかもしれません。

  • Psr\Log\LoggerAwareInterfacesetLogger(LoggerInterface $logger) メソッドのみを持ち,フレームワークが任意のインスタンスとロガーを接続するために利用できます。

  • Psr\Log\LoggerAwareTrait トレイトは等価なインタフェースを任意のクラスに対して簡単に実装するために使うことができます。 これによって $this->logger へアクセスすることができるようになります。

  • Psr\Log\LogLevel クラスは 8 段階のログレベルを示す定数を持ちます。

2. パッケージ

 前述のインタフェースとクラスのほか,関連する例外クラスや実装を検証するためのテストスイートは,psr/log パッケージの一部として提供されます。

3. Psr\Log\LoggerInterface

<?php

namespace Psr\Log;

/**
 * ロガーのインスタンスを記述します。
 *
 * メッセージは文字列か __toString() メソッドを持ったオブジェクトで
 * なければなりません (MUST)。
 *
 * メッセージには {foo} 形式のプレースホルダを含めることができます。
 * foo は "foo" というキーのコンテキストデータで置換されます。
 *
 * コンテキスト配列は任意のデータを含むことができます。
 * 実装者に許される唯一の仮定は,スタックトレースを提供するために
 * Exception クラスのインスタンスが渡される場合,そのキー名は
 * "exception" でなければならない (MUST) ことである。
 *
 * インタフェースの全仕様については
 * https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
 * を参照してください。
 */
interface LoggerInterface
{
    /**
     * システム利用不能な状況
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function emergency($message, array $context = array());

    /**
     * 即時対応が必要な状況
     *
     * 例: ウェブサイト全体のダウン,データベースの利用不可など。
     * SNS でアラートを発し,あなたを起こすべき状況です。
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function alert($message, array $context = array());

    /**
     * 危機的な状況
     *
     * 例: アプリケーションのコンポーネントが利用できなかったり
     * 予期しない例外など。
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function critical($message, array $context = array());

    /**
     * すぐに対応する必要はないが,一般に記録・監視されるべき実行時エラー
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function error($message, array $context = array());

    /**
     * エラーではないが通常生じない事象
     *
     * 例: 非推奨の API が使用された,不完全な API の利用,
     * 必ずしも間違いではないが望ましくない事象
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function warning($message, array $context = array());

    /**
     * 正常だが重要なイベント
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function notice($message, array $context = array());

    /**
     * 興味のあるイベント
     *
     * 例: ユーザのログイン,SQL ログ
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function info($message, array $context = array());

    /**
     * 詳細なデバッグ情報
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function debug($message, array $context = array());

    /**
     * 任意のレベルでのログ
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     * @return null
     */
    public function log($level, $message, array $context = array());
}

4. Psr\Log\LoggerAwareInterface

<?php

namespace Psr\Log;

/**
 * Describes a logger-aware instance
 */
interface LoggerAwareInterface
{
    /**
     * ロガーインタフェースをオブジェクトにセットする。
     *
     * @param LoggerInterface $logger
     * @return null
     */
    public function setLogger(LoggerInterface $logger);
}

5. Psr\Log\LogLevel

<?php

namespace Psr\Log;

/**
 * Describes log levels
 */
class LogLevel
{
    const EMERGENCY = 'emergency';
    const ALERT     = 'alert';
    const CRITICAL  = 'critical';
    const ERROR     = 'error';
    const WARNING   = 'warning';
    const NOTICE    = 'notice';
    const INFO      = 'info';
    const DEBUG     = 'debug';
}