Giới Thiệu Về Log4Net
Log4Net là một thư viện ghi log phổ biến trong hệ sinh thái .NET, giúp theo dõi và lưu trữ thông tin ứng dụng một cách hiệu quả.
Bước 1: Cài Đặt Thư Viện
Thêm gói log4net vào dự án qua NuGet Package Manager:
Install-Package log4net
Sau khi cài đặt xong, file DLL sẽ được tự động thêm vào project.
Bước 2: Thiết Lập Assembly Configuration
Trong tệp AssemblyInfo.cs, bổ sung attribute để cấu hình log4net:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
Bước 3: Khai Báo Section Trong Config File
Cập nhật Web.config hoặc App.config với section handler:
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
Bước 4: Tạo Tệp Cấu Hình Log
Tạo log4net.config file với thuộc tính Copy Always để đảm bảo luôn được sao chép vào output folder.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
<log4net>
<!-- Cấu hình Root Logger -->
<root>
<level value="ALL"/>
<appender-ref ref="AppenderErrors"/>
<appender-ref ref="AppenderInformation"/>
<appender-ref ref="AppenderDebug"/>
</root>
<!-- File Appender cho lỗi -->
<appender name="AppenderErrors"
type="log4net.Appender.RollingFileAppender">
<file value="Logs/Error/" />
<appendToFile value="true"/>
<maxSizeRollBackups value="50"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="false"/>
<rollingStyle value="Date"/>
<datePattern value="yyyyMMdd'.log'"/>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ERROR"/>
<levelMax value="FATAL"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
</layout>
</appender>
<!-- File Appender cho thông tin -->
<appender name="AppenderInformation"
type="log4net.Appender.RollingFileAppender">
<file value="Logs/Info/" />
<appendToFile value="true"/>
<maxSizeRollBackups value="50"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="false"/>
<rollingStyle value="Date"/>
<datePattern value="yyyyMMdd'.txt'"/>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO"/>
<levelMax value="INFO"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{ISO8601} | %-5p | %m%n"/>
</layout>
</appender>
<!-- File Appender cho Debug -->
<appender name="AppenderDebug"
type="log4net.Appender.RollingFileAppender">
<file value="Logs/Debug/" />
<appendToFile value="true"/>
<maxSizeRollBackups value="50"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="false"/>
<rollingStyle value="Date"/>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG"/>
<levelMax value="DEBUG"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[DEBUG] %date - %message%n"/>
</layout>
</appender>
</log4net>
</configuration>
Bước 5: Giải Thích Pattern Conversion
| Mã | Mô tả | Ví dụ |
|---|---|---|
| %message hay %m | Nội dung log message | "User logged in" |
| %newline hay %n | Ký tự xuống dòng | \n |
| %date hay %d | Thời gian hiện tại | 2024-01-15 10:30:00 |
| %thread hay %t | ID luồng thực thi | Thread-1 |
| %level hay %p | Độ ưu tiên của log | INFO, ERROR, DEBUG |
| %logger hay %c | Tên logger/class | MyApplication.Service |
| %line hay %L | Số dòng code | 42 |
| %file hay %F | Tên file source | UserService.cs |
Bước 6: Xây Dựng Class Helper Để Ghi Log
Tạo lớp tiện ích xử lý ghi log với phương thức đồng bộ và bất đồng bộ:
public class LoggingService
{
private static readonly log4net.ILog _errorLogger =
log4net.LogManager.GetLogger(typeof(LoggingService).Namespace + ".Error");
private static readonly log4net.ILog _infoLogger =
log4net.LogManager.GetLogger(typeof(LoggingService).Namespace + ".Info");
/// <summary>
/// Ghi log cấp độ thông tin
/// </summary>
public void RecordInformation(object message)
{
Task.Run(() => _infoLogger.Info(message));
}
/// <summary>
/// Ghi log cấp độ thông tin kèm dữ liệu phụ
/// </summary>
public void RecordInformationWithDetails(object message, object additionalData)
{
_infoLogger.Info($"{message} | Details: {additionalData}");
}
/// <summary>
/// Ghi log lỗi có ngoại lệ
/// </summary>
public void RecordException(Exception exception, string context = "")
{
if (exception != null)
{
var errorMessage = string.IsNullOrEmpty(context)
? exception.Message
: $"{context} - {exception.Message}";
Task.Run(() => _errorLogger.Error(errorMessage, exception));
}
}
/// <summary>
/// Ghi log lỗi kết hợp thông điệp tùy chỉnh
/// </summary>
public void RecordCustomError(string customMessage, Exception exception = null)
{
if (exception == null)
{
Task.Run(() => _errorLogger.Error(customMessage));
}
else
{
Task.Run(() => _errorLogger.Error(customMessage, exception));
}
}
/// <summary>
/// Khởi tạo logger cho tên cụ thể
/// </summary>
private static log4net.ILog CreateNamedLogger(string loggerName)
{
return log4net.LogManager.GetLogger(loggerName);
}
}
Bước 7: Khởi Tạo Trong Application
Trong Program.cs hoặc Global.asax.cs, thực hiện cấu hình khởi chạy:
// Trong Startup hoặc Entry point
var basePath = AppDomain.CurrentDomain.BaseDirectory;
var configFile = Path.Combine(basePath, "log4net.config");
if (File.Exists(configFile))
{
log4net.Config.XmlConfigurator.Configure(
new FileInfo(configFile));
}
Bước 8: Sử Dụng Trong Code
Ví dụ sử dụng service logging:
// Tạo instance
var logger = new LoggingService();
// Ghi log thông tin
logger.RecordInformation("Hệ thống đã khởi động thành công");
// Ghi log với thông tin chi tiết
logger.RecordInformationWithDetails("Người dùng đăng nhập", userId: 12345);
// Ghi log ngoại lệ
try
{
// Xử lý logic có thể gây lỗi
}
catch (Exception ex)
{
logger.RecordException(ex, "Xử lý thanh toán");
}
// Ghi lỗi tùy chỉnh
logger.RecordCustomError("Không tìm thấy dữ liệu", ex);
Lưu Ý Quan Trọng
- Đảm bảo đường dẫn thư mục log tồn tại trước khi chạy ứng dụng
- Thiết lập quyền truy cập ghi file cho ứng dụng
- Điều chỉnh mức giới hạn kích thước file theo nhu cầu thực tế
- Sử dụng level phù hợp cho từng môi trường (Dev: DEBUG, Production: INFO/WARN)
- Xem xét implement asynchronous logging cho performance cao hơn