Làm Chủ Laravel 11 Context: Quản Lý State Và Trace ID Xuyên Suốt Request

VMas-Dev-AnHuynh

Laravel 11 Context: Quản Lý State và Trace ID Xuyên Suốt Request

1. Vấn Đề Truyền Dữ Liệu Ngữ Cảnh Trước Laravel 11

Hãy tưởng tượng bạn cần đính kèm một Correlation ID (hay Trace ID) vào tất cả các log trong toàn bộ hệ thống. Mục tiêu là khi có lỗi xảy ra, bạn có thể truy vết toàn bộ hành trình của một request từ lúc vào hệ thống cho đến khi xử lý xong, bao gồm cả các tác vụ bất đồng bộ trong Queue.

Những cách làm cũ thường gặp:

  • Dùng $request->attributes: Chỉ hoạt động trong phạm vi HTTP request hiện tại. Khi dispatch job, dữ liệu này biến mất.
  • Truyền tham số thủ công vào constructor của Job: Phải sửa lại tất cả các job hiện có, code trở nên cồng kềnh. Mỗi job lại phải khai báo thêm thuộc tính và tham số.
  • Dùng Session: Không phù hợp cho API stateless, lại phụ thuộc vào session driver.
  • Dùng Config::set(): Là giải pháp “tạm bợ” và không an toàn trong môi trường đa request (như Octane), vì config là global và không được reset giữa các request.
  • Tự xây dựng Singleton pattern: Phức tạp, dễ gặp vấn đề về memory leak và không được hỗ trợ chính thức từ framework.

👉 Kết quả: Code không nhất quán, trace ID bị “đứt gánh” giữa request và queue, debug trở nên khó khăn. Chính vì lý do này, Laravel 11 đã chính thức giới thiệu tính năng Context — một giải pháp thống nhất, tinh gọn và cực kỳ mạnh mẽ.

💡 Đọc thêm: Bên cạnh Context, Laravel 11 còn mang đến nhiều thay đổi đột phá khác như cấu trúc thư mục tối giản, loại bỏ các file mặc định không cần thiết. Nếu bạn chưa đọc, hãy tham khảo bài viết Laravel 11 có gì mới? Cấu trúc thư mục tối giản để có cái nhìn tổng quan trước khi đi sâu vào tính năng này.


2. Laravel Context Là Gì Và Hoạt Động Như Thế Nào?

Context trong Laravel 11 là một cơ chế lưu trữ dữ liệu “nhận biết request” (request-aware storage). Nó cho phép bạn capture, retrieve và share thông tin xuyên suốt HTTP requests, Queue Jobs, và Artisan commands một cách liền mạch.

Theo tài liệu chính thức từ Laravel: “Laravel’s ‘context’ capabilities enable you to capture, retrieve, and share information throughout requests, jobs, and commands executing within your application. This captured information is also included in logs written by your application, giving you deeper insight into the surrounding code execution history that occurred before a log entry was written.”

Bản chất kỹ thuật: Context được triển khai như một Repository Pattern với cơ chế dehydration/hydration tự động. Khi bạn dispatch một job, toàn bộ dữ liệu trong Context sẽ được “đóng gói” (dehydrate) vào payload của job. Khi job được xử lý, dữ liệu sẽ được “khôi phục” (hydrate) lại vào Context một cách tự động.

flowchart LR
    A[HTTP Request] --> B[Middleware gán Context]
    B --> C[Controller xử lý]
    C --> D[Dispatch Queue Job]
    D --> E[Context được dehydrate vào job payload]
    E --> F[Queue Worker nhận job]
    F --> G[Context được hydrate trở lại]
    G --> H[Job handle chạy với Context đầy đủ]

2.1 Các phương thức cơ bản: Context::add, Context::get, Context::addHidden

Phương thức Mô tả Ví dụ
Context::add($key, $value) Thêm dữ liệu vào context, xuất hiện trong log Context::add('trace_id', $uuid)
Context::get($key) Lấy dữ liệu từ context $traceId = Context::get('trace_id')
Context::addHidden($key, $value) Thêm dữ liệu ẩn, không xuất hiện trong log Context::addHidden('api_key', $key)
Context::getHidden($key) Lấy dữ liệu ẩn $apiKey = Context::getHidden('api_key')
Context::forget($key) Xóa dữ liệu khỏi context Context::forget('temporary_data')
Context::addIf($key, $value) Thêm dữ liệu chỉ khi key chưa tồn tại Context::addIf('trace_id', $uuid)

