Logging and error handling
On a live site you cannot show an error to a visitor, but you need to learn about it. Laravel writes errors to a log and gives the user a tidy page. Your own log messages help you see what happened before a failure.
Writing to the log
use Illuminate\Support\Facades\Log;
Log::info('User logged in', ['user_id' => $user->id]);
Log::warning('Payment succeeded on the second attempt', ['order_id' => $order->id]);
Log::error('The payment service is unavailable');The second argument is an array of details. By default messages go to the storage/logs/laravel.log file.
Levels
| Level | When to use it |
|---|---|
debug | Details for debugging |
info | Ordinary events: a login, an order |
warning | Something unusual, but work continues |
error | An operation failed |
critical | An important part of the system is down |
The LOG_LEVEL variable in .env sets the lowest level that gets written. Production servers usually use warning or error.
Channels
A channel decides where messages go. Channels are described in config/logging.php:
| Channel | What it does |
|---|---|
single | A single file |
daily | A new file for every day, old ones are removed |
stack | Several channels at once |
slack | Messages to a Slack chat |
LOG_CHANNEL=daily
LOG_LEVEL=warningA message can be sent to a specific channel: Log::channel('slack')->critical('The site is down').
How Laravel handles errors
Laravel catches an uncaught exception itself: it writes it to the log and returns a response. With APP_DEBUG=true that is a detailed page with code and the call stack; with false it is a plain "Server error" page.
Custom error pages
Create a template named after the error code in the resources/views/errors folder:
{{-- resources/views/errors/404.blade.php --}}
<x-layout>
<h1>Page not found</h1>
<p>It may have been removed, or the address was mistyped.</p>
<a href="/">Go to the home page</a>
</x-layout>403.blade.php, 500.blade.php and 503.blade.php are made the same way.
Raising an error
abort(404);
abort_if(!$user->is_admin, 403);
abort_unless($post->is_published, 404, 'The post is not published');The findOrFail() method raises a 404 error by itself if the record is not found.
Configuring the handling
Behavior for particular exceptions is set in the bootstrap/app.php file:
use App\Exceptions\PaymentFailed;
->withExceptions(function (Exceptions $exceptions) {
$exceptions->report(function (PaymentFailed $e) {
Log::channel('slack')->error($e->getMessage());
});
$exceptions->render(function (PaymentFailed $e, Request $request) {
return response()->view('errors.payment', status: 402);
});
})report() decides how to record an exception, render() what to show the user.
Common mistake
Passwords, card numbers and tokens must not be written to the log. The log file is read by developers and support staff and is sent to third-party services. Record identifiers — user_id, order_id — rather than the data itself. And do not leave LOG_LEVEL=debug on a production server: the log grows to gigabytes.