日志(Serilog)
本页介绍 Ape‑Volo‑Admin Ape‑Volo‑Admin 的 Serilog 集成方式、配置项、常用 Sinks(文件/控制台/数据库/Elasticsearch)、结构化日志与最佳实践。
启用与初始化
位置:Ape.Volo.Infrastructure/Middleware/SerilogMiddleware.cs
csharp
public static class SerilogMiddleware
{
public static IHostBuilder UseSerilogMiddleware(this IHostBuilder builder)
{
return builder.UseSerilog((context, services, logger) =>
{
// 可切换为配置驱动:logger.ReadFrom.Configuration(context.Configuration)
logger.Enrich.FromLogContext();
logger.MinimumLevel.Debug();
logger.MinimumLevel.Override("Microsoft", LogEventLevel.Information);
logger.MinimumLevel.Override("Default", LogEventLevel.Information);
logger.MinimumLevel.Override("System", LogEventLevel.Information);
var serilogOptions = App.GetOptions<SerilogOptions>();
if (serilogOptions.ToFile.Enabled)
{
foreach (LogEventLevel level in Enum.GetValues(typeof(LogEventLevel)))
{
logger.WriteToFile(level);
}
}
if (App.GetOptions<SystemOptions>().IsQuickDebug && serilogOptions.ToConsole.Enabled)
{
logger.WriteToConsole();
}
if (serilogOptions.ToDb.Enabled)
{
logger.WriteToDb();
}
if (serilogOptions.ToElasticsearch.Enabled && App.GetOptions<MiddlewareOptions>().Elasticsearch.Enabled)
{
// docker run --name elasticsearch -d -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e "discovery.type=single-node" -p 9200:9200 -p 9300:9300 elasticsearch:7.5.0
logger.WriteToElasticsearch();
}
});
}
}要点:
- 默认采用代码方式初始化,亦可改为
ReadFrom.Configuration使用 appsettings 控制。 - 通过自定义
SerilogOptions控制启用的 Sink,按需输出到文件/控制台/数据库/Elasticsearch。 SystemOptions.IsQuickDebug用于开发期控制台输出开关。
注册为默认日志:Ape.Volo.Infrastructure/Extensions/SerilogExtensions.cs
csharp
public static class SerilogExtensions
{
public static void AddSerilogService(this IServiceCollection services)
{
services.AddLogging(builder =>
{
builder.ClearProviders();
builder.AddSerilog(dispose: true);
});
}
}配置项(SerilogOptions)
示例(appsettings.*.json):
json
{
"Serilog": {
"RecordSqlEnabled": true,
"ToDb": { "Enabled": true },
"ToFile": { "Enabled": true },
"ToConsole": { "Enabled": true },
"ToElasticsearch": { "Enabled": false }
}
}说明:
- RecordSqlEnabled:是否记录 SQL(建议仅在开发或排障时开启,注意脱敏)。
- ToFile/ToConsole/ToDb/ToElasticsearch:分别控制 Sinks 的启用。
- Elasticsearch 输出还受
MiddlewareOptions.Elasticsearch.Enabled影响。
提示:该 Options 通过
[OptionsSettings]自动注册绑定,详见《配置选项》文档。
输出开关一览(重点)
| 开关 | 作用 | 推荐环境 | 注意事项 |
|---|---|---|---|
| RecordSqlEnabled | 记录 ORM 执行的 SQL 与耗时 | 开发/联调临时开启;生产默认关闭 | 涉及敏感数据时务必脱敏;大量 SQL 日志会放大 I/O 与存储占用 |
| ToConsole.Enabled | 输出到控制台 | 开发 | 通常仅开发机开启;容器/生产建议关闭以减少噪音与 I/O |
| ToFile.Enabled | 输出到本地文件 | 开发/测试/生产 | 配合滚动策略与保留天数;注意磁盘容量与权限 |
| ToDb.Enabled | 输出到数据库 | 测试/生产(可选) | 已启用批量写入;需建立索引与归档任务,避免膨胀;DB 压力与容量需评估 |
| ToElasticsearch.Enabled | 输出到 Elasticsearch | 生产(可选) | 需要 ES/Kibana;网络与吞吐受限时注意重试与缓冲,索引模板要匹配版本 |
环境建议(可按需调整):
开发(Development)
- RecordSqlEnabled: 开启(排障时)
- ToConsole: 开启
- ToFile: 开启
- ToDb: 视需要
- ToElasticsearch: 关闭
测试/预生产(Staging)
- RecordSqlEnabled: 关闭(特殊问题临时开启)
- ToConsole: 关闭
- ToFile: 开启
- ToDb: 可开启(便于留痕)
- ToElasticsearch: 视环境开启
生产(Production)
- RecordSqlEnabled: 关闭
- ToConsole: 关闭
- ToFile: 开启(基础留痕)
- ToDb: 按需(配合归档/清理)
- ToElasticsearch: 推荐(集中检索与告警)
补充建议:
- 若同时启用 ToDb 与 ToElasticsearch,注意链路压力与重复存储成本;可按用途择一或分级输出。
- 对高频日志(如 Info)控制采样或限制日志点,避免在高 QPS 场景产生瓶颈。
- 统一结构化字段(如 TraceId/UserId/Action)便于跨 Sink 检索与关联分析。
Sinks 说明
文件(Rolling File)
- 方法:
logger.WriteToFile(level)(项目扩展) - 通常按级别分别落盘,便于按级别检索与轮转。
控制台
- 方法:
logger.WriteToConsole() - 受
SystemOptions.IsQuickDebug与SerilogOptions.ToConsole.Enabled控制。
数据库(自定义 Sink)
实现位置(节选):
csharp
public static class LoggerToDbSinkConfiguration
{
public static LoggerConfiguration WriteToDb(this LoggerConfiguration logger)
{
var sink = new LoggerToDbSink();
var options = new PeriodicBatchingSinkOptions
{
BatchSizeLimit = 500,
Period = TimeSpan.FromSeconds(1),
EagerlyEmitFirstEvent = true,
QueueLimit = 10000
};
return logger.WriteTo.Sink(new PeriodicBatchingSink(sink, options));
}
}要点:
- 使用
PeriodicBatchingSink聚合写入,降低对数据库的写放大。 - 建议为日志表加索引并设归档/保留策略,避免体积膨胀。
Elasticsearch
- 方法:
logger.WriteToElasticsearch() - 需确保 ES 服务可达并已开启中间件配置;版本示例:
elasticsearch:7.5.0 - 结合 Kibana 可进行可视化查询与仪表盘展示
最小级别与覆盖
csharp
logger.MinimumLevel.Debug();
logger.MinimumLevel.Override("Microsoft", LogEventLevel.Information);
logger.MinimumLevel.Override("Default", LogEventLevel.Information);
logger.MinimumLevel.Override("System", LogEventLevel.Information);建议:
- 应用代码保留 Debug 起步,外部组件(Microsoft/System)提升到 Information,降低噪音。
- 生产可整体抬升到 Information 或 Warning,结合异常告警。
结构化日志与上下文
启用上下文:logger.Enrich.FromLogContext()
在业务中添加上下文属性:
csharp
using (Serilog.Context.LogContext.PushProperty("TraceId", traceId))
{
_logger.LogInformation("User {UserId} login from {IP}", userId, ip);
}示例(注入 ILogger<T> 使用):
csharp
public class AccountService
{
private readonly ILogger<AccountService> _logger;
public AccountService(ILogger<AccountService> logger) => _logger = logger;
public void Login(long userId, string ip)
{
_logger.LogInformation("User {UserId} login from {IP}", userId, ip);
try
{
// ...
}
catch (Exception ex)
{
_logger.LogError(ex, "Login failed for {UserId}", userId);
throw;
}
}
}实战建议
- 分环境配置:在
appsettings.Development.json打开 Console/File 与 SQL 记录;生产收敛到 File/ES,并谨慎开启 SQL。 - 异步批量:对数据库/网络类 Sink 使用
PeriodicBatchingSink,设置合理批量与队列上限。 - 日志切分:文件日志按级别/日期滚动;设置保留天数,避免磁盘占满。
- 脱敏与合规:避免输出敏感信息(密码、密钥、身份证、手机号等);必要时做脱敏或过滤器。
- 关联 ID:为每个请求注入 TraceId/RequestId,便于端到端串联;可结合中间件写入 LogContext。
- 指标与告警:基于 ES/Kibana 或 APM 工具监控 Error/Warning 比例与关键字,设置阈值告警。
常见问题(FAQ)
- 为什么控制台没有日志?
- 检查
SystemOptions.IsQuickDebug以及SerilogOptions.ToConsole.Enabled; - 确认已调用
AddSerilogService()替换默认 Logging 提供者。
- 检查
- ES 输出失败?
- 确认
MiddlewareOptions.Elasticsearch.Enabled与 ES 服务可用; - 检查网络连通性与索引模板;
- 查看
WriteToElasticsearch()的内部配置是否与当前 ES 版本匹配。
- 确认
- 数据库日志膨胀?
- 启用归档/清理任务;
- 调整批量与保留策略,必要时降级写入级别。
相关文档
- 《配置选项(Options)》:SerilogOptions/MiddlewareOptions 的自动注册与说明。
- 《定时任务(Quartz)》:可用任务实现定期归档/清理历史日志。