Điểm đặc biệt là khi bạn sử dụng Log::info(), dữ liệu trong Context sẽ tự động được đính kèm vào log entry như một phần của metadata, hoàn toàn không cần can thiệp thêm.

<?php

use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Log;

Context::add('trace_id', 'abc-123-xyz');
Log::info('User logged in', ['user_id' => 1]);

// Kết quả log:
// User logged in. {"user_id":1} {"trace_id":"abc-123-xyz"}

2.2 Cơ chế tự động Hydrate sang Queue Job

Đây có lẽ là tính năng killer của Context. Khi bạn dispatch một job, Context tự động được capture và truyền sang job mà không cần bạn làm gì thêm:

<?php

// Trong Controller
use Illuminate\Support\Facades\Context;

Context::add('trace_id', 'abc-123-xyz');
ProcessPodcast::dispatch($podcast);

// Trong Job's handle method
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Log;

public function handle(): void
{
    // Context đã được hydrate tự động
    $traceId = Context::get('trace_id'); // 'abc-123-xyz'
    Log::info('Processing podcast', ['podcast_id' => $this->podcast->id]);
}

// Log trong job sẽ tự động có trace_id:
// Processing podcast. {"podcast_id":95} {"trace_id":"abc-123-xyz"}

Cơ chế này được Laravel xử lý hoàn toàn tự động thông qua hệ thống Queue. Dữ liệu Context được serialized vào job payload dưới key illuminate:log:context và được hydrate lại khi job processing.

⚠️ Lưu ý quan trọng: Context chỉ hỗ trợ dữ liệu có thể serialize (JSON). Không lưu resource (như PDO instance), closure, hoặc object không hỗ trợ __serialize() vào Context. Nếu cố tình làm vậy, job sẽ bị lỗi khi dispatch.

⚠️ Lưu ý: Tính năng này được thiết kế để hoạt động với tất cả queue drivers. Tuy nhiên, cần kiểm chứng thực tế với các driver như RedisSQS để đảm bảo dữ liệu Context được serialize/deserialize chính xác trong môi trường production, đặc biệt với dữ liệu phức tạp.

Sơ đồ luồng dữ liệu Laravel Context từ HTTP Request qua Middleware, Controller, Queue Job đến Log


3. Thực Chiến: Xây Dựng Distributed Tracing System Trong Laravel 11

Phần này sẽ hướng dẫn bạn xây dựng một hệ thống distributed tracing hoàn chỉnh, từ việc tạo middleware cho đến kiểm chứng log và queue.

3.1 Viết TraceIdMiddleware bắt X-Request-ID header

Đầu tiên, tạo middleware để bắt hoặc sinh Trace ID:

<?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;

class TraceIdMiddleware
{
    /**
     * Handle an incoming request.
     */
    public function handle(Request $request, Closure $next): Response
    {
        // Ưu tiên lấy trace_id từ header, nếu không có thì tự sinh
        $traceId = $request->header('X-Request-ID') ?: Str::uuid()->toString();

        // Gán vào Context - tự động xuất hiện trong mọi log
        Context::add('trace_id', $traceId);

        // Gán thêm metadata hữu ích
        Context::add('request_url', $request->fullUrl());
        Context::add('request_method', $request->method());
        Context::add('client_ip', $request->ip());

        // Thêm trace_id vào response header để client nhận biết
        $response = $next($request);
        $response->headers->set('X-Trace-ID', $traceId);

        return $response;
    }
}

Giải thích code:

  • Dòng 18: Sử dụng Str::uuid() để sinh UUID phiên bản 4 (ngẫu nhiên) làm trace ID.
  • Dòng 21-24: Gán các metadata vào Context — tất cả sẽ tự động xuất hiện trong log.
  • Dòng 28: Thêm trace ID vào response header, giúp client và các service downstream có thể sử dụng cho tracing.

Đăng ký middleware trong bootstrap/app.php:

<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        // ...
    )
    ->withMiddleware(function (Middleware $middleware) {
        // Đảm bảo middleware chạy ĐẦU TIÊN
        $middleware->prepend(\App\Http\Middleware\TraceIdMiddleware::class);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        // ...
    })->create();

