Hướng dẫn dùng sys log trong PHP

Trong ngôn ngữ PHP, Exception là một class được xây dựng sẵn để quản lý lỗi kiểu hướng đối tượng, nó cho phép bạn đưa ra các cảnh báo khi một vấn đề xấu xảy ra hoặc người dùng hoạt động theo những cách thức không mong muốn [ví dụ như phép chia cho 0 chẳng hạn]. Không có exception, ứng dụng của bạn có thể dừng lại khi gặp lỗi và cũng rất khó để kiểm tra lỗi.

1. Exception là gì?

Exceptions signal something outside the expected bounds of behavior of the code in question. Exception [Ngoại lệ] báo hiệu một điều gì đó nghi ngờ về hành vi của chương trình vượt qua phạm vi mong đợi. Martin Fowler

Đây là một định nghĩa hoàn chỉnh nhất cho Exception là gì được đưa ra bởi Martin Fowler, cũng chính là tác giả của một loạt bài viết rất hay về nguyên lý Inversion of Control. Trong thực tế một exception là một sự kiện, nó xảy ra khi chương trình thực thi và làm gián đoạn luồng thực hiện. Khi bạn tạo ra một exception, hệ thống sẽ bắt exception này và tìm cách xử lý phù hợp cùng với các message tương ứng.

try { 
    // Các đoạn mã có thể phát sinh lỗi
} catch [Exception $e] { 
    // Nếu một exception xảy ra, đoạn mã trong catch sẽ được thực hiện
}

Gợi ý: Bạn nên tham khảo bài viết Quản lý lỗi với Exception trong PHP để có kiến thức cơ bản về Exception.

1.1 Exception nên sử dụng trong những trường hợp nào?

Sử dụng exception khi hệ thống phải đối mặt với những tình huống đặc biệt ngăn cản hệ thống giành quyền điều khiển hay nói một cách khác exception sử dụng khi hệ thống không thể xác định điều gì đã xảy ra. Nếu một lỗi là một hành vi mong đợi thì chúng ta không nên sử dụng exception, ví dụ trường hợp chúng ta cần kiểm tra dữ liệu nhập vào. Bắt exception với câu lệch catch là rất quan trọng vì nó nếu không thực hiện nó hệ thống sẽ trả về lỗi và ứng dụng dừng lại. Câu lệnh catch sẽ giúp chương trình quản lý được lỗi và vẫn hoạt động khi lỗi xảy ra.

Chú ý: Exception không nên sử dụng trong thao tác với các toán tử logic.

2. Laravel Exception là gì?

Trong framework Laravel Exception vẫn được sử dụng như class Exception thông thường của ngôn ngữ PHP và thêm vào đó, Laravel cho phép quản lý tập trung exception với class app\Exceptions\Handler. Với class này Laravel cho phép chúng ta có thể quản lý lỗi thông qua các dịch vụ bên thứ 3 và cũng cho phép điều hướng một cách phù hợp đến các trang báo lỗi.

Đi kèm với các các exception, Laravel còn sử dụng thư viện Monolog để giúp ghi lại nhật ký lỗi với rất nhiều các thiết lập cấu hình tùy chọn như sử dụng file riêng lẻ hay file log theo ngày hoặc thậm chí ghi nhận vào system log. Chúng ta sẽ cùng tìm hiểu cách thiết lập cấu hình cho quản lý lỗi và ghi log trong Laravel, tiếp đó là phần ví dụ về xây dựng một class Exception riêng.

2.1 Cấu hình

2.1.1 Bật tắt chế độ ghi log lỗi

Tùy chọn debug trong config/app.php xác định thông tin lỗi có được hiển thị cho người dùng hay không. Mặc định, tùy chọn này lấy giá trị biến môi trường APP_DEBUG trong file .env. Với phát triển cục bộ, bạn nên thiết lập biến môi trường APP_DEBUG là true, khi đưa mã nguồn lên máy chủ nên để giá trị này là false.

2.1.2 Thiết lập lưu trữ log

Laravel hỗ trợ ghi thông tin log vào các file đơn lẻ, file log theo ngày hoặc syslog và errorlog. Để cấu hình cơ chế Laravel sử dụng để lưu trữ log, bạn thay đổi tùy chọn log trong config/app.php. Ví dụ, nếu bạn muốn sử dụng cách ghi log ra file theo ngày thay cho một file riêng lẻ thì bạn thiết lập giá trị log trong app.php thành daily:

'log' => 'daily'

