Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Building Web Apps with Laravel  Module 11 – Inside the framework

Errors, logging and context

Configure how Laravel 13 reports and renders errors, keep exception details off visitors' pages, and tie every log line to its request with context.

  • Intermediate
  • 15 minutes
  • Examples run with PHP 8.5.11, Composer 2.10.3, Laravel 13.34.0 and Python 3.14.8
  • By MySmartCoPilot
Free core, Pro depth: 6 of 15 minutes free
Free: Laravel reports errors, then renders a response · Debug mode decides how much of the errors a visitor sees · Logging and context: one line per event, with its request. With a pass: 2 in-depth parts and 3 interview answers, about 9 minutes.

What you will learn

  • Configure exception reporting and rendering in bootstrap/app.php
  • Show generic error pages to visitors while the details stay in the logs
  • Log to the right channel and level for each environment, with secrets masked
  • Trace one request across every log line with the Context facade
  • Test the error pages and the log lines so that a leak fails the build

Before you start

What you’ll learn · Before you start

What you will learn

  • Configure exception reporting and rendering in bootstrap/app.php
  • Show generic error pages to visitors while the details stay in the logs
  • Log to the right channel and level for each environment, with secrets masked
  • Trace one request across every log line with the Context facade
  • Test the error pages and the log lines so that a leak fails the build

Before you start

On this page

Pathshala’s fee sync failed one evening, and the 500 page a parent saw showed the database password, while the log could not say which of that hour’s requests had failed. Laravel handles errors in two steps: it reports each exception to the logs and renders a response for the visitor. Its logging writes lines to channels, and context adds fields such as a request id to every line of a request.

You will run one failing route with debug mode on and off, and write log lines that carry their request id. Later parts control how your own exceptions are reported and rendered, and keep logs searchable with no secrets in them, into queued jobs too.

Laravel reports errors, then renders a response

Every exception that leaves your code reaches Laravel’s exception handler: The part of Laravel that receives every exception that leaves your code. It reports the exception, usually to the log, then renders the response the visitor gets. Its rules live in the withExceptions callback of bootstrap/app.php., which deals with it in two separate steps. exception reporting: Recording an exception for the team, by default as a log line with its message and stack trace. It happens the same way whether debug mode is on or off. records the exception, by default as a log line with its message and its stack trace. exception rendering: Turning an exception into the response a visitor receives: an HTML page, or JSON for a client that asks for it. Debug mode decides how much of the exception the response shows. turns it into the response the visitor receives: an HTML page, or JSON for a client that asks for one. Both steps are set up in the withExceptions() callback of bootstrap/app.php, and a new project has one rule there, which picks JSON for paths under api/ and for requests that ask for JSON:

bootstrap/app.php of a new Laravel 13 project PHP · debug/bootstrap/app.php
<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Request;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        //
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        $exceptions->shouldRenderJsonWhen(
            fn (Request $request) => $request->is('api/*') || $request->expectsJson(),
        );
    })->create();

Follow the exception that Pathshala’s fee sync route throws:

Interactive · stage by stage One exception through the handler Step through what Laravel did with the exception the fee sync route threw, from the throw to the response.
One exception, reported and then rendered, step 5 of 5. Showing The route throws, The kernel catches it, report() (laravel.log, ERROR), render(), The response. In focus: The response.The route throwsa RuntimeExceptionThe kernel catches itthe request goes onreport()laravel.log, ERRORrender()JSON or a pageThe responsestatus 500

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. An exception leaves the route. The fee sync route throws a RuntimeException. Nothing in the route catches it, so it travels up through the middleware towards the HTTP kernel.
  2. The kernel catches it. The kernel never lets an exception reach PHP's own error output. It hands the exception to Laravel's exception handler, which works in two separate steps.
  3. Step one reports. Reporting writes the exception to the log, with its message and its stack trace. It happens the same way whether debug mode is on or off, which is why the log held the message in both runs.
  4. Step two renders. Rendering builds what the visitor receives. The skeleton's one rule in bootstrap/app.php picks JSON for an api path or a client that asks for it, and an HTML page otherwise; debug mode decides how much of the exception either one shows.
  5. The response goes out. The visitor gets status 500 with the generic page or the body message Server Error. The details stay in the log, where only the team can read them.

