日志(基于Serilog的高性能日志记录库)
一个基于Serilog的高性能日志记录库,为GameFrameX框架提供统一的日志记录接口和丰富的日志输出功能。
特性
- 多级别日志支持 - 支持Verbose、Debug、Info、Warn、Error、Fatal六个日志级别
- 多输出目标 - 支持文件、控制台、Grafana Loki等多种输出方式
- 灵活配置 - 通过LogOptions类提供丰富的配置选项
- 文件滚动 - 支持按时间间隔和文件大小进行日志文件滚动
- 标签支持 - 支持为日志添加标签,便于分类和过滤
- 异常记录 - 专门的异常记录方法,包含完整的堆栈跟踪信息
- 控制台输出 - 支持同时输出到日志文件和控制台
- 高性能 - 基于Serilog构建,提供高性能的日志记录能力
安装
bash
dotnet add package GameFrameX.Foundation.Logger快速开始
1. 基本使用
csharp
using GameFrameX.Foundation.Logger;
// 使用默认配置初始化日志系统
var logger = LogHandler.Create(LogOptions.Default);
// 记录不同级别的日志
LogHelper.Info("应用程序启动");
LogHelper.Warn("这是一个警告消息");
LogHelper.Error("发生了一个错误");2. 自定义配置
csharp
using GameFrameX.Foundation.Logger;
// 创建自定义日志配置
var logOptions = new LogOptions("mylogs")
{
LogType = "WebApi",
LogTagName = "Production",
LogEventLevel = LogEventLevel.Information,
IsConsole = true,
RollingInterval = RollingInterval.Hour,
FileSizeLimitBytes = 50 * 1024 * 1024, // 50MB
RetainedFileCountLimit = 7 // 保留7个文件
};
// 初始化日志系统
var logger = LogHandler.Create(logOptions);
// 使用日志
LogHelper.Info("服务器", "服务器启动在端口 {Port}", 8080);
LogHelper.InfoConsole("同时输出到文件和控制台的消息");详细用法
日志级别
支持六个标准的日志级别:
csharp
// Verbose - 最详细的日志信息
LogHelper.Verbose("详细的调试信息");
// Debug - 调试信息
LogHelper.Debug("调试信息: 变量值 = {Value}", someValue);
// Information - 一般信息
LogHelper.Info("用户 {UserId} 登录成功", userId);
// Warning - 警告信息
LogHelper.Warn("磁盘空间不足,剩余: {FreeSpace}MB", freeSpace);
// Error - 错误信息
LogHelper.Error("数据库连接失败: {Error}", errorMessage);
// Fatal - 致命错误
LogHelper.Fatal("应用程序即将崩溃: {Reason}", reason);异常记录
专门的异常记录方法,自动包含堆栈跟踪:
csharp
try
{
// 可能抛出异常的代码
DoSomething();
}
catch (Exception ex)
{
// 记录异常
LogHelper.Error(ex);
// 带标签的异常记录
LogHelper.Error("数据库", ex);
// 自定义异常消息
LogHelper.Error("处理用户请求时发生错误: {Message}", ex.Message);
}标签支持
为日志添加标签,便于分类和过滤:
csharp
// 带标签的日志记录
LogHelper.Info("用户管理", "用户 {UserId} 创建成功", userId);
LogHelper.Warn("安全", "检测到可疑登录尝试,IP: {IP}", ipAddress);
LogHelper.Error("支付", "支付处理失败,订单号: {OrderId}", orderId);
// 带标签的控制台输出
LogHelper.InfoConsole("启动", "服务器启动完成,监听端口: {Port}", port);控制台输出
支持同时输出到日志文件和控制台:
csharp
// 仅输出到日志文件
LogHelper.Info("这条消息只会写入日志文件");
// 同时输出到日志文件和控制台
LogHelper.InfoConsole("这条消息会同时显示在控制台和日志文件中");
// 错误消息的控制台输出(红色显示)
LogHelper.ErrorConsole("这是一个错误消息,控制台中会以红色显示");
// 仅输出到控制台(不写入日志文件)
LogHelper.Console("这条消息只会显示在控制台");配置
LogOptions 配置类
csharp
var logOptions = new LogOptions("logs") // 日志目录名
{
// 基本配置
LogType = "WebServer", // 服务器类型标识
LogTagName = "Production", // 日志标签名
LogEventLevel = LogEventLevel.Info, // 最低日志级别
// 输出配置
IsConsole = true, // 是否输出到控制台
// 文件配置
RollingInterval = RollingInterval.Day, // 滚动间隔(天)
IsFileSizeLimit = true, // 是否限制文件大小
FileSizeLimitBytes = 100 * 1024 * 1024, // 文件大小限制(100MB)
RetainedFileCountLimit = 31, // 保留文件数量(31个)
// Grafana Loki 配置
IsGrafanaLoki = false, // 是否启用Loki
GrafanaLokiUrl = "http://localhost:3100", // Loki服务地址
GrafanaLokiLabels = new Dictionary<string, string>
{
["app"] = "myapp",
["env"] = "production"
},
GrafanaLokiUsername = "admin", // Loki用户名
GrafanaLokiPassword = "password" // Loki密码
};滚动间隔选项
csharp
// 支持的滚动间隔
RollingInterval.Infinite // 不滚动
RollingInterval.Year // 按年滚动
RollingInterval.Month // 按月滚动
RollingInterval.Day // 按天滚动(默认)
RollingInterval.Hour // 按小时滚动
RollingInterval.Minute // 按分钟滚动日志级别配置
csharp
// 支持的日志级别
LogEventLevel.Verbose // 最详细
LogEventLevel.Debug // 调试(默认)
LogEventLevel.Information // 信息
LogEventLevel.Warning // 警告
LogEventLevel.Error // 错误
LogEventLevel.Fatal // 致命错误高级用法
Grafana Loki 集成
支持将日志发送到Grafana Loki进行集中化日志管理:
csharp
var logOptions = new LogOptions()
{
IsGrafanaLoki = true,
GrafanaLokiUrl = "http://loki.example.com:3100",
GrafanaLokiLabels = new Dictionary<string, string>
{
["service"] = "user-service",
["environment"] = "production",
["version"] = "1.0.0"
},
GrafanaLokiUsername = "your-username",
GrafanaLokiPassword = "your-password"
};
var logger = LogHandler.Create(logOptions);自定义日志配置
支持通过回调函数进行更高级的自定义配置:
csharp
var logger = LogHandler.Create(logOptions, true, config =>
{
// 添加自定义的Sink
config.WriteTo.Email(
fromEmail: "noreply@example.com",
toEmail: "admin@example.com",
outputTemplate: "{Timestamp} [{Level}] {Message}{NewLine}{Exception}",
restrictedToMinimumLevel: LogEventLevel.Error
);
// 添加自定义的Enricher
config.Enrich.WithProperty("MachineName", Environment.MachineName);
config.Enrich.WithProperty("ProcessId", Environment.ProcessId);
});使用自定义Logger实例
csharp
// 创建多个Logger实例
var webLogger = LogHandler.Create(webLogOptions, false);
var dbLogger = LogHandler.Create(dbLogOptions, false);
// 使用特定的Logger实例
LogHelper.Info(webLogger, "Web请求处理完成");
LogHelper.Error(dbLogger, "数据库连接异常", exception);性能优化
异步日志刷新
csharp
// 同步刷新(阻塞)
LogHelper.FlushAndSave();
// 异步刷新(非阻塞)
LogHelper.CloseAndFlushAsync();条件日志记录
csharp
// 避免不必要的字符串格式化
if (logger.IsEnabled(LogEventLevel.Debug))
{
LogHelper.Debug("复杂的调试信息: {Data}", ExpensiveOperation());
}最佳实践
结构化日志
使用结构化的日志消息,便于后续分析:
csharp
// 好的做法 - 结构化日志
LogHelper.Info("用户登录成功,用户ID: {UserId}, IP: {IP}, 耗时: {Duration}ms",
userId, ipAddress, duration);
// 避免的做法 - 字符串拼接
LogHelper.Info($"用户登录成功,用户ID: {userId}, IP: {ipAddress}, 耗时: {duration}ms");合理使用日志级别
csharp
// Debug - 开发调试信息
LogHelper.Debug("进入方法 ProcessOrder,参数: {OrderId}", orderId);
// Info - 重要的业务事件
LogHelper.Info("订单创建成功,订单号: {OrderId}, 用户: {UserId}", orderId, userId);
// Warn - 可恢复的问题
LogHelper.Warn("重试连接数据库,第 {Attempt} 次尝试", attemptCount);
// Error - 需要关注的错误
LogHelper.Error("处理支付失败,订单: {OrderId}, 错误: {Error}", orderId, error);
// Fatal - 导致应用程序终止的严重错误
LogHelper.Fatal("数据库连接池耗尽,应用程序即将关闭");使用标签分类
csharp
// 按功能模块分类
LogHelper.Info("用户管理", "用户注册成功: {Email}", email);
LogHelper.Info("订单处理", "订单状态更新: {OrderId} -> {Status}", orderId, status);
LogHelper.Info("支付系统", "支付完成: {Amount} 元", amount);
// 按环境分类
LogHelper.Info("生产环境", "服务器启动完成");
LogHelper.Debug("开发环境", "调试信息: {Data}", debugData);异常处理
csharp
try
{
await ProcessOrderAsync(orderId);
LogHelper.Info("订单处理", "订单 {OrderId} 处理完成", orderId);
}
catch (BusinessException ex)
{
// 业务异常,记录为警告
LogHelper.Warn("订单处理", "业务规则验证失败: {Message}", ex.Message);
throw;
}
catch (Exception ex)
{
// 系统异常,记录为错误
LogHelper.Error("订单处理", ex);
throw;
}配置管理
csharp
// 开发环境配置
var devLogOptions = new LogOptions("logs")
{
LogEventLevel = LogEventLevel.Debug,
IsConsole = true,
RollingInterval = RollingInterval.Hour
};
// 生产环境配置
var prodLogOptions = new LogOptions("logs")
{
LogEventLevel = LogEventLevel.Information,
IsConsole = false,
RollingInterval = RollingInterval.Day,
IsGrafanaLoki = true,
GrafanaLokiUrl = "http://loki.prod.com:3100"
};
// 根据环境选择配置
var logOptions = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development"
? devLogOptions
: prodLogOptions;API 参考
LogHandler
| 方法 | 说明 |
|---|---|
LogHandler.Create(LogOptions) | 使用指定配置创建 Logger 实例 |
LogHandler.Create(LogOptions, bool) | 创建 Logger 实例,第二个参数控制是否设为全局默认 |
LogHandler.Create(LogOptions, bool, ``Action<LoggerConfiguration>``) | 创建 Logger 实例并通过回调自定义 Serilog 配置 |
LogHelper 日志记录方法
| 方法 | 说明 |
|---|---|
LogHelper.Verbose(message) | 记录 Verbose 级别日志 |
LogHelper.Debug(message) | 记录 Debug 级别日志 |
LogHelper.Info(message) | 记录 Information 级别日志 |
LogHelper.Warn(message) | 记录 Warning 级别日志 |
LogHelper.Error(message) | 记录 Error 级别日志 |
LogHelper.Fatal(message) | 记录 Fatal 级别日志 |
LogHelper.Info(tag, message, args) | 带标签的 Info 日志 |
LogHelper.Warn(tag, message, args) | 带标签的 Warn 日志 |
LogHelper.Error(tag, message, args) | 带标签的 Error 日志 |
LogHelper.Error(Exception) | 记录异常(含堆栈跟踪) |
LogHelper.Error(tag, Exception) | 带标签的异常记录 |
LogHelper.InfoConsole(message) | 同时输出到控制台的 Info 日志 |
LogHelper.ErrorConsole(message) | 同时输出到控制台的 Error 日志(红色) |
LogHelper.Console(message) | 仅输出到控制台 |
LogHelper.FlushAndSave() | 同步刷新并保存日志 |
LogHelper.CloseAndFlushAsync() | 异步关闭并刷新日志 |
LogOptions 主要属性
| 属性 | 类型 | 说明 |
|---|---|---|
LogSavePath | string | 日志目录路径 |
LogType | string | 服务器类型标识 |
LogTagName | string | 日志标签名 |
LogEventLevel | LogEventLevel | 最低日志级别 |
IsConsole | bool | 是否输出到控制台 |
RollingInterval | RollingInterval | 文件滚动间隔 |
FileSizeLimitBytes | long | 单个日志文件大小限制 |
RetainedFileCountLimit | int | 保留的日志文件数量 |
IsGrafanaLoki | bool | 是否启用 Grafana Loki |
GrafanaLokiUrl | string | Loki 服务地址 |
GrafanaLokiLabels | Dictionary<string, string> | Loki 标签 |
GrafanaLokiUsername | string | Loki 认证用户名 |
GrafanaLokiPassword | string | Loki 认证密码 |
依赖项
- Serilog.AspNetCore (9.0.0) - 核心日志框架
- Serilog.Sinks.Console (6.0.0) - 控制台输出
- Serilog.Sinks.File (7.0.0) - 文件输出
- Serilog.Sinks.Grafana.Loki (8.3.1) - Grafana Loki集成
- GameFrameX.Foundation.Json - JSON序列化支持
