--- git: 1b69438a67473dc3a9c7f351b3fa742460d11054 --- # Логирование ## Введение Чтобы помочь вам узнать больше о том, что происходит в вашем приложении, Laravel предлагает надежные службы ведения журнала, которые позволяют записывать сообщения в файлы, журнал системных ошибок и даже в Slack, чтобы уведомить всю вашу команду. Ведение журнала Laravel основано на «каналах». Каждый канал представляет собой определенный способ записи информации журнала. Например, канал `single` записывает файлы журнала в один файл журнала, а канал `slack` отправляет сообщения журнала в Slack. Сообщения журнала могут быть записаны в несколько каналов в зависимости от их серьезности. Под капотом Laravel использует библиотеку [Monolog](https://github.com/Seldaek/monolog), которая обеспечивает поддержку множества мощных обработчиков журналов. Laravel упрощает настройку этих обработчиков, позволяя вам смешивать и сопоставлять их для настройки обработки журналов вашего приложения. ## Конфигурирование Все параметры конфигурации, которые управляют ведением журнала вашего приложения размещены в файле конфигурации `config/logging.php`. Этот файл позволяет вам настраивать каналы журнала вашего приложения, поэтому обязательно просмотрите каждый из доступных каналов и их параметры. Ниже мы рассмотрим несколько распространенных вариантов. По умолчанию Laravel будет использовать канал `stack` при регистрации сообщений. Канал `stack` используется для объединения нескольких каналов журнала в один канал. Для получения дополнительной информации о построении стеков ознакомьтесь с [документацией ниже](#building-log-stacks). ### Доступные драйверы канала Каждый канал журнала работает через «драйвер». Драйвер определяет, как и где фактически записывается сообщение журнала. Следующие драйверы канала журнала доступны в каждом приложении Laravel. Запись для большинства этих драйверов уже присутствует в файле конфигурации вашего приложения `config/logging.php`, поэтому обязательно просмотрите этот файл, чтобы ознакомиться с его содержимым: | Имя | Описание | | ------------ | ------------------------------------------------------------------------------ | | `custom` | Драйвер, который вызывает указанную фабрику для создания канала. | | `daily` | Драйвер Monolog на основе `RotatingFileHandler` с ежедневной ротацией. | | `errorlog` | Драйвер Monolog на основе `ErrorLogHandler`. | | `monolog` | Драйвер фабрики Monolog, использующий любой поддерживаемый Monolog обработчик. | | `papertrail` | Драйвер Monolog на основе `SyslogUdpHandler`. | | `single` | Канал на основе одного файла или пути (`StreamHandler`) | | `slack` | Драйвер Monolog на основе `SlackWebhookHandler`. | | `stack` | Обертка для облегчения создания «многоканальных» каналов. | | `syslog` | Драйвер Monolog на основе `SyslogHandler`. | > [!NOTE] > Ознакомьтесь с документацией по [продвинутой кастомизации каналов](#monolog-channel-customization), чтобы узнать больше о драйверах `monolog` и `custom`. #### Настройка имени канала По умолчанию экземпляр Monolog создается с «именем канала», которое соответствует текущей среде, например, `production` или `local`. Чтобы изменить это значение, добавьте параметр `name` в конфигурацию вашего канала: 'stack' => [ 'driver' => 'stack', 'name' => 'channel-name', 'channels' => ['single', 'slack'], ], ### Предварительная подготовка канала #### Конфигурирование каналов Single и Daily Каналы (Channels) `single` и `daily` имеют три необязательных параметра конфигурации: `bubble`, `permission`, и `locking`. | Имя | Описание | По умолчанию | | ------------ | -------------------------------------------------------------- | ------------ | | `bubble` | Должны ли сообщения переходить в другие каналы после обработки | `true` | | `locking` | Попытаться заблокировать файл журнала перед записью в него | `false` | | `permission` | Права доступа на файл журнала | `0644` | Дополнительно, способ хранения для канала `daily` можно настроить с помощью переменной среды `LOG_DAILY_DAYS` или путем установки параметра конфигурации `days`. | Name | Description | Default | | ------ | ----------------------------------------------------------------------- | ------- | | `days` | Количество дней, в течение которых следует хранить файлы daily channel. | `7` | #### Конфигурирование канала Papertrail Для канала `papertrail` требуются параметры конфигурации `host` и `port`. Их можно определить с помощью переменных среды `PAPERTRAIL_URL` и `PAPERTRAIL_PORT`. Эти значения можно получить из [Papertrail](https://help.papertrailapp.com/kb/configuration/configuring-centralized-logging-from-php-apps/#send-events-from-php-app). #### Конфигурирование канала Slack Для канала `slack` требуется параметр конфигурации `url`. Это значение может быть определено через переменную среды `LOG_SLACK_WEBHOOK_URL`. Этот URL-адрес должен соответствовать URL-адресу [входящего веб-хука](https://slack.com/apps/A0F7XDUAZ-incoming-webhooks), который вы настроили для своей команды Slack. По умолчанию Slack будет получать логи только с уровнем `critical` и выше; однако вы можете настроить это, используя переменную среды `LOG_LEVEL` или изменив параметр конфигурации `level` в массиве вашего драйвера Slack. ### Логирование предупреждений об устаревании PHP, Laravel и другие библиотеки часто уведомляют своих пользователей о том, что некоторые из их функций устарели и будут удалены в будущей версии. Если вы хотите регистрировать эти предупреждения об устаревании, вы можете указать предпочитаемый канал журнала `deprecations`, используя переменную среды `LOG_DEPRECATIONS_CHANNEL` или в файле конфигурации вашего приложения `config/logging.php`: 'deprecations' => [ 'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'), 'trace' => env('LOG_DEPRECATIONS_TRACE', false), ], 'channels' => [ // ... ] Или вы можете определить канал журнала с именем `deprecations`. Если канал журнала с таким именем существует, он всегда будет использоваться для регистрации устаревания: 'channels' => [ 'deprecations' => [ 'driver' => 'single', 'path' => storage_path('logs/php-deprecation-warnings.log'), ], ], ## Построение стека журналов Как упоминалось ранее, драйвер `stack` позволяет для удобства объединить несколько каналов в один канал журнала. Чтобы проиллюстрировать, как использовать стеки журналов, давайте рассмотрим пример конфигурации, которую вы можете увидеть в эксплуатационном приложении: ```php 'channels' => [ 'stack' => [ 'driver' => 'stack', 'channels' => ['syslog', 'slack'], // [tl! add] 'ignore_exceptions' => false, ], 'syslog' => [ 'driver' => 'syslog', 'level' => env('LOG_LEVEL', 'debug'), 'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER), 'replace_placeholders' => true, ], 'slack' => [ 'driver' => 'slack', 'url' => env('LOG_SLACK_WEBHOOK_URL'), 'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'), 'emoji' => env('LOG_SLACK_EMOJI', ':boom:'), 'level' => env('LOG_LEVEL', 'critical'), 'replace_placeholders' => true, ], ], ``` Давайте разберем эту конфигурацию. Во-первых, обратите внимание, что наш канал `stack` объединяет два других канала с помощью параметра `channels`: `syslog` и `slack`. Таким образом, при регистрации сообщений оба канала будут иметь возможность регистрировать сообщение. Однако, как мы увидим ниже, действительно ли эти каналы регистрируют сообщение, может быть определено серьезностью / «уровнем» сообщения. #### Уровни журнала Обратите внимание на параметр конфигурации `level`, присутствующий в конфигурациях каналов `syslog` и `slack` в приведенном выше примере. Эта опция определяет минимальный «уровень» сообщения, которое должно быть зарегистрировано каналом. Monolog, на котором работают службы ведения журналов Laravel, предлагает все уровни журналов, определенные в спецификации [RFC 5424 specification](https://tools.ietf.org/html/rfc5424). Эти уровни журнала в порядке убывания критичности: **emergency**, **alert**, **critical**, **error**, **warning**, **notice**, **info**, и **debug**. Итак, представьте, что мы регистрируем сообщение, используя метод `debug`: Log::debug('An informational message.'); Учитывая нашу конфигурацию, канал `syslog` будет записывать сообщение в системный журнал; однако, поскольку сообщение об ошибке не является уровнем `critical` или выше, то оно не будет отправлено в Slack. Однако, если мы регистрируем сообщение уровня `emergency`, то оно будет отправлено как в системный журнал, так и в Slack, поскольку уровень `emergency` выше нашего минимального порогового значения для обоих каналов: Log::emergency('The system is down!'); ## Запись сообщений журнала Вы можете записывать информацию в журналы с помощью [фасада](/docs/{{version}}/facades) `Log`. Как упоминалось ранее, средство ведения журнала обеспечивает восемь уровней ведения журнала, определенных в спецификации [RFC 5424 specification](https://tools.ietf.org/html/rfc5424): **emergency**, **alert**, **critical**, **error**, **warning**, **notice**, **info**, и **debug**. use Illuminate\Support\Facades\Log; Log::emergency($message); Log::alert($message); Log::critical($message); Log::error($message); Log::warning($message); Log::notice($message); Log::info($message); Log::debug($message); Вы можете вызвать любой из этих методов, чтобы записать сообщение для соответствующего уровня. По умолчанию сообщение будет записано в канал журнала по умолчанию, как настроено вашим файлом конфигурации `logging`: $id]); return view('user.profile', [ 'user' => User::findOrFail($id) ]); } } ### Контекстная информация Методам журнала может быть передан массив контекстных данных. Эти контекстные данные будут отформатированы и отображены в сообщении журнала: use Illuminate\Support\Facades\Log; Log::info('User {id} failed to login.', ['id' => $user->id]); Иногда вы можете указать некоторую контекстную информацию, которая должна быть включена во все последующие записи журнала в определенном канале. Например, вы можете захотеть зарегистрировать идентификатор запроса, связанный с каждым входящим запросом к вашему приложению. Для этого вы можете вызвать метод `withContext` фасада `Log`: $requestId ]); $response = $next($request); $response->headers->set('Request-Id', $requestId); return $response; } } Если вы хотите добавить общую информацию между _всеми_ каналами, вы можете вызвать метод `Log::shareContext()`. Этот метод предоставит дополнительную информацию всем созданным каналам и всем каналам, которые будут созданы впоследствии. $requestId ]); // ... } } > [!NOTE] > Если вам нужно передавать контекст журнала при обработке задач в очереди, вы можете использовать [middleware заданий](/docs/{{version}}/queues#job-middleware). ### Запись в определенные каналы По желанию можно записать сообщение в канал, отличный от канала по умолчанию вашего приложения. Вы можете использовать метод `channel` фасада `Log` для получения и регистрации любого канала, определенного в вашем файле конфигурации: use Illuminate\Support\Facades\Log; Log::channel('slack')->info('Something happened!'); Если вы хотите создать стек протоколирования по запросу, состоящий из нескольких каналов, вы можете использовать метод `stack`: Log::stack(['single', 'slack'])->info('Something happened!'); #### Каналы по запросу Также возможно создать канал по запросу, предоставив конфигурацию во время выполнения, без того, чтобы эта конфигурация присутствовала в файле `logging` вашего приложения. Для этого вы можете передать массив конфигурации методу `build` фасада `Log`: use Illuminate\Support\Facades\Log; Log::build([ 'driver' => 'single', 'path' => storage_path('logs/custom.log'), ])->info('Something happened!'); Вы также можете включить канал по запросу в стек журналов по запросу. Этого можно добиться, включив экземпляр вашего канала по запросу в массив, переданный в метод `stack`: use Illuminate\Support\Facades\Log; $channel = Log::build([ 'driver' => 'single', 'path' => storage_path('logs/custom.log'), ]); Log::stack(['slack', $channel])->info('Something happened!'); ## Настройка канала Monolog ### Настройка Monolog для каналов Иногда требуется полный контроль над настройкой Monolog для существующего канала. Например, бывает необходимо настроить собственную реализацию Monolog `FormatterInterface` для встроенного в Laravel канала `single`. Для начала определите массив `tap` в конфигурации канала. Массив `tap` должен содержать список классов, которые должны иметь возможность настраивать (или «касаться») экземпляр Monolog после его создания. Не существует обычного места для размещения этих классов, поэтому вы можете создать каталог в своем приложении, чтобы разместить эти классы: 'single' => [ 'driver' => 'single', 'tap' => [App\Logging\CustomizeFormatter::class], 'path' => storage_path('logs/laravel.log'), 'level' => env('LOG_LEVEL', 'debug'), 'replace_placeholders' => true, ], После того как вы настроили опцию `tap` своего канала, вы готовы определить класс, который будет контролировать ваш экземпляр Monolog. Этому классу нужен только один метод: `__invoke`, который получает экземпляр `Illuminate\Log\Logger`. Экземпляр `Illuminate\Log\Logger` передает все вызовы методов базовому экземпляру Monolog: getHandlers() as $handler) { $handler->setFormatter(new LineFormatter( '[%datetime%] %channel%.%level_name%: %message% %context% %extra%' )); } } } > [!NOTE] > Все ваши классы «tap» извлекаются через [контейнер служб](/docs/{{version}}/container), поэтому любые зависимости конструктора, которые им требуются, будут автоматически внедрены. ### Создание обработчика каналов Monolog В Monolog есть множество [доступных обработчиков](https://github.com/Seldaek/monolog/tree/main/src/Monolog/Handler), а в Laravel из коробки не включены каналы для каждого из них. В некоторых случаях вам может потребоваться создать собственный канал, являющийся просто экземпляром определенного обработчика Monolog, у которого нет соответствующего драйвера журнала Laravel. Эти каналы могут быть легко созданы с помощью драйвера `monolog`. При использовании драйвера `monolog` параметр конфигурации `handler` используется для указания того, какой обработчик будет создан. При желании любые параметры конструктора, необходимые обработчику, могут быть указаны с помощью опции конфигурации `with`: 'logentries' => [ 'driver' => 'monolog', 'handler' => Monolog\Handler\SyslogUdpHandler::class, 'with' => [ 'host' => 'my.logentries.internal.datahubhost.company.com', 'port' => '10000', ], ], #### Форматтеры Monolog При использовании драйвера `monolog`, Monolog-класс `LineFormatter` будет использоваться как средство форматирования по умолчанию. Однако вы можете настроить тип средства форматирования, передаваемого обработчику, используя параметры конфигурации `formatter` и `formatter_with`: 'browser' => [ 'driver' => 'monolog', 'handler' => Monolog\Handler\BrowserConsoleHandler::class, 'formatter' => Monolog\Formatter\HtmlFormatter::class, 'formatter_with' => [ 'dateFormat' => 'Y-m-d', ], ], Если вы используете обработчик Monolog, который может предоставлять свой собственный модуль форматирования, вы можете установить для параметра конфигурации `formatter` значение `default`: 'newrelic' => [ 'driver' => 'monolog', 'handler' => Monolog\Handler\NewRelicHandler::class, 'formatter' => 'default', ], #### Monolog Процессоры (Processors) Monolog также может обрабатывать сообщения перед их записью в журнал. Вы можете создавать свои собственные процессоры или использовать [существующие процессоры, предлагаемые Monolog](https://github.com/Seldaek/monolog/tree/main/src/Monolog/Processor). Если вы хотите кастомизировать процессоры для драйвера `monolog`, добавьте значение конфигурации `processors` в конфигурацию вашего канала: 'memory' => [ 'driver' => 'monolog', 'handler' => Monolog\Handler\StreamHandler::class, 'with' => [ 'stream' => 'php://stderr', ], 'processors' => [ // Simple syntax... Monolog\Processor\MemoryUsageProcessor::class, // With options... [ 'processor' => Monolog\Processor\PsrLogMessageProcessor::class, 'with' => ['removeUsedContextFields' => true], ], ], ], ### Создание каналов через фабрики Если вы хотите определить полностью настраиваемый канал, в котором у вас есть полный контроль над созданием и конфигурацией Monolog, вы можете указать тип драйвера `custom` в файле конфигурации `config/logging.php`. Ваша конфигурация должна включать параметр `via`, содержащий имя класса фабрики, которая будет вызываться для создания экземпляра Monolog: 'channels' => [ 'example-custom-channel' => [ 'driver' => 'custom', 'via' => App\Logging\CreateCustomLogger::class, ], ], После того как вы настроили канал драйвера `custom`, вы готовы определить класс, который будет создавать ваш экземпляр Monolog. Этому классу нужен только один метод `__invoke`, который должен возвращать экземпляр регистратора Monolog. Метод получит массив конфигурации каналов в качестве единственного аргумента: ## Просмотр сообщения журнала с помощью Pail Часто вам может понадобиться просматривать журналы приложения в режиме реального времени. Например, при отладке проблемы или при мониторинге журналов приложения на предмет определенных типов ошибок. Laravel Pail - это пакет, который позволяет вам легко погружаться в лог-файлы вашего приложения Laravel прямо из командной строки. В отличие от стандартной команды `tail`, Pail предназначен для работы с любым драйвером журналов, включая Sentry или Flare. Кроме того, Pail предоставляет набор полезных фильтров, которые помогут вам быстро найти то, что вы ищете. ### Установка > [!WARNING] > Laravel Pail поддерживает [PHP 8.2+](https://php.net/releases/) и расширение [PCNTL](https://www.php.net/manual/en/book.pcntl.php). Чтобы начать работу, установите Pail в свой проект с помощью менеджера пакетов Composer: ```bash composer require laravel/pail ``` ### Использование Чтобы начать отслеживать журналы, выполните команду `pail`: ```bash php artisan pail ``` Чтобы увеличить детализацию вывода и избежать усечения (…), используйте опцию `-v`: ```bash php artisan pail -v ``` Для максимальной детализации и отображения трассировок стека исключений используйте опцию `-vv` : ```bash php artisan pail -vv ``` Чтобы прекратить отслеживание журналов, нажмите `Ctrl+C` в любой момент. ### Фильтрация логов #### `--filter` Вы можете использовать опцию `--filter` для фильтрации журналов по их типу, файлу, сообщению и содержимому трассировки стека: ```bash php artisan pail --filter="QueryException" ``` #### `--message` Чтобы фильтровать журналы только по их сообщениям, вы можете использовать опцию `--message`: ```bash php artisan pail --message="User created" ``` #### `--level` Опцию `--level` можно использовать для фильтрации журналов по их [уровню](#log-levels): ```bash php artisan pail --level=error ``` #### `--user` Чтобы отображать только те журналы, которые были записаны при аутентифицированным пользователем, вы можете указать идентификатор пользователя в опции `--user`: ```bash php artisan pail --user=1 ```