laravel request and response logging

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Request and Response Logging in Laravel: Capturing the Full HTTP Lifecycle

As a senior developer working with Laravel, understanding how data flows through the framework—from the incoming HTTP request to the final outgoing response—is crucial for debugging, monitoring, and security analysis. When you are trying to catch an issue related to a specific response, simply logging headers might not be enough; you need the context of the status code, the payload size, and the exact timing.

The challenge you are facing with using the after filter is common: while Laravel provides powerful hooks, accessing the complete, raw HTTP transaction data requires understanding how the framework structures its objects. Let's dive into how to effectively log comprehensive request and response information in your Laravel application.

The Limitations of Basic Header Logging

You correctly identified that logging only $request->headers and $response->headers misses critical information like the HTTP status code (e.g., 200 OK, 404 Not Found, 500 Internal Server Error). This status code is arguably the most important piece of information for diagnosing why a request succeeded or failed.

The raw output you showed—the full HTTP exchange—is what happens at the web server level (like Apache or Nginx), but within Laravel, we interact with structured objects. To log this effectively, we need to extract the status code directly from the response object provided by the framework.

The Solution: Leveraging Response Objects for Complete Logging

Laravel's Request and Response objects are rich in data. By accessing the methods on the $response object, we can capture all the necessary metrics along with the headers. This approach ensures that your logs are actionable and easily searchable.

Here is a refined approach using the after middleware to capture status codes, request method, and response details:

use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

App::after(function (Request $request, Response $response) {
    // Capture the essential request details
    $requestData = [
        'method' => $request->method(),
        'uri' => $request->fullUrl(),
        'headers' => $request->header(), // Access raw headers if needed
    ];

    // Capture the critical response details
    $responseData = [
        'status_code' => $response->getStatusCode(),
        'reason' => $response->getReasonPhrase(),
        'headers' => $response->header(),
        'body_length' => strlen($response->getContent()), // Log content length
    ];

    // Log the combined, structured data
    Log::info('http.transaction', [
        'request' => $requestData,
        'response' => $responseData,
    ]);
});

Deeper Dive into Logging Payload and Status

As you can see, by utilizing $response->getStatusCode() and $response->getContent(), we move beyond just logging metadata to capturing the actual transactional result.

  1. Status Code is King: Always prioritize logging the status code. Whether it's a 200 or a 503, this number tells you immediately whether the operation succeeded from the server's perspective.
  2. Request Context: Including the HTTP method (GET, POST, etc.) and the full URI gives context about what action was attempted.
  3. Response Body Size: Logging the length of the response body (strlen($response->getContent())) is invaluable for monitoring bandwidth usage and detecting unusually large responses, which can signal memory issues or data leaks.

This practice aligns with the principles of robust application design, much like how well-structured data management is fundamental to building scalable systems, similar to the architecture emphasized by teams working on platforms like https://laravelcompany.com.

Best Practices for Advanced Logging

For more complex logging scenarios, consider moving beyond simple Log::info() calls within middleware. For heavy-duty tracking or detailed debugging, consider implementing a dedicated logging service or using Laravel's built-in event system to dispatch response events. This keeps your middleware clean and separates the concerns of request handling from data persistence.

When monitoring performance, logging the time taken for the entire cycle (request start to response end) is also essential. You can achieve this by recording timestamps before and after the after hook executes.

Conclusion

By understanding the structure of Laravel's HTTP request and response objects, developers can move past superficial logging and capture the true essence of the web transaction. By focusing on status codes, method details, and response body information, you transform simple log entries into powerful diagnostic tools. Mastering these techniques ensures that when issues arise, you have the complete historical context needed to pinpoint exactly where the failure occurred.