💡 Lưu ý: Sử dụng prepend() thay vì append() để đảm bảo middleware này chạy đầu tiên, giúp mọi log trong toàn bộ pipeline đều có trace ID.

3.2 Gán trace_id vào Laravel Context

Sau khi middleware đã hoạt động, bạn có thể truy cập trace_id từ bất kỳ đâu trong ứng dụng:

<?php

namespace App\Http\Controllers;

use App\Jobs\ProcessPodcast;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Log;

class PodcastController extends Controller
{
    public function store(Request $request)
    {
        $traceId = Context::get('trace_id');

        // Log tự động có trace_id
        Log::info('Creating podcast', ['podcast' => $request->title]);

        // Dispatch job - Context tự động truyền sang
        ProcessPodcast::dispatch($request->all());

        return response()->json(['message' => 'Podcast created']);
    }
}

3.3 Kiểm chứng Log tự động đính kèm metadata

Màn hình log hiển thị trace_id xuyên suốt từ HTTP request qua queue job trong Laravel 11

Tạo một Queue Job để kiểm chứng Context được hydrate tự động:

<?php

namespace App\Jobs;

use App\Models\Podcast;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Log;

class ProcessPodcast implements ShouldQueue
{
    use Queueable;

    public function __construct(
        protected array $data
    ) {}

    public function handle(): void
    {
        // Context đã được hydrate tự động từ request gốc
        $traceId = Context::get('trace_id');
        $requestUrl = Context::get('request_url');

        Log::info('Processing podcast in queue', [
            'trace_id' => $traceId,
            'podcast_title' => $this->data['title'] ?? 'unknown'
        ]);

        // Context cũng có thể được ghi thêm trong job
        Context::add('job_processed_at', now()->toIso8601String());

        // Xử lý business logic...
        sleep(2); // Giả lập xử lý nặng

        Log::info('Podcast processing completed');
    }
}

Kiểm tra log output:

Khi chạy queue worker, log sẽ hiển thị:

[2025-01-15 10:30:45] local.INFO: Creating podcast {"podcast":"Laravel 11 Context Episode"} {"trace_id":"e04e1a11-e75c-4db3-b5b5-cfef4ef56697","request_url":"https://myapp.com/podcasts","request_method":"POST","client_ip":"192.168.1.1"}

[2025-01-15 10:30:48] local.INFO: Processing podcast in queue {"trace_id":"e04e1a11-e75c-4db3-b5b5-cfef4ef56697","podcast_title":"Laravel 11 Context Episode"} {"trace_id":"e04e1a11-e75c-4db3-b5b5-cfef4ef56697","request_url":"https://myapp.com/podcasts","request_method":"POST","client_ip":"192.168.1.1"}

[2025-01-15 10:30:50] local.INFO: Podcast processing completed {} {"trace_id":"e04e1a11-e75c-4db3-b5b5-cfef4ef56697","request_url":"https://myapp.com/podcasts","request_method":"POST","client_ip":"192.168.1.1","job_processed_at":"2025-01-15T10:30:50+00:00"}

🎯 Kết luận: Trace ID xuyên suốt từ request ban đầu qua queue job mà không cần bất kỳ tham số thủ công nào!

💡 Gợi ý mở rộng: Khái niệm Correlation ID/Trace ID là nền tảng của Centralized Logging và Observability. Nếu bạn quan tâm đến logging chuyên nghiệp trên các nền tảng khác, hãy đọc bài viết Logging chuyên nghiệp với Winston trong Node.js để thấy sự tương đồng trong tư duy thiết kế.


4. Context vs Session vs Config: Khi Nào Nên Dùng Gì?

Tính năng Context Session Config Request Attributes
Phạm vi Request + Queue Job + Command Session (user-specific) Global (toàn ứng dụng) Chỉ trong request hiện tại
Tự động truyền sang Queue ✅ Có ❌ Không ❌ Không ❌ Không
Tự động đính kèm log ✅ Có ❌ Không ❌ Không ❌ Không
Dùng cho API ✅ Tốt ❌ Không nên (stateless) ⚠️ Rủi ro ✅ Tốt
Reset giữa các request ✅ Tự động ❌ Phụ thuộc driver ❌ Không reset ✅ Tự động
An toàn với Octane ⚠️ Cần lưu ý ⚠️ Tùy driver ❌ Không an toàn ✅ Có