Khi sử dụng chế độ daily, Laravel chỉ giữ lại 5 file log của 5 ngày gần nhất, nếu bạn muốn điều chỉnh số lượng file log được lưu trữ lại, bạn có thể thay đổi giá trị log_max_files trong app.php:

'log_max_files' => 30

2.1.3 Thiết lập cấp độ lỗi cần ghi log

Khi sử dụng Monolog, các message log có rất nhiều cấp độ với độ nghiêm trọng khác nhau. Mặc định, Laravel ghi tất cả các cấp độ log, tuy nhiên, trong môi trường ứng dụng chạy thực tế, bạn nên thiết lập chỉ ghi log với các cấp độ nghiêm trọng cần thiết thông qua giá trị log_level trong file app.php.

Khi tùy chọn này được cấu hình, Laravel sẽ ghi log tất cả các cấp độ nghiêm trọng hơn hoặc bằng với cấp độ được cấu hình. Ví dụ, mặc định giá trị log_level có giá trị là error do đó Laravel sẽ ghi log các cấp độ là error, critical, alert và emergency:

'log_level' => env['APP_LOG_LEVEL', 'error'],

2.1.4 Thiết lập cấu hình Monolog riêng

Nếu bạn muốn hoàn toàn kiểm soát cách Monolog được cấu hình trong ứng dụng của bạn, bạn có thể sử dụng phương thức configureMonologUsing và thực hiện gọi đến phương thức này trong file bootstrap/app.php trước khi trả về biến $app:

$app->configureMonologUsing[function [$monolog] {
    $monolog->pushHandler[...];
}];

return $app;

2.2 Quản lý Exception

2.2.1 Phương thức report

Tất cả các exception được quản lý bởi class app\Exceptions\Handler, class này chứa hai phương thức là report và render. Phương thức report được sử dụng để log exception và gửi chúng đến các dịch vụ ngoài như Bugsnag hoặc Sentry. Mặc định, phương thức report chỉ đơn giản truyền exception đến class nơi exception xảy ra. Ví dụ, nếu bạn cần báo cáo các dạng khác nhau của exception theo cách khác, bạn có thể sử dụng toán tử so sánh của PHP là instanceof:

/**
 * Report or log an exception.
 *
 * 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];
}

Đôi khi chúng ta muốn bỏ qua một số exception, thuộc tính $dontReport của class app\Exceptions\Handler chứa một mảng các dạng exeception không muốn log. Ví dụ, các exception cho kết quả lỗi 404 không muốn ghi xuống file log, bạn có thể đưa các exception này vào thuộc tính $dontReport:

/**
 * A list of the exception types that should not be reported.
 *
 * @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,
];

2.2.2 Phương thức render

Phương thức này được sử dụng cho mục đích điều hướng, với mỗi exception cụ thể bạn muốn điều hướng người dùng đến một trang HTTP. Mặc định, exception được truyền đến base class nơi sinh ra response, tuy nhiên bạn hoàn toàn có thể kiểm tra dạng exception và trả về một response tùy ý:

/**
 * Render an exception into an HTTP response.
 *
 * @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];
}

2.3 HTTP Exception

Một số các exception tương ứng với một mã lỗi HTTP, ví dụ như lỗi "Trang không tìm thấy" tương ứng với mã lỗi 404 hay lỗi "Không được cấp quyền truy nhập" tương ứng với 401... Trong ứng dụng, phương thức abort giúp bạn tạo ra các exception này:

abort[404];

Helper abort sẽ ngay lập tức bung ra một exception, phương thức này cũng nhận một chuỗi text để hiển thị cho mã lỗi tương ứng.

abort[403, 'Unauthorized action.'];

2.3.1 Tạo ra view riêng cho mã lỗi HTTP

Laravel cho phép tạo ra các trang thông báo lỗi riêng tương ứng với các mã lỗi. Ví dụ, nếu bạn muốn cá nhân hóa trang báo lỗi 404 "Không tìm thấy trang web" bạn có thể tạo view resources/views/errors/404.blade.php. View này sẽ được sử dụng khi lỗi 404 phát sinh trong ứng dụng. Các view trong thư mục này cần được đặt tên tương ứng với mã lỗi HTTP. Một instance của HttpException sẽ được truyền đến view trong biến $exception khi hàm abort được gọi đến.

{{ $exception->getMessage[] }}

2.4 Ghi log

Laravel có một abstraction layer bao phủ thư viện Monolog, mặc định một file log được lưu trong thư mục storage/logs. Bạn hoàn toàn có thể ghi log vào đây sử dụng facade Log:

Chủ Đề