The same callback holds the rules that handle errors you expect. With dontReport(), a kind of exception is rendered but never logged. With throttle(), only some reports of a noisy exception are kept. An exception class can also carry report() and render() methods of its own, which the handler calls instead of its defaults.

Debug mode decides how much of the errors a visitor sees

Debug mode follows APP_DEBUG, which a new project’s .env sets to true. The session sends one failing request with debug on and off, as a browser and as a JSON client, and the route’s message holds an invented password:

The failing route, and the test that checks what it shows

routes/web.php · debug/routes/web.php

<?php

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

// A sync job written in a hurry: its error message includes the database password (an invented one).
// The lesson uses it to show where such a message ends up; never put a secret into an exception message.
Route::get('/fees/sync', function () {
    throw new RuntimeException('Could not reach the fee database: DB password is hunter2');
});

debug/tests/Feature/ErrorPagesTest.php

<?php

namespace Tests\Feature;

use Illuminate\Support\Facades\Route;
use RuntimeException;
use Tests\TestCase;

// Run it in the pipeline with the production settings: it fails the build whenever a 500 shows exception details.
class ErrorPagesTest extends TestCase
{
    public function test_a_server_error_shows_no_exception_details(): void
    {
        Route::get('/boom', fn () => throw new RuntimeException('Could not reach the fee database: DB password is hunter2'));

        $page = $this->get('/boom')->assertStatus(500)->getContent();
        $this->assertFalse(str_contains($page, 'hunter2'), 'The 500 page shows the exception message.');

        $json = $this->getJson('/boom')->assertStatus(500);
        $this->assertSame('Server Error', $json->json('message'), 'The JSON error shows the exception message.');
    }
}
The same failing request with APP_DEBUG true and false Python · debug_session.py
"""Debug mode and what a visitor sees: the same failing route with APP_DEBUG=true and APP_DEBUG=false, for a browser
and for a JSON client, then a test that fails while debug is on and passes once it is off. The password in the
message is invented. Files: the folder debug/ next to this file."""

from session import run

run(
    """
    export COLLISION_IGNORE_DURATION=true
    export APP_DEBUG=true
    php debug_probe.php
    !php artisan test --filter=ErrorPagesTest
    export APP_DEBUG=false
    php debug_probe.php
    php artisan test --filter=ErrorPagesTest
    """,
    app=True,
    overlay=("debug",),
)

Output

$ export COLLISION_IGNORE_DURATION=true
$ export APP_DEBUG=true
$ php debug_probe.php
APP_DEBUG=true
browser:     status 500, page shows the password: yes, page title: Laravel
JSON client: status 500, body keys: message, exception, file, line, trace
             message: "Could not reach the fee database: DB password is hunter2"
log file:    local.ERROR: Could not reach the fee database: DB password is hunter2 (the stack trace follows)
$ php artisan test --filter=ErrorPagesTest
   FAIL  Tests\Feature\ErrorPagesTest
  ⨯ a server error shows no exception details
  ────────────────────────────────────────────────────────────────────────────
   FAILED  Tests\Feature\ErrorPagesTest > a server error shows no exception…
  The 500 page shows the exception message.
Failed asserting that true is false.

  at tests/Feature/ErrorPagesTest.php:17
     13▕     {
     14▕         Route::get('/boom', fn () => throw new RuntimeException('Could not reach the fee database: DB password is hunter2'));
     15▕
     16▕         $page = $this->get('/boom')->assertStatus(500)->getContent();
  ➜  17▕         $this->assertFalse(str_contains($page, 'hunter2'), 'The 500 page shows the exception message.');
     18▕
     19▕         $json = $this->getJson('/boom')->assertStatus(500);
     20▕         $this->assertSame('Server Error', $json->json('message'), 'The JSON error shows the exception message.');
     21▕     }

  1   tests/Feature/ErrorPagesTest.php:17


  Tests:    1 failed (2 assertions)
  Duration: …s
