TGViewer
Пых Пых @phpyh · 7.83K subscribers
Post #525 8.36K
Контекст в PSR-3 Logger

Периодически сталкиваюсь с неправильным использованием $context в PSR логгере. Давайте вместе внимательно перечитаем стандарт.

1.3.1 Every method accepts an array as context data. This is meant to hold any extraneous information that does not fit well in a string. The array can contain anything. Implementors MUST ensure they treat context data with as much lenience as possible. A given value in the context MUST NOT throw an exception nor raise any php error, warning or notice.


Жирным выделил то, что многие упускают: вы можете передавать в контекст абсолютно любые значения, в том числе массивы, объекты, замыкания и ресурсы. Не нужно самостоятельно проводить нормализацию. По стандарту это задача логгера, а не ваша. Вот как, например, Monolog обработает контекст со сложными элементами:


$logger = new Monolog\Logger(
name: 'app',
handlers: [new Monolog\Handler\StreamHandler(STDOUT)],
processors: [new Monolog\Processor\PsrLogMessageProcessor()]
);

final readonly class Foo
{
public function __construct(
public string $public = 'bar',
private string $private = 'baz',
) {}
}

$logger->debug('Message', [
'birthday' => new DateTimeImmutable('06.04.2019'),
'object' => new Foo(),
'closure' => static fn (): int => 1,
'resource' => STDIN,
]);


[2024-09-27T13:02:16.303651+00:00] app.DEBUG: Message {"birthday":"2019-04-06T00:00:00+00:00","object":{"Foo":{"public":"bar"}},"closure":{"Closure":[]},"resource":"[resource(stream)]"} []


1.3.2 If an Exception object is passed in the context data, it MUST be in the 'exception' key. Logging exceptions is a common pattern and this allows implementors to extract a stack trace from the exception when the log backend supports it. Implementors MUST still verify that the 'exception' key is actually an Exception before using it as such, as it MAY contain anything.


Исключения нужно добавлять в контекст с ключом 'exception'. Никогда не раскладывайте объект исключения на массив вида ['message' => $e->getMessage(), 'line' => $e->getLine(), ...] — так вы не даёте процессорам и форматтерам самим принять решение относительно состава лога исключения и глубины его нормализации.


$logger->critical('Oops!', [
'exception' => new LogicException(
message: 'Level 2',
previous: new RuntimeException('Level 1'),
),
]);


[2024-09-27T13:14:04.880133+00:00] app.CRITICAL: Oops! {"exception":"[object] (LogicException(code: 0): Level 1 at test.php:27)\n[previous exception] [object] (RuntimeException(code: 0): Level 2 at test.php:29)"} []


1.2.2 The message MAY contain placeholders which implementors MAY replace with values from the context array.
Placeholder names MUST correspond to keys in the context array.
Placeholder names MUST be delimited with a single opening brace { and a single closing brace }.
Placeholder names SHOULD be composed only of the characters A-Z, a-z, 0-9, underscore _, and period .. The use of other characters is reserved for future modifications of the placeholders specification.
Users SHOULD NOT pre-escape placeholder values since they can not know in which context the data will be displayed.


Ну и конечно же не забывайте про плейсхолдеры в сообщении. Вместо интерполяции и sprintf куда удобнее писать так:


$logger->notice('Process {pid} started at {time}', [
'pid' => getmypid(),
'time' => new DateTimeImmutable(),
]);


[2024-09-27T13:23:29.306682+00:00] app.NOTICE: Process 45104 started at 2024-09-27T13:23:29.306681+00:00 {"pid":45104,"time":"2024-09-27T13:23:29+00:00"} []
www.php-fig.org PSR-3: Logger Interface - PHP-FIG We're a group of established PHP projects whose goal is to talk about commonalities between our projects and find ways we can work better together.
  • 👍 136
  • 🔥 39
  • ❤ 9
More from @phpyh
  1. Sep 30, 2026🍺 BeerPHP AI Moscow Кажется, «неделя PHP» потихоньку превращается в месяц PHP. 😅 Будет 2…
  2. Sep 28, 2026Запустили Пыхник и неделю PHP! Залетайте на первый открытый доклад от Дмитрия Dantes про к…
  3. Sep 15, 2026Сейчас один человек с AI может выполнять работу целого IT-отдела. Только хуёво
  4. Sep 12, 2026Спасибо за заявки! Всем напишу в понедельник. Осталось 1 место.
  5. Sep 11, 2026Хардкорный курс асинхронного PHP https://hardcourse.ru/php/async
  6. Sep 11, 2026Ещё полчасика надо — сайт готов, расписываю программу! 🙏
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →