Ошибки и логирование
11.x
.
Почему это важно?
Введение
Когда вы начинаете новый Laravel проект, обработка ошибок и исключений уже настроена для вас. Все происходящие в вашем приложении исключения записываются в журнал и отображаются пользователю в классе App\Exceptions\Handler
. В этой документации мы подробно рассмотрим этот класс.
Для логгирования Laravel использует библиотеку Monolog, которая обеспечивает поддержку различных мощных обработчиков логов. В Laravel настроены несколько из них, благодаря чему вы можете выбрать между единым файлом журнала, ротируемыми файлами журналов и записью информации в системный журнал.
Настройка
Детализация ошибок
Параметр debug
в файле настроек config/app.php
определяет, сколько информации об ошибке показывать пользователю. По умолчанию этот параметр установлен в соответствии со значением переменной среды APP_DEBUG
, которая хранится в файле .env
.
Для локальной разработки вам следует установить переменную среды APP_DEBUG
в значение true
. В продакшн-среде эта переменная всегда должна иметь значение false
. Если значение равно true
, на продакшн-сервере, вы рискуете раскрыть важные значения настроек вашим конечным пользователям.
Хранилище логов
Изначально Laravel поддерживает запись журналов в единые файлы single
, в отдельные файлы для каждого дня daily
, в syslog
и errorlog
. Для использования определённого механизма хранения вам надо изменить параметр log
в файле config/app.php
. Например, если вы хотите использовать ежедневные файлы логов вместо единого файла, вам надо установить значение log
равное daily
в файле настроек app
:
'log' => 'daily'
Максимальное число ежедневных файлов логов
При использовании режима daily
Laravel по умолчанию хранит логи только за последние пять дней. Если вы хотите изменить число хранимых файлов, добавьте в файл app
значение для параметра log_max_files
:
'log_max_files' => 30
Коды серьёзности логов
При использовании Monolog сообщения в журнале могут иметь разные уровни серьёзности. По умолчанию Laravel сохраняет в журнал события всех уровней. Но на продакшн-сервере вы можете задать минимальный уровень серьёзности, который необходимо заносить в журнал, добавив параметр log_level
в конфиг app.php
.
После задания этого параметра Laravel будет записывать события всех уровней начиная с указанного и выше. Например, при log_level
равном error
будут записываться события error, critical, alert и emergency:
'log_level' => env('APP_LOG_LEVEL', 'error'),
В Monolog используются следующие уровни серьёзности — от меньшего к большему:
debug
,info
,notice
,warning
,error
,critical
,alert
,emergency
.
Пользовательская настройка Monolog
Если вы хотите иметь полный контроль над конфигурацией Monolog для вашего приложения, вы можете использовать метод приложения configureMonologUsing
. Вызов этого метода необходимо поместить в файл bootstrap/app.php
прямо перед тем, как в нём возвращается переменная $app
:
$app->configureMonologUsing(function ($monolog) {
$monolog->pushHandler(...);
});
return $app;
Обработчик исключений
Метод Report
Все исключения обрабатываются классом App\Exceptions\Handler
. Этот класс содержит два метода: report
и render
. Рассмотрим каждый из них подробнее. Метод report
используется для занесения исключений в журнал или для отправки их во внешний сервис, такой как Bugsnag или Sentry. По умолчанию метод report
просто передаёт исключение в базовую реализацию родительского класса, где это исключение зафиксировано. Но вы можете регистрировать исключения как пожелаете.
Например, если вам необходимо сообщать о различных типах исключений разными способами, вы можете использовать оператор сравнения PHP instanceof
:
/**
* Сообщить или зарегистрировать исключение.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
{
if ($exception instanceof CustomException) {
//
}
return parent::report($exception);
}
Игнорирование исключений заданного типа
Свойство обработчика исключений $dontReport
содержит массив с типами исключений, которые не будут заноситься в журнал. Например, исключения, возникающие при ошибке 404, а также при некоторых других типах ошибок, не записываются в журналы. При необходимости вы можете включить другие типы исключений в этот массив:
/**
* Список типов исключений, о которых не надо сообщать.
*
* @var array
*/
protected $dontReport = [
\Illuminate\Auth\AuthenticationException::class,
\Illuminate\Auth\Access\AuthorizationException::class,
\Symfony\Component\HttpKernel\Exception\HttpException::class,
\Illuminate\Database\Eloquent\ModelNotFoundException::class,
\Illuminate\Validation\ValidationException::class,
];
Метод Render
Метод render
отвечает за конвертацию исключения в HTTP-отклик, который должен быть возвращён браузеру. По умолчанию исключение передаётся в базовый класс, который генерирует для вас отклик. Но вы можете проверить тип исключения или вернуть ваш собственный отклик:
/**
* Отображение HTTP-оклика для исключения.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
if ($exception instanceof CustomException) {
return response()->view('errors.custom', [], 500);
}
return parent::render($request, $exception);
}
HTTP-исключения
Некоторые исключения описывают коды HTTP-ошибок от сервера. Например, это может быть ошибка “страница не найдена” (404), “ошибка авторизации” (401) или даже сгенерированная разработчиком ошибка 500. Для возврата такого отклика из любого места в приложении можете использовать хелпер abort
:
abort(404);
Хелпер abort
немедленно создаёт исключение, которое будет отрисовано обработчиком исключений. Или вы можете предоставить такой отклик:
abort(403, 'Unauthorized action.');
Пользовательские страницы HTTP-ошибок
В Laravel можно легко возвращать свои собственные страницы для различных кодов HTTP-ошибок. Например, для выдачи собственной страницы для ошибки 404 создайте файл resources/views/errors/404.blade.php
. Этот файл будет использован для всех ошибок 404, генерируемых вашим приложением. Представления в этой папке должны иметь имена, соответствующие кодам ошибок. Экземпляр HttpException
, созданный функцией abort
, будет передан в представление как переменная $exception
:
<h2>{{ $exception->getMessage() }}</h2>
Логгирование
Laravel обеспечивает простой простой уровень абстракции над мощной библиотекой Monolog. По умолчанию Laravel настроен на создание файла журнала в директории storage/logs
. Вы можете записывать информацию в журнал при помощи фасада Log
:
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Показать профиль данного пользователя.
*
* @param int $id
* @return Response
*/
public function showProfile($id)
{
Log::info('Showing user profile for user: '.$id);
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
Регистратор событий предоставляет восемь уровней логгирования, как описано в RFC 5424: emergency, alert, critical, error, warning, notice, info и debug.
Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);
Контекстная информация
Также в методы логгирования можно передать массив контекстных данных:
Log::info('User failed to login.', ['id' => $user->id]);
Обращение к расположенному ниже экземпляру Monolog
В Monolog доступно множество дополнительных обработчиков для журналов. При необходимости вы можете получить доступ к расположенному ниже экземпляру Monolog, используемому в Laravel:
$monolog = Log::getMonolog();