[exit status 1]
$ export APP_DEBUG=false
$ php debug_probe.php
APP_DEBUG=false
browser:     status 500, page shows the password: no, page title: Server Error
JSON client: status 500, body keys: message
             message: "Server Error"
log file:    local.ERROR: Could not reach the fee database: DB password is hunter2 (the stack trace follows)
$ php artisan test --filter=ErrorPagesTest
   PASS  Tests\Feature\ErrorPagesTest
  ✓ a server error shows no exception details

  Tests:    1 passed (4 assertions)
  Duration: …s

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 debug_session.py

With debug on, the page showed the password, and the JSON body had five keys, message, exception, file, line and trace, which name your application’s files. With debug off, the page was the generic Server Error page and the body held only that message. The log line kept the full message in both runs, because reporting does not depend on debug mode. The Laravel documentation requires debug off in production.

The test turns that rule into a check: it failed while debug was on and passed once it was off. Run it with your production settings in the pipeline, and a deploy that would show details fails first.

A secret inside an exception message

Debug off kept the password off the page, but the log line still held it. Name what failed in a message, such as fee database unreachable, and never put credentials, tokens or personal data there.

Pages for the statuses you expect, such as 403 or 404, are Blade views in resources/views/errors/.

Checkpoint

Check: Reporting and rendering · What debug mode shows

  1. Question 1 of 2 Which of Laravel's two steps decides what a visitor receives when a route throws?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Rendering, which builds the HTML page or the JSON body

    The handler reports first, by default as a log line with the message and the stack trace, then renders the response. The two steps are independent, which is why the log held the details while the page did not.

  2. Question 2 of 2 With APP_DEBUG=false, a JSON client requests a route that throws a RuntimeException. What is the body?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Only a message key, holding "Server Error"

    Debug mode decides how much of the exception the response shows. Off, the body says Server Error; the details still reach the log, because reporting does not depend on it.

Logging and context: one line per event, with its request

Logging in Laravel sends every line to a log channel: A named destination for log lines in config/logging.php, such as single (one file), daily (a file per day), stderr or stack, which forwards each line to a list of other channels., set up in config/logging.php. A new project’s stack channel forwards each line to the channels that LOG_STACK lists, here only single, the file storage/logs/laravel.log. The log level: The severity of a log line, from debug up to emergency. A channel writes only lines at or above its level, which Laravel reads from LOG_LEVEL. in LOG_LEVEL is the lowest level a channel writes, from debug up to emergency.

Context makes logging useful across a request. The Context facade stores values for the current request, and Laravel adds them to every log line written while it runs. This middleware stores a request id: A unique value given to one request and written on every log line it produces, and often returned in a response header, so that all the lines of that request can be found with one search., keeping the one a proxy sent when it looks valid:

A global middleware that adds the request id to the context

context/app/Http/Middleware/AssignRequestId.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;

// Gives every request an id, adds it to the context so that every log line of the request carries it, and returns it
// in a header so a support message can quote it. An id from the proxy is kept only if it looks like one.
class AssignRequestId
{
    public function handle(Request $request, Closure $next): Response
    {
        $given = (string) $request->header('X-Request-Id');
        $id = preg_match('/^[A-Za-z0-9-]{8,64}$/', $given) ? $given : (string) Str::uuid();

        Context::add('request_id', $id);

        $response = $next($request);
        $response->headers->set('X-Request-Id', $id);

        return $response;
    }
}

routes/web.php · context/routes/web.php

<?php

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

// A receipt page that writes two log lines: a detail for debugging, and the event itself.
Route::get('/instalments/{id}/receipt', function (string $id) {
    Log::debug('Receipt total computed', ['instalment' => (int) $id, 'paise' => 118000]);
    Log::info('Receipt viewed', ['instalment' => (int) $id]);

    return response('Receipt for instalment '.$id);
});

