🎩 Книга «Денди-код» о том, как сделать код аккуратным и понятным

Ошибки и логирование

Вы просматриваете документ для прошлой версии.
Рассмотрите возможность обновления вашего проекта до актуальной версии 13.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();