Интеграция с фреймворком
Библиотека не зависит от инфраструктуры: она никогда не читает env-переменные и не определяет рантайм. Это делает ваш бутстрап — строит конфиг и подключает логгер. Вот разделение ответственности и точный порядок вызовов.
Кто что делает
| Шаг | Ответственность | Кто вызывает |
|---|---|---|
| Разрешить env → конфиг (уровни, вывод, пути) | инфраструктура | ядро фреймворка |
Собрать LoggerManager |
инфраструктура | ядро фреймворка |
setManager() |
зарегистрировать один раз | ядро фреймворка |
setDefaultChannel() |
выбрать активный канал | точка входа |
setContextStorage() |
выбрать стратегию изоляции | точка входа (Swoole) |
Ядро строит и регистрирует менеджер. Точка входа — public/index.php, раннер Swoole
или CLI-скрипт — знает реальный рантайм, поэтому задаёт канал по умолчанию и (для Swoole)
хранилище контекста.
Бутстрап — зарегистрируйте менеджер один раз
<?php
use Monolog\Level;
use Flytachi\Winter\Logger\LoggerManager;
use Flytachi\Winter\Logger\LoggerFactory;
use Flytachi\Winter\Logger\Context\ProcessContext;
$manager = new LoggerManager(
contextStorage: new ProcessContext(), // по умолчанию; подменяется под рантайм ниже
channels: [
'sys' => ['level' => Level::Warning, 'format' => 'line', 'output' => 'stderr',
'file_path' => null, 'file_max' => 30, 'syslog_ident' => 'winter'],
'http' => ['level' => Level::Info, 'format' => 'line', 'output' => 'stderr',
'file_path' => null, 'file_max' => 30, 'syslog_ident' => 'winter'],
'cli' => ['level' => Level::Debug, 'format' => 'line', 'output' => 'stdout',
'file_path' => null, 'file_max' => 30, 'syslog_ident' => 'winter'],
],
);
LoggerFactory::setManager($manager);Точки входа — выберите канал и хранилище под рантайм
Каждая точка входа подключает бутстрап, затем объявляет свой рантайм:
<?php
require '../bootstrap.php';
// FPM: один запрос = один процесс, ProcessContext уже правильный.
LoggerFactory::setDefaultChannel('http');<?php
require '../bootstrap.php';
use Flytachi\Winter\Logger\Context\CoroutineContext;
// Swoole: переключитесь на изолированный по корутинам контекст до приёма запросов.
LoggerFactory::setContextStorage(new CoroutineContext());
LoggerFactory::setDefaultChannel('http');<?php
require 'bootstrap.php';
// CLI-задачи / воркеры очередей / демоны.
LoggerFactory::setDefaultChannel('cli');Порядок важен
setManager() — всегда первым. setContextStorage() и addChannel() работают с текущим
менеджером, поэтому должны идти после него. Каждый из них также очищает поклассовый кэш
логгеров, поэтому задавайте их на бутстрапе — не посреди запроса.
Использование из кода приложения
После подключения код приложения никогда не видит менеджер:
use Flytachi\Winter\Logger\LoggerFactory;
use Flytachi\Winter\Logger\Log;
// Логгер на класс на канале по умолчанию:
LoggerFactory::getLogger(self::class)->info('user created', ['id' => 42]);
// Быстрый однострочник:
Log::warning('rate limit hit');Рекомендуемые каналы по умолчанию
Распространённая конвенция (как в winter-kernel):
| Канал | Типичное использование | Вывод по умолчанию |
|---|---|---|
sys |
системные события, фолбэк | stderr |
http |
контроллеры, сервисы (FPM/Swoole) | stderr (FPM) / stdout (Swoole) |
cli |
задачи, воркеры очередей, демоны | stdout |
stderr для FPM, stdout для Swoole
Под FPM php://stdout — это поток ответа FastCGI: запись в него после отключения клиента
рискует broken pipe. Там предпочтителен stderr. Swoole обрабатывает ответы своим I/O,
поэтому stdout безопасен. См. Вывод и broken pipe.
Сброс в тестах
LoggerFactory хранит статическое состояние. Пересоберите его в setUp(), чтобы тесты не
делили менеджер:
protected function setUp(): void
{
LoggerFactory::setManager($this->buildManager());
}Связанное
- Динамические каналы — регистрация доп. каналов в рантайме
- Корутины Swoole — точка входа Swoole целиком
- Справочник API → LoggerFactory