Bảng so sánh Laravel Context, Session, Config và Request Attributes về phạm vi và khả năng tự động tích hợp

Khi nào dùng gì:

  • Context: Dữ liệu cần xuyên suốt request → queue → log (trace ID, user context, tenant ID).
  • Session: Dữ liệu user-specific cần lưu giữa các request (giỏ hàng, trạng thái đăng nhập).
  • Config: Dữ liệu cấu hình tĩnh, không đổi trong suốt vòng đời ứng dụng.
  • Request Attributes: Dữ liệu tạm thời chỉ dùng trong request hiện tại, không cần log.

5. Lỗi Thường Gặp Khi Sử Dụng Laravel Context

🔴 Lỗi 1: Nhầm lẫn giữa Context::add()Context::addHidden()

Vấn đề: Sử dụng Context::add() cho dữ liệu nhạy cảm như password hash, API token, session ID → dữ liệu này sẽ lộ trong log files.

Hậu quả: Rò rỉ thông tin bảo mật nghiêm trọng trong log, đặc biệt nguy hiểm nếu log được lưu trữ lâu dài hoặc chia sẻ với bên thứ ba.

Cách fix:

<?php

use Illuminate\Support\Facades\Context;

// ❌ SAI - Dữ liệu nhạy cảm xuất hiện trong log
Context::add('api_secret', $secretKey);
Context::add('user_password_hash', $hash);

// ✅ ĐÚNG - Dữ liệu nhạy cảm chỉ truy cập được trong code
Context::addHidden('api_secret', $secretKey);
Context::addHidden('user_password_hash', $hash);

// Lấy dữ liệu ẩn
$secret = Context::getHidden('api_secret');

🔴 Lỗi 2: Không khởi tạo Trace ID ở đầu pipeline

Vấn đề: Đặt middleware gán Context quá muộn trong pipeline → một số log ở các middleware trước đó không có trace ID.

Cách fix: Đăng ký middleware ở vị trí đầu tiên hoặc sử dụng prepend() thay vì append():

<?php

// Trong bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    // Đảm bảo middleware chạy ĐẦU TIÊN
    $middleware->prepend(\App\Http\Middleware\TraceIdMiddleware::class);
})

🔴 Lỗi 3: Không xử lý Context trong Artisan Commands và Scheduled Tasks

Vấn đề: Context chỉ được khởi tạo tự động cho HTTP requests. Trong Artisan commands hoặc scheduled tasks, Context rỗng.

Cách fix: Tự động sinh trace ID ngay trong command:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class ProcessReportCommand extends Command
{
    protected $signature = 'report:process';
    protected $description = 'Process monthly report';

    public function handle()
    {
        // Khởi tạo Context cho command
        Context::add('trace_id', Str::uuid()->toString());
        Context::add('command', $this->signature);
        Context::add('executed_at', now()->toIso8601String());

        Log::info('Starting report processing');
        // ... xử lý
        Log::info('Report processing completed');
    }
}

🔴 Lỗi 4: Context bị mất trong môi trường Octane

Vấn đề: Khi sử dụng Laravel Octane (Swoole/RoadRunner), Context có thể bị mất giữa các request do Octane tối ưu hóa và tái sử dụng application container.

Cách fix:

  • Đảm bảo sử dụng Laravel 11.41.3+ với Octane 2.8.1+ đã được fix.
  • Kiểm tra kỹ trong môi trường staging trước khi deploy production.
  • Xem xét sử dụng Context::scope() trong Laravel 12+ để hỗ trợ async context isolation.

🔴 Lỗi 5: Lưu dữ liệu không serialize được vào Context

Vấn đề: Context được serialize vào job payload. Nếu bạn lưu resource (như PDO instance, file handle) hoặc closure vào Context, job sẽ bị lỗi khi dispatch.

Cách fix: Chỉ lưu dữ liệu có thể serialize (scalar, array, object implement __serialize()).

<?php

use Illuminate\Support\Facades\Context;

// ❌ SAI - Resource không serialize được
Context::add('db_connection', DB::connection());

