😎 Có bao giờ bạn debug mà không biết cái request đó từ đâu tới, của user nào, hay chạy trên server nào chưa?
Như anh em đã biết, Logging là một phần không thể thiếu để theo dõi, gỡ lỗi và phân tích hành vi của ứng dụng. Mặc dù .NET cung cấp hệ thống logging tích hợp (`Microsoft.Extensions.Logging`), Serilog là một thư viện logging của bên thứ ba cực kỳ phổ biến và mạnh mẽ, nổi bật với khả năng structured logging (logging có cấu trúc) và hệ sinh thái phong phú các sinks (đích đến log) và enrichers (bộ làm giàu log).
Trong bài viết này, chúng ta sẽ đi sâu vào các tính năng được Serilog hỗ trợ nhé.
Tại sao lại cần Structured Logging?
Logging truyền thống thường ghi lại các thông điệp dưới dạng chuỗi văn bản tự do. Điều này gây khó khăn cho việc phân tích và truy vấn log một cách tự động.
Structured Logging ghi lại log dưới dạng các sự kiện (events) với các thuộc tính (properties) có tên và giá trị rõ ràng, thường là định dạng JSON.
Lợi ích của Serilog và Structured Logging:
Dễ dàng Truy vấn và Phân tích: Log có cấu trúc dễ dàng được gửi đến các hệ thống quản lý log (như Seq, Elasticsearch/Kibana, Splunk, Datadog...) và được truy vấn, lọc, tạo dashboard một cách hiệu quả.
Thông tin Ngữ cảnh Phong phú: Dễ dàng đính kèm thêm thông tin ngữ cảnh vào log (ví dụ: UserId, RequestId, ThreadId...) thông qua Enrichers.
Hệ sinh thái Sinks Đa dạng: Serilog hỗ trợ ghi log ra rất nhiều đích đến khác nhau (Console, File, Seq, Elasticsearch, Application Insights, SQL Server, MongoDB, Graylog, Slack...).
Cấu hình Linh hoạt: Cấu hình Serilog thông qua code hoặc file cấu hình (appsettings.json, logger.json) một cách dễ dàng.
Hiệu năng Tốt: Serilog được thiết kế với hiệu năng cao.
Các bước Sử dụng Serilog trong ASP.NET Core
1. Cài đặt NuGet Packages
Serilog.AspNetCore: Gói chính để tích hợp với ASP.NET Core.
Các gói Sinks cần thiết (ví dụ: Serilog.Sinks.Console, Serilog.Sinks.File, Serilog.Sinks.Seq, Serilog.Sinks.Elasticsearch...).
Các gói Enrichers cần thiết (ví dụ: Serilog.Enrichers.Environment, Serilog.Enrichers.Thread, Serilog.Enrichers.CorrelationId...).
Hoặc tự viết Enrickers.
2. Cấu hình Serilog trong Program.cs - quan trọng nhất
Cách tốt nhất là cấu hình Serilog ngay từ đầu trước khi WebApplication.CreateBuilder được gọi, để có thể log cả quá trình khởi tạo ứng dụng.
3. Cấu hình trong appsettings.json
4. Inject ILogger<T> và sử dụng trong nghiệp vụ
Serilog tích hợp hoàn toàn với Microsoft.Extensions.Logging. Bạn chỉ cần injectILogger<T>như bình thường.
Dưới đây là chi tiết code của ProductService sử dụng ILogger, cụ thể ở Get Product By Id nhằm mục đích trace lỗi dễ dàng hơn nhé
Enrichers:
Enrichers thêm thông tin ngữ cảnh vào tất cả các log event. Một số enricher phổ biến:
FromLogContext(): Cho phép thêm property tạm thời bằng LogContext.PushProperty.
WithMachineName(): Tên máy.
WithThreadId(): ID luồng.
WithEnvironmentUserName(): Tên user môi trường.
WithCorrelationId() (từ Serilog.Enrichers.CorrelationId): ID duy nhất cho mỗi request, giúp theo dõi luồng xử lý.
WithHttpRequestClientHostIP(), WithHttpRequestId(), WithHttpRequestUserAgent() (thông qua UseSerilogRequestLogging() middleware).
Sinks:
Sinks quyết định log sẽ được ghi vào đâu, Console, File,... hay log tập trung Seq, database hay Elasticsearch...
Thậm chí, chúng ta cũng có thể cấu hình nhiều sink cùng lúc (ví dụ: vừa ghi ra Console để debug, vừa ghi ra Seq để phân tích).
Kinh nghiệm & Best Practices
Structured Logging cực kỳ quan trọng: Luôn sử dụng placeholder ({PropertyName}) thay vì string interpolation ($) khi log để tận dụng structured logging.
Cấu hình qua appsettings.json, logger.json: Giúp linh hoạt thay đổi cấu hình logging (level, sinks) mà không cần build lại code.
Chọn Sinks phù hợp: Console/Debug cho local dev, File cho môi trường đơn giản, Seq/ELK/Datadog... cho hệ thống lớn cần phân tích log tập trung.
Sử dụng Enrichers hợp lý: Thêm các thông tin ngữ cảnh quan trọng (CorrelationId, UserId...) để dễ dàng theo dõi và gỡ lỗi.
Kiểm soát Log Level: Đặt MinimumLevel hợp lý (ví dụ: Information cho production, Debug cho dev) và override cho các namespace của Microsoft/System để giảm nhiễu.
Log đúng mức độ: Verbose/Debug cho thông tin chi tiết, Information cho các sự kiện quan trọng, Warning cho các tình huống bất thường nhưng không phải lỗi, Error cho lỗi cần xử lý, Fatal cho lỗi nghiêm trọng khiến ứng dụng dừng.
Tuyệt đối Không log thông tin nhạy cảm: Cẩn thận không ghi mật khẩu, API key, dữ liệu cá nhân vào log.
LogContext.PushProperty: Rất hữu ích để thêm context tạm thời trong một scope xử lý cụ thể.
UseSerilogRequestLogging(): Middleware rất tiện lợi để tự động log thông tin HTTP request.
Kết luận
Serilog là một thư viện logging mạnh mẽ và linh hoạt, đặc biệt với các khả năng structured logging. Nó giúp việc ghi log trở nên có ý nghĩa hơn, dễ dàng cho việc truy vấn, phân tích và giám sát ứng dụng .NET. Cộng với hệ sinh thái sinks và enrichers rất phong phú, cùng khả năng cấu hình linh hoạt, Serilog là lựa chọn hàng đầu cho việc xây dựng hệ thống logging hiệu quả.
/Son Do - I share real-world lessons, team building & developer growth.