|
@@ -0,0 +1,104 @@
|
|
|
|
|
+# Promtail JSON 采集方案 (v1.3)
|
|
|
|
|
+
|
|
|
|
|
+零侵入 · 防爆炸 · 生产级
|
|
|
|
|
+
|
|
|
|
|
+适用:Kubernetes 1.20+ / 裸机 / 容器混合场景
|
|
|
|
|
+
|
|
|
|
|
+目标:业务输出单行 JSON,采集层(Promtail / Vector)负责解析、采样、标签与告警,尽量降低业务代码改动与系统资源消耗。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 目录
|
|
|
|
|
+- [快速概述](#快速概述)
|
|
|
|
|
+- [日志格式](#日志格式)
|
|
|
|
|
+- [开发接入(低侵入)](#开发接入低侵入)
|
|
|
|
|
+- [Agent 选择与 Promtail 指南](#agent-选择与-promtail-指南)
|
|
|
|
|
+- [资源占用参考](#资源占用参考)
|
|
|
|
|
+- [存储与爆炸兜底](#存储与爆炸兜底)
|
|
|
|
|
+- [告警模板(LogQL)](#告警模板logql)
|
|
|
|
|
+- [运维 Checklist](#运维-checklist)
|
|
|
|
|
+- [迁移与回滚简要流程](#迁移与回滚简要流程)
|
|
|
|
|
+- [附录:脚本与示例文件](#附录脚本与示例文件)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 快速概述
|
|
|
|
|
+
|
|
|
|
|
+- 目标:统一单行 JSON 输出,由采集层负责所有解析与降噪。
|
|
|
|
|
+- 核心设计:尽早低成本过滤 → 保留低基数标签 → 基于哈希的采样 → 针对异常/慢调用/审计分支保留。
|
|
|
|
|
+- 可选优化:在高吞吐场景使用 `Vector` 替代 Promtail 做解析以节省 CPU/内存。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 日志格式
|
|
|
|
|
+
|
|
|
|
|
+建议业务输出单行 JSON(最小必需字段):
|
|
|
|
|
+
|
|
|
|
|
+```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` 字段区分
|
|
|
|
|
+
|
|
|
|
|
+注意:不要将高基数字段(如 `userId`、`orderId`)作为标签。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 开发接入(低侵入)
|
|
|
|
|
+
|
|
|
|
|
+- 将 `logback` 配置与 `common-logging` 模块统一下发,业务只需引入一次依赖并使用简单 wrapper(如 `AppLogger.info(...)`)。
|
|
|
|
|
+- 在网关/Filter/拦截器中统一设置 MDC 字段:`traceId`、`uri`、`startTime`、`userId`,请求结束时写入 `duration` 并清理。
|
|
|
|
|
+- 推荐接入 OpenTelemetry 自动注入 traceId,减少手动传递。
|
|
|
|
|
+
|
|
|
|
|
+示例:Async JSON appender(logback)
|
|
|
|
|
+
|
|
|
|
|
+```xml
|
|
|
|
|
+<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(伪码)
|
|
|
|
|
+
|
|
|
|
|
+```java
|
|
|
|
|
+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");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|