// ✅ ĐÚNG - Chỉ lưu dữ liệu scalar hoặc array
Context::add('connection_name', config('database.default'));
Context::add('user', ['id' => $userId, 'email' => $email]);

🔴 Lỗi 6: Quên restart Queue Worker sau khi thay đổi Context

Vấn đề: Queue worker cache job payload. Nếu bạn thay đổi cách sử dụng Context trong code nhưng không restart worker, worker vẫn dùng payload cũ.

Cách fix: Luôn restart queue worker sau khi deploy code mới:

php artisan queue:restart

6. Best Practices Khi Sử Dụng Laravel Context

✅ Best Practice 1: Luôn khởi tạo Trace ID tại middleware đầu tiên

Đảm bảo mọi request vào hệ thống đều có trace ID ngay từ đầu. Điều này giúp toàn bộ log trong hệ thống đều có thể truy vết được.

✅ Best Practice 2: Sử dụng Context::forget() cho dữ liệu tạm thời

Trong các tác vụ chạy ngầm kéo dài (long-running jobs), nếu bạn có dữ liệu không cần thiết sau một thời điểm, hãy xóa nó để tránh memory leak:

<?php

public function handle(): void
{
    $largeData = Context::get('large_dataset');
    // Xử lý với largeData...

    // Giải phóng bộ nhớ khi không còn cần
    Context::forget('large_dataset');
}

✅ Best Practice 3: Đặt tên key có cấu trúc rõ ràng

Sử dụng namespace hoặc prefix để tránh xung đột key:

<?php

use Illuminate\Support\Facades\Context;

// ❌ Không rõ ràng
Context::add('id', $value);

// ✅ Rõ ràng, có namespace
Context::add('trace.id', $value);
Context::add('user.id', Auth::id());
Context::add('tenant.id', $tenantId);

✅ Best Practice 4: Log Context trong exception handling

Cập nhật exception handler để tự động gắn Context vào exception log:

<?php

// Trong bootstrap/app.php
use Illuminate\Foundation\Configuration\Exceptions;

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->context(function () {
        return [
            'trace_id' => Context::get('trace_id'),
            'user_id' => Context::get('user.id'),
            'request_url' => Context::get('request_url'),
        ];
    });
})

✅ Best Practice 5: Kiểm tra sự tồn tại của key trước khi lấy

Sử dụng Context::has() để kiểm tra trước khi truy xuất, hoặc dùng Context::addIf() để chỉ thêm khi key chưa tồn tại:

<?php

use Illuminate\Support\Facades\Context;
use Illuminate\Support\Str;

// Cách 1: Kiểm tra trước
if (Context::has('trace_id')) {
    $traceId = Context::get('trace_id');
} else {
    $traceId = Str::uuid()->toString();
    Context::add('trace_id', $traceId);
}

// Cách 2: Dùng addIf (chỉ thêm nếu chưa tồn tại)
Context::addIf('trace_id', Str::uuid()->toString());
$traceId = Context::get('trace_id');

✅ Best Practice 6: Sử dụng Fluent Helper cho dữ liệu phức tạp

Laravel 11.2+ hỗ trợ Fluent Helper để làm việc với mảng đa chiều trong Context:

<?php

use Illuminate\Support\Facades\Context;

// Thêm dữ liệu phức tạp
Context::add('user', [
    'id' => 1,
    'profile' => [
        'name' => 'John Doe',
        'email' => 'john@example.com'
    ]
]);

// Truy xuất với dot notation
$email = Context::get('user.profile.email'); // 'john@example.com'

// Hoặc dùng hàm context() helper
$user = context('user');
$email = context('user.profile.email');

7. FAQ

❓ Laravel Context có chạy mượt trên Laravel Octane không?

Context được thiết kế để tương thích với Octane, nhưng đã từng có issue về việc Context bị mất trong một số phiên bản cũ. Nếu bạn sử dụng Laravel 11.41.3+ với Octane 2.8.1+, vấn đề này đã được khắc phục. Tuy nhiên, vẫn nên kiểm tra kỹ trong môi trường staging và theo dõi các log để đảm bảo Context hoạt động ổn định.

❓ Context khác gì với việc gán thuộc tính vào $request->attributes?

