DevOps Team d1f96fce2f 日志方案改动 2 mesiacov pred
..
Log-operation-full.md 7cf139cc90 Add non-overwriting full Log-operation copy 2 mesiacov pred
Log-operation.md a2fd98901c Move logs into logs/ and add examples; fix CI script 2 mesiacov pred
Log.md d1f96fce2f 日志方案改动 2 mesiacov pred
LoggingFilter.java a2fd98901c Move logs into logs/ and add examples; fix CI script 2 mesiacov pred
README.md 3a6dcbaf92 add log read.me 2 mesiacov pred
logback-spring.xml a2fd98901c Move logs into logs/ and add examples; fix CI script 2 mesiacov pred

README.md

Promtail JSON 采集方案 (v1.3)

零侵入 · 防爆炸 · 生产级

适用:Kubernetes 1.20+ / 裸机 / 容器混合场景

目标:业务输出单行 JSON,采集层(Promtail / Vector)负责解析、采样、标签与告警,尽量降低业务代码改动与系统资源消耗。


目录


快速概述

  • 目标:统一单行 JSON 输出,由采集层负责所有解析与降噪。
  • 核心设计:尽早低成本过滤 → 保留低基数标签 → 基于哈希的采样 → 针对异常/慢调用/审计分支保留。
  • 可选优化:在高吞吐场景使用 Vector 替代 Promtail 做解析以节省 CPU/内存。

日志格式

建议业务输出单行 JSON(最小必需字段):

{
  "ts":"2026-01-23T14:23:45.123Z",
  "level":"INFO|WARN|ERROR",
  "logger":"c.x.Foo",
  "msg":"...",
  "traceId":"a1b2c3",
  "uri":"/api/order",
  "duration":120,
  "userId":123456,
  "event":"order_create|login|APP_START|security|slow_sql",
  "error":"NullPointerException: xxx"
}

说明:

  • 无异常:error=""
  • 慢调用:duration>500(ms)
  • 审计/安全/生命周期:通过 event 字段区分

注意:不要将高基数字段(如 userIdorderId)作为标签。


开发接入(低侵入)

  • logback 配置与 common-logging 模块统一下发,业务只需引入一次依赖并使用简单 wrapper(如 AppLogger.info(...))。
  • 在网关/Filter/拦截器中统一设置 MDC 字段:traceIduristartTimeuserId,请求结束时写入 duration 并清理。
  • 推荐接入 OpenTelemetry 自动注入 traceId,减少手动传递。

示例:Async JSON appender(logback)

<appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
  <encoder class="net.logstash.logback.encoder.LogstashEncoder">
    <includeContext>true</includeContext>
    <provider class="net.logstash.logback.composite.loggingevent.LoggingEventPatternJsonProvider">
      <pattern>{"ts":"%d{yyyy-MM-dd'T'HH:mm:ss.SSS'Z'}","level":"%level","logger":"%logger","msg":"%msg","traceId":"%X{traceId:-}","uri":"%X{uri:-}","duration":"%X{duration:-0}","userId":"%X{userId:-}","event":"%X{event:-}","error":"%X{error:-}"}</pattern>
    </provider>
  </encoder>
</appender>

<appender name="ASYNC_JSON" class="ch.qos.logback.classic.AsyncAppender">
  <appender-ref ref="JSON" />
</appender>

<root level="INFO"><appender-ref ref="ASYNC_JSON"/></root>

Servlet Filter(伪码)

public class LoggingFilter implements Filter {
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
    String traceId = extractOrGenerate(req);
    MDC.put("traceId", traceId);
    MDC.put("uri", ((HttpServletRequest)req).getRequestURI());
    long start = System.currentTimeMillis();
    try { chain.doFilter(req, res); }
    finally {
      MDC.put("duration", String.valueOf(System.currentTimeMillis() - start));
      MDC.remove("traceId"); MDC.remove("uri"); MDC.remove("duration");
    }
  }
}

Agent 选择与 Promtail 指南

  • 何时用 Vector:当每节点日志吞吐大(数十 MB/s)或对 CPU/内存敏感,优先使用 Vector 做高效 JSON 解析与标签抽取。
  • Promtail 场景:路径收集或小规模集群。若用 Promtail,尽量把复杂解析移到 Vector/后端。

Promtail 配置要点(原则):

  • 先用非常廉价的判断(按 level 快速 drop DEBUG/TRACE),避免复杂正则。
  • 在深度解析前完成 drop/采样,减少 JSON parse 次数。
  • 只将低基数字段作为 label(例:levelnamespaceeventexception_type)。
  • duration 作为 numeric 字段供 unwrap/unpack 使用,不作为标签。

(保留原方案“三段减压 + 哈希采样 + 异常/慢调用/审计分支”思路,详见 Log.md。)


资源占用参考(4C8G 节点)

阶段 CPU 内存 说明
原始全量 JSON 解析 150-200% 400 MB 无过滤
加三段减压阀后 30-40% 120 MB 同集群实测
换 Vector 解析 10-15% 100 MB Promtail 仅转发

测试提示:在 staging 用真实流量做 A/B 对比(72 小时)量化效果。


存储与爆炸兜底

  1. 标签基数门禁:上线前运行基数扫描脚本,任一计划作为 label 的字段 24h 唯一值 > 5000 则阻断发布。

  2. Loki 整流:

limits_config:
  per_stream_rate_limit: 3MB
  per_stream_rate_limit_burst: 5MB
  ingestion_rate_mb: 10
  ingestion_burst_size_mb: 20

超限将被丢弃并暴露 rate_limit_discarded_bytes 指标。

  1. Retention:audit 流 365d,其余 7d,持久化到 S3/OSS。

基数扫描示例(部署前/CI)

logcli query '{env="prod"}' --since=24h | jq -r '.[].event' | sort | uniq -c | awk '$1>5000{print $2, $1}'

告警模板(LogQL)

保留原有:异常突增、慢调用 P99、审计事件下降。

补充监控:agent 解析错误与丢弃量

# agent parsing errors
sum(rate(promtail_parsing_errors_total[5m])) > 0

# Loki 丢弃流量
rate(loki_ingester_discarded_bytes_total[5m]) > 0

# Promtail/Vector 本地丢弃量(采样)
rate(promtail_dropped_bytes_total[5m]) > 0

运维 Checklist

每日

  • kubectl top pod -l app=promtail 单核 CPU <500m
  • 部署前运行基数扫描脚本(CI/PR 阶段)

每周

  • 检查 rate(promtail_dropped_bytes_total[5m]) > 0(确认采样生效)

每月

  • 回顾 per_stream_rate_limit 丢弃量并调整采样策略

新增:在 Helm/Chart CI 中加入基数检测脚本,发现高基数阻断发布并在 PR 中给出异常样例。


迁移与回滚简要流程

阶段:

  1. Staging:双写(旧流 & 新流)72 小时,验证告警与检索一致性。
  2. Canary:10% 节点,逐步增加采样并监控 parsing_errorsdropped_bytes、Loki ingress。
  3. 全量切换并监控 24-72 小时;若异常立即回滚并恢复双写。

回滚:通过 Git/Helm release 快速回退到上一个成功版本。