Ocelot网关日志体系构建:Serilog+Loki+Grafana全链路实践

一、技术选型与架构设计

在微服务架构中,API网关作为流量入口,其日志系统需要满足三大核心需求:高吞吐量写入、结构化查询能力、实时可视化分析。传统ELK方案存在资源消耗大、维护复杂等问题,而Loki作为云原生时代的日志存储方案,通过标签索引和对象存储分离设计,可显著降低存储成本。

1.1 组件协同机制

  • Serilog:提供结构化日志生成能力,支持多级日志过滤
  • Loki:实现日志的分布式存储与标签化查询,支持水平扩展
  • Grafana:构建可视化仪表盘,支持动态查询与告警集成
  • Ocelot中间件:扩展请求日志上下文,注入服务标识等元数据

1.2 部署架构图

  1. graph TD
  2. A[Ocelot网关集群] -->|日志推送| B(Serilog Sink)
  3. B -->|gRPC协议| C[Loki存储集群]
  4. C -->|查询接口| D[Grafana可视化]
  5. D -->|告警规则| E[监控告警系统]

二、环境准备与组件安装

2.1 基础环境要求

  • .NET Core 3.1+运行环境
  • Docker容器平台(19.03+版本)
  • 对象存储服务(用于Loki持久化存储)

2.2 组件安装流程

  1. # 安装Serilog核心包
  2. dotnet add package Serilog.AspNetCore
  3. dotnet add package Serilog.Sinks.Loki
  4. # 安装Grafana插件(可选)
  5. grafana-cli plugins install grafana-piechart-panel

建议采用分层安装策略:

  1. 基础层:Docker引擎、对象存储客户端
  2. 日志层:Serilog框架、Loki适配器
  3. 可视化层:Grafana及其插件系统

三、核心配置实现

3.1 Serilog配置详解

  1. Log.Logger = new LoggerConfiguration()
  2. .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
  3. .Enrich.WithProperty("AppName", "ocelot-gateway")
  4. .Enrich.WithMachineName()
  5. .WriteTo.LokiHttp(
  6. uri: "http://loki:3100/loki/api/v1/push",
  7. labels: new[] { "app", "level", "env" },
  8. batchPostingLimit: 1000,
  9. period: TimeSpan.FromSeconds(5)
  10. )
  11. .CreateLogger();

关键参数说明:

  • batchPostingLimit:批量写入阈值,影响吞吐量
  • period:刷新间隔,平衡实时性与资源消耗
  • labels:预定义标签集,决定查询维度

3.2 Loki存储优化

生产环境建议配置:

  1. # loki-config.yaml示例
  2. storage_config:
  3. aws:
  4. s3: s3://access-key:secret-key@region/bucket-name
  5. s3forcepathstyle: true
  6. schema_config:
  7. configs:
  8. - from: 2023-01-01
  9. store: boltdb-shipper
  10. object_store: aws
  11. schema: v12
  12. index:
  13. prefix: loki_index_
  14. period: 24h

3.3 Grafana数据源配置

  1. 添加Loki数据源:

    • URL设置:http://loki:3100
    • 默认查询间隔:15s
    • 最大数据点数:5000
  2. 仪表盘设计原则:

    • 采用PromQL风格查询语法
    • 关键指标:请求速率、错误率、延迟分布
    • 维度分解:按服务名、环境、版本过滤

四、高级功能实现

4.1 自定义日志中间件

  1. public class CustomLoggingMiddleware
  2. {
  3. private readonly RequestDelegate _next;
  4. public CustomLoggingMiddleware(RequestDelegate next)
  5. {
  6. _next = next;
  7. }
  8. public async Task InvokeAsync(HttpContext context)
  9. {
  10. var stopwatch = Stopwatch.StartNew();
  11. var request = context.Request;
  12. try
  13. {
  14. await _next(context);
  15. stopwatch.Stop();
  16. Log.Information("Request processed {@RequestInfo}", new {
  17. Path = request.Path,
  18. Method = request.Method,
  19. StatusCode = context.Response.StatusCode,
  20. DurationMs = stopwatch.ElapsedMilliseconds,
  21. TraceId = context.TraceIdentifier
  22. });
  23. }
  24. catch (Exception ex)
  25. {
  26. stopwatch.Stop();
  27. Log.Error(ex, "Request failed {@ErrorInfo}", new {
  28. Path = request.Path,
  29. Method = request.Method,
  30. StatusCode = context.Response?.StatusCode ?? 500,
  31. DurationMs = stopwatch.ElapsedMilliseconds
  32. });
  33. throw;
  34. }
  35. }
  36. }

4.2 敏感信息脱敏处理

实现ILogEventEnricher接口过滤敏感字段:

  1. public class SensitiveDataFilter : ILogEventEnricher
  2. {
  3. public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
  4. {
  5. if (logEvent.Properties.TryGetValue("Authorization", out var authProp))
  6. {
  7. logEvent.RemovePropertyIfPresent("Authorization");
  8. logEvent.AddOrUpdateProperty(
  9. propertyFactory.CreateProperty(
  10. "Authorization",
  11. "[FILTERED]"
  12. )
  13. );
  14. }
  15. // 添加其他敏感字段处理逻辑...
  16. }
  17. }

4.3 高可用架构设计

建议采用三节点Loki集群部署:

  1. [Loki写入节点] <--> [对象存储]
  2. | |
  3. [Loki查询节点] <--> [缓存层]

关键优化点:

  • 写入节点:启用-target=write模式
  • 查询节点:配置-target=read模式
  • 缓存配置:使用Redis作为查询结果缓存

五、生产环境最佳实践

5.1 日志级别策略

环境 Debug Information Warning Error Critical
开发
测试
生产

5.2 查询效率优化

  1. 标签设计原则:

    • 保持标签基数在1000以下
    • 避免高频变化的标签
    • 优先使用枚举型标签
  2. 查询语法示例:

    1. {app="ocelot-gateway", env="prod"} |= "error" | logfmt | duration > 500ms

5.3 容量规划模型

指标 计算公式 示例值
日均日志量 QPS × 日均请求数 × 单条日志大小 2.5GB/天
存储需求 日均日志量 × 保留周期 × 压缩比 150GB/月
查询并发 峰值QPS × 查询比例 × 复杂度系数 50 QPS

六、故障排查指南

6.1 常见问题处理

  1. 日志丢失

    • 检查Loki写入队列积压情况
    • 验证对象存储权限配置
    • 查看Serilog重试机制配置
  2. 查询超时

    • 优化查询标签组合
    • 增加Loki查询节点资源
    • 调整-querier.timeout参数
  3. 可视化异常

    • 验证Grafana数据源配置
    • 检查Loki指标端点可用性
    • 清除浏览器缓存重试

6.2 监控告警配置

建议设置以下关键告警规则:

  1. Loki写入延迟 > 5分钟
  2. 对象存储错误率 > 1%
  3. 查询响应时间 > 10s
  4. 日志吞吐量突降50%

通过这种集成方案,开发者可以构建出具备企业级特性的日志监控系统,既满足开发阶段的调试需求,又能支撑生产环境的稳定性保障。实际部署时建议先在测试环境验证全链路功能,再逐步推广到生产环境。