---
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
```