Skip to content

日志(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.IsQuickDebugSerilogOptions.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)》:可用任务实现定期归档/清理历史日志。

版权所有 © 2021-2026 ApeVolo-Team