bootstrap/app.php · context/bootstrap/app.php

<?php

use App\Http\Middleware\AssignRequestId;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Request;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        $middleware->append(AssignRequestId::class); // global: every request gets an id first
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        $exceptions->shouldRenderJsonWhen(
            fn (Request $request) => $request->is('api/*') || $request->expectsJson(),
        );
    })->create();
Two requests, then the same with LOG_LEVEL=info Python · context_session.py
"""Logging with context: a global middleware adds the request id to the context, so every log line of the request
carries it; the same requests are sent again with LOG_LEVEL=info, which drops the debug line. The time at the start of
each log line is left out. Files: the folder context/ next to this file."""

from session import run

run(
    """
    php context_probe.php
    export LOG_LEVEL=info
    php context_probe.php
    """,
    app=True,
    overlay=("context",),
)

Output

$ php context_probe.php
GET /instalments/42/receipt -> 200, X-Request-Id: req-1001-asha
GET /instalments/43/receipt -> 200, X-Request-Id: req-1002-kabir
storage/logs/laravel.log (LOG_LEVEL=debug):
  local.DEBUG: Receipt total computed {"instalment":42,"paise":118000} {"request_id":"req-1001-asha"}
  local.INFO: Receipt viewed {"instalment":42} {"request_id":"req-1001-asha"}
  local.DEBUG: Receipt total computed {"instalment":43,"paise":118000} {"request_id":"req-1002-kabir"}
  local.INFO: Receipt viewed {"instalment":43} {"request_id":"req-1002-kabir"}
$ export LOG_LEVEL=info
$ php context_probe.php
GET /instalments/42/receipt -> 200, X-Request-Id: req-1001-asha
GET /instalments/43/receipt -> 200, X-Request-Id: req-1002-kabir
storage/logs/laravel.log (LOG_LEVEL=info):
  local.INFO: Receipt viewed {"instalment":42} {"request_id":"req-1001-asha"}
  local.INFO: Receipt viewed {"instalment":43} {"request_id":"req-1002-kabir"}

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 context_session.py

Every line ended with its request’s id, although no logging call mentioned one, so one search finds all that a request did. With LOG_LEVEL=info the debug lines were gone.

For servers and containers, the daily channel keeps a file per day and the stderr channel can write each line as JSON. A log processor: A function that Monolog runs on every log record before it is written. It can add fields to the record or change them, for example to mask a phone number. can mask phone numbers and tokens before a line is written. Values stored as hidden context: Values stored with Context::addHidden(). Code can read them with Context::getHidden(), but Laravel leaves them out of the log lines that carry the rest of the context. stay available to code and never appear in log lines.

Checkpoint

Check: Channels, levels and context

  1. Question 1 of 2 A middleware calls Context::add('request_id', $id), and the controller calls Log::info('Receipt viewed', [...]) without any id. What does the log line hold?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: The message, its own context, and the request id from the Context facade

    Context values are added to the extra part of every log record written during the request, so one search for the id finds everything the request logged.

  2. Question 2 of 2 A request writes one debug line and one info line. LOG_LEVEL is set to info. What reaches the log file?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Only the info line

    LOG_LEVEL sets the lowest severity a channel writes, from debug up to emergency. Development often keeps debug, while production usually starts at info.

Exception classes that report and render themselves, throttled and critical errors, error pages and tests with Exceptions::fake() Pro: opens with a Pro, Premium or Ultimate pass

The skeleton’s one rule is a start. Exception classes can log and explain themselves, an outage can be quieted without hiding new bugs, and tests can keep the rules from drifting.

In this part:

  • An exception class that logs itself and explains itself
  • Throttling a noisy failure, and raising a serious one
  • What every report carries, and what it should not
  • Error pages and abort() for the statuses you expect
  • Testing the rules with Exceptions::fake()