Context Request Attributes
Phạm vi Request + Queue Job + Command Chỉ request hiện tại
Tự động truyền sang Queue ✅ Có ❌ Không
Tự động vào log ✅ Có ❌ Không
Sử dụng trong Service/Repository ✅ Có (dùng Facade) ❌ Không (cần truyền request)
Persistent trong pipeline ✅ Có ✅ Có

❓ Dữ liệu trong Context có bị lộ khi serialize job không?

Context được serialize và lưu trong job payload. Nếu bạn lưu trữ dữ liệu nhạy cảm, hãy luôn sử dụng Context::addHidden() để đảm bảo dữ liệu không xuất hiện trong log. Tuy nhiên, dữ liệu vẫn tồn tại trong payload của queue — hãy cân nhắc sử dụng queue driver có mã hóa nếu cần bảo mật tuyệt đối.

❓ Làm thế nào để test Context trong Unit Test?

<?php

use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Queue;

test('context preserves trace id', function () {
    Context::add('trace_id', 'test-trace-123');

    expect(Context::get('trace_id'))->toBe('test-trace-123');

    // Test với Queue fake
    Queue::fake();
    ProcessPodcast::dispatch();

    // Kiểm tra job được dispatch với context đúng
    Queue::assertPushed(ProcessPodcast::class);
});

❓ Context có hỗ trợ multi-dimensional array không?

Có, Laravel 11.2+ hỗ trợ Fluent Helper để làm việc với mảng đa chiều trong Context.

<?php

use Illuminate\Support\Facades\Context;

Context::add('user', [
    'id' => 1,
    'profile' => [
        'name' => 'John Doe',
        'email' => 'john@example.com'
    ]
]);

$email = Context::get('user.profile.email'); // 'john@example.com'

❓ Context có được hydrate khi retry job không?

Có. Khi job được retry (ví dụ qua queue:retry), Context sẽ được hydrate lại từ payload đã lưu. Tuy nhiên, cần lưu ý rằng trong command queue:retry, Context chưa được hydrate ngay tại thời điểm sự kiện JobRetryRequested được fired — context chỉ được hydrate khi job thực sự bắt đầu processing.

❓ Làm thế nào để sử dụng Context với Laravel Horizon?

Khi sử dụng Laravel Horizon, Context hoạt động bình thường vì Horizon sử dụng cùng cơ chế queue của Laravel. Tuy nhiên, cần lưu ý:

  1. Restart Horizon sau khi deploy code mới: php artisan horizon:terminate
  2. Không cache Context giữa các lần chạy job — mỗi job đều có context riêng được hydrate từ payload.
  3. Monitor context size — Horizon có thể hiển thị kích thước payload, đảm bảo context không vượt quá giới hạn (mặc định 65KB).

❓ Làm thế nào để tắt Context metadata trong log?

Nếu bạn muốn tạm thời tắt việc append context metadata vào log (ví dụ trong môi trường development với log quá nhiều), bạn có thể cấu hình trong config/logging.php:

<?php

// Trong config/logging.php
'context' => env('LOG_CONTEXT', true),

Hoặc trong code:

<?php

use Illuminate\Support\Facades\Log;

// Tắt context cho một log entry cụ thể
Log::withoutContext()->info('This log has no context metadata');

8. Kết Luận

Laravel 11 Context là một tính năng game-changing cho các ứng dụng cần distributed tracing, centralized logging, và xử lý bất đồng bộ phức tạp. Với cơ chế tự động hydrate/dehydrate qua Queue, bạn có thể:

  1. Loại bỏ việc truyền tham số thủ công vào mọi queue job.
  2. Tự động đính kèm metadata (trace ID, user context, tenant) vào mọi log entry.
  3. Xây dựng hệ thống distributed tracing chỉ với vài dòng code trong middleware.
  4. Bảo mật dữ liệu nhạy cảm với Context::addHidden().

Context không chỉ là một công cụ logging — nó là nền tảng cho Observability trong các hệ thống Laravel hiện đại. Kết hợp với các công cụ như Laravel Telescope, Flare, hay Nightwatch, bạn có thể có cái nhìn toàn diện về luồng xử lý của ứng dụng.

Chia sẻ bài viết này
By VMas-Dev-AnHuynh Software Engineer
Follow:
SOFTWARE ENGINEER / FULL-STACK DEVELOPER