Прикрепление контекста запроса
Задайте поля вроде request_id или user_id один раз в начале запроса или задачи — и они
автоматически появятся в каждой строке лога, без прокидывания через каждый вызов.
Как это работает
Каждый канал строится с автоматически прикреплённым
ContextInjectingProcessor. На каждой записи
лога он вливает снимок текущего
ContextStorage в extra записи, так что
любое заданное поле показывается, пока вы его не очистите. Настройка не нужна.
Задайте поля в начале работы
Достаньте хранилище через менеджер или фабрику, затем set() свои поля:
use Flytachi\Winter\Logger\LoggerFactory;
// В начале запроса (фронт-контроллер / middleware в FPM):
$ctx = LoggerFactory::contextStorage();
$ctx->set('request_id', $_SERVER['HTTP_X_REQUEST_ID'] ?? uniqid('req_'));
$ctx->set('user_id', $userId);
$ctx->set('method', $_SERVER['REQUEST_METHOD']);
// Любой вызов лога дальше несёт все три поля:
LoggerFactory::getLogger(self::class)->info('processing');[2024-01-01 12:00:00] [INFO ] -http- [4821] (OrderController): processing {"class":"App\\Http\\OrderController","request_id":"req_65a1...","user_id":42,"method":"POST"}Очищайте поля в конце работы
В процессе, который обрабатывает больше одной единицы работы, очищайте контекст между
ними — иначе поля протекут в следующий запрос. Под FPM процесс умирает после каждого
запроса, поэтому register_shutdown_function — чистый хук:
register_shutdown_function(
fn () => LoggerFactory::contextStorage()->clear()
);Долгоживущие процессы протекают без clear()
FPM сносит процесс за вас, но CLI-демон или Swoole-воркер переиспользуют один процесс.
Там всегда clear() в конце каждой итерации/запроса — иначе request_id предыдущей задачи
поедет вместе с логами следующей.
Паттерн демона в цикле
Для CLI-воркера, крутящегося вечно, задавайте поля на итерацию и очищайте внизу:
while (true) {
$ctx = LoggerFactory::contextStorage();
$ctx->set('iteration_id', uniqid('iter_'));
processNextJob();
$ctx->clear(); // сбрасываем поля этой итерации; процесс продолжает работу
}Привязанный контекст против контекста запроса
Две разные области видимости — выбирайте по времени жизни:
| Хотите поля на… | Используйте | Заметки |
|---|---|---|
| каждом логгере этого запроса/задачи | contextStorage()->set() |
вливается процессором в extra |
| только одном конкретном логгере | ->withContext([...]) |
возвращает новый логгер; вливается в context |
// Для всего запроса — видит каждый логгер:
LoggerFactory::contextStorage()->set('request_id', $id);
// Только для этого логгера — не влияет на другие:
$log = LoggerFactory::getLogger(self::class)->withContext(['order_id' => 5001]);
$log->info('charged');Удаление одного поля
forget() сбрасывает один ключ, не трогая остальные:
LoggerFactory::contextStorage()->forget('user_id');Связанное
- Корутины Swoole — изоляция контекста на запрос под Swoole
- Изоляция контекста — почему стратегия зависит от рантайма
- Справочник API → ContextStorage — полный интерфейс