4 runnable examples (FeeAlreadyPaid.php, PHP, PaymentDeclined.php, Python, bootstrap/app.php, handling_probe.php, routes/web.php) · about 7 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Channels for each environment, a processor that masks secrets with a failing test, and one request id from the web request into a queued job Pro: opens with a Pro, Premium or Ultimate pass

A log helps only when you can find the lines you need and nothing in it can hurt anyone. Channels can follow the environment, a processor that a test proves can mask secrets, and one request id can follow the work into a queued job.

In this part:

  • Channels and levels for each environment
  • A processor that masks phone numbers and tokens, proven by a failing test
  • Deciding what a log line says
  • One request id from the web request to the queued job

1 diagram · 4 runnable examples (AddRedaction.php, LogRedactionTest.php, Python, RedactSecrets.php, SendFeeReceipt.php, queue_probe.php, routes/web.php) · about 9 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Practise

Try both halves in your own Pathshala project:

  1. Add the AssignRequestId middleware with $middleware->append(...) in bootstrap/app.php, request a page, and find the id in the X-Request-Id header and on its log lines.
  2. Set APP_DEBUG=false, request a route that throws, and compare the page and the JSON body.
  3. Add ErrorPagesTest to your tests and run it with debug on and with debug off.

Then take the self-check:

Practice that adapts to you

Practise this lesson

6 questions about 10 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 6 Debug is off and a route throws. Where can the team find the exception's message?

    Choose one answer.

    Show the answer: Question 1 of 6

    Answer: In the log, because reporting writes it whatever debug mode is

    Reporting and rendering are separate, so turning debug off hides details from visitors and keeps them for the team.

  2. Question 2 of 6 A mobile app calls /fees/sync with an Accept header of application/json, not under api/. What does the skeleton's rule return when it fails?

    Choose one answer.

    Show the answer: Question 2 of 6

    Answer: JSON, because the rule also covers requests that ask for JSON

    shouldRenderJsonWhen in bootstrap/app.php decides the format: is('api/*') or expectsJson(). Change it there if your clients need another rule.

  3. Question 3 of 6 Where does a new Laravel project's debug setting come from?

    Choose one answer.

    Show the answer: Question 3 of 6

    Answer: The APP_DEBUG value in the environment, which a new .env sets to true

    APP_DEBUG must be set to false in every environment that faces the public; APP_ENV=production does not do it for you.

  4. Question 4 of 6 How can a pipeline stop a deploy whose settings would show exception details to visitors?

    Choose one answer.

    Show the answer: Question 4 of 6

    Answer: Run a test that throws in a route and asserts that the 500 body does not contain the message, with the production settings

    A check that fails on the weak setting and passes on the fix turns a rule into something a deploy cannot skip.

  5. Question 5 of 6 In a new Laravel 13 project, where do log lines go by default?

    Choose one answer.

    Show the answer: Question 5 of 6

    Answer: To the stack channel, which forwards them to single, the file storage/logs/laravel.log

    The stack channel is a list of channels. Adding daily or stderr to LOG_STACK sends each line to all of them.

  6. Question 6 of 6 A parent quotes the X-Request-Id shown on an error page. Why does the middleware's design make that id useful to support?

    Choose one answer.

    Show the answer: Question 6 of 6

    Answer: The same id is on every log line of that request, so one search returns all of them

    An id that appears both in the response and on the log lines links a visitor's report to the exact lines, without exposing anything else.

Interview questions

Warm-up: in Laravel, what is the difference between reporting an exception and rendering it?

Reporting records the exception for the team, by default as a log line with its message and stack trace, and it happens whatever the visitor sees. Rendering builds the response the visitor gets, an HTML page or JSON, and debug mode decides how much detail it shows. Both are configured in the withExceptions callback of bootstrap/app.php.

Three longer questions follow:

  1. Mid to senior

    A parent emails Pathshala a screenshot of an error page that shows a file path, a SQL query and some configuration values. Production was deployed an hour ago. Say what you do in the first hour, and what stops it from happening again.

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to staff

    A guardian says a payment went through yesterday evening but no receipt SMS arrived. Pathshala runs three web servers and two queue workers, all logging JSON to standard error. Design logging that lets support answer in five minutes, and say what must never appear in those lines.

    Model answer, Pro. First step and follow-ups

  3. Mid to senior

    During an SMS provider outage, Pathshala's error tracker receives 4,000 timeout reports an hour, and a new bug in fee calculation goes unnoticed for a day. Change the reporting rules so the outage stays visible without drowning everything else, and say what parents see meanwhile.

    Model answer, Pro. First step and follow-ups

Flashcards · 7 cards

Recall it, then check

Say the answer to yourself before you look: recalling it is what makes it stick.

  1. What two steps does Laravel's exception handler take with an exception?

    Reporting records it, by default as a log line with the message and stack trace. Rendering turns it into the visitor's response, an HTML page or JSON. Both are set up in the withExceptions() callback of bootstrap/app.php.

  2. Which tools in withExceptions() handle errors you expect?

    dontReport() renders a kind of exception but never logs it, and throttle() keeps only some reports of a noisy one. An exception class may also carry its own report() and render() methods, which the handler calls instead.

  3. What does a visitor see of a failing request with APP_DEBUG on and off?

    On, which a new project's .env sets, the page showed the message with an invented password, and the JSON body had message, exception, file, line and trace. Off, the generic Server Error page and only that message. Production requires debug off.

  4. Debug mode is off. Can a secret in an exception message still leak?

    Yes, into the log: reporting does not depend on debug mode, so the log line kept the full message. Name what failed, such as fee database unreachable, and never put credentials, tokens or personal data in a message.

  5. How do you stop a deploy that would show error details to visitors?

    A test that checks the error response with production settings: it failed while debug was on and passed once it was off. Run it in the pipeline so the bad deploy fails first.

  6. How does a new project's logging decide where a line goes and which lines are written?

    config/logging.php sends lines to the stack channel, which forwards them to the channels in LOG_STACK, here single, the file storage/logs/laravel.log. LOG_LEVEL is the lowest level a channel writes, from debug up to emergency.

  7. How do all the log lines of one request carry its request id?

    A middleware stores the id with the Context facade, and Laravel adds context values to every log line written during that request, though no logging call mentions them. Hidden context stays available to code but never appears in log lines.

Key takeaways

  • Laravel handles every exception in two steps: reporting writes it to the logs, rendering builds the page or the JSON the visitor receives.
  • With APP_DEBUG=true a 500 shows the message and your files to anyone, so production runs with debug off, and a test that searches the 500 response keeps it so.
  • Logging writes each line to a channel at a level, and the Context facade adds fields such as a request id to every line of a request.

Terms in this lesson

exception handler
The part of Laravel that receives every exception that leaves your code. It reports the exception, usually to the log, then renders the response the visitor gets. Its rules live in the withExceptions callback of bootstrap/app.php.
exception rendering
Turning an exception into the response a visitor receives: an HTML page, or JSON for a client that asks for it. Debug mode decides how much of the exception the response shows.
exception reporting
Recording an exception for the team, by default as a log line with its message and stack trace. It happens the same way whether debug mode is on or off.
hidden context
Values stored with Context::addHidden(). Code can read them with Context::getHidden(), but Laravel leaves them out of the log lines that carry the rest of the context.
log channel
A named destination for log lines in config/logging.php, such as single (one file), daily (a file per day), stderr or stack, which forwards each line to a list of other channels.
log level
The severity of a log line, from debug up to emergency. A channel writes only lines at or above its level, which Laravel reads from LOG_LEVEL.
log processor
A function that Monolog runs on every log record before it is written. It can add fields to the record or change them, for example to mask a phone number.
request id
A unique value given to one request and written on every log line it produces, and often returned in a response header, so that all the lines of that request can be found with one search.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.