# Syslog WAL 与分 IP 诊断历史 ## 功能范围 `syslog-serve` 每分钟保存一次全局 WAL 状态,并按来源 IP 保存接收、WAL 持久化、Kafka ACK、过滤、背压、丢弃和 TCP 异常计数。网络异常发生时立即写入事件文件。 某个来源 IP 抛出网络接入异常后,如果后续重新收到该 IP 的数据,服务会打印一次 `Syslog 网络接入异常后已恢复接收` 日志,并包含异常时间、恢复时间和两者间隔。该机制不根据无数据时长推断断网,也不生成离线统计;连续正常数据不会重复打印恢复日志。 诊断文件不经过 Kafka 和数据库,默认写入容器目录 `/app/logs/syslog-monitor`。生产编排已将 `/app/logs` 映射到宿主机 `/home/syslog/logs`,因此容器重启不会删除历史。文件按自然日生成,保留今天及此前 6 天,共 7 天。 诊断记录不包含日志正文、凭据或 Kafka 消息内容。 ## 文件目录 ```text /home/syslog/logs/syslog-monitor/ ├── snapshots/syslog-status-YYYY-MM-DD.jsonl ├── ip-snapshots/syslog-ip-status-YYYY-MM-DD.jsonl └── events/syslog-events-YYYY-MM-DD.jsonl ``` - `snapshots`:全局 WAL、磁盘和 Kafka 投递状态,每分钟一行。 - `ip-snapshots`:每个来源 IP 每分钟一行,包含进程累计值与相邻快照增量 `delta`。 - `events`:`TOO_LONG_FRAME`、`CONNECTION_RESET`、超长消息和最终设备过滤等即时事件。 每次进程启动生成新的 `instance_id`,并记录 `process_start_time`。对累计值进行跨重启分析时必须按 `instance_id` 分段。 ## 部署配置 生产默认值: ```yaml environment: - SYSLOG_DIAGNOSTICS_DIRECTORY=/app/logs/syslog-monitor - SYSLOG_DIAGNOSTICS_RETENTION_DAYS=7 ``` 可选参数: ```text SYSLOG_DIAGNOSTICS_ENABLED=true SYSLOG_DIAGNOSTICS_SNAPSHOT_INTERVAL_MS=60000 SYSLOG_DIAGNOSTICS_MAX_SOURCE_IPS=10000 SYSLOG_DIAGNOSTICS_EVENT_QUEUE_CAPACITY=10000 ``` 来源 IP 超过上限后,新 IP 的指标汇总到 `__OTHER__`,避免伪造 UDP 来源导致内存无限增长。事件队列满时不会阻塞 Netty 接入线程,丢弃的诊断事件数量通过 `event_queue_dropped` 暴露。 ## 现场查询 ### 第一步:检查诊断持久化是否正常 ```bash docker exec syslog-serve-dm sh -c \ "curl -fsS http://127.0.0.1:8189/syslogserve/api/syslog/wal/diagnostics/current" ``` 确认以下字段: ```text persistence.enabled = true persistence.active = true persistence.retention_days = 7 persistence.initialization_failures = 0 persistence.snapshot_write_failures = 0 persistence.event_write_failures = 0 persistence.event_queue_dropped = 0 persistence.last_write_error = null ``` ### 第二步:查询单个来源 IP ```bash docker exec syslog-serve-dm sh -c \ "curl -fsS 'http://127.0.0.1:8189/syslogserve/api/syslog/wal/diagnostics/current?source_ip=10.56.170.107'" ``` 主要字段: ```text network_received wal_appended wal_admission_backpressure wal_admission_unavailable kafka_acked invalid_device_dropped oversized_dropped udp_dropped tcp_pause_total tcp_pending_frames_current tcp_pending_frames_max network_exception_total tcp_network_exception_total udp_network_exception_total tcp_connection_reset_total tcp_too_long_frame_total dispatch_terminal_dropped dispatch_retry last_receive_time last_exception_time ``` `wal_appended` 只在 WAL 完成持久化后增加;`kafka_acked` 只在 Kafka 明确 ACK 后增加。 全局状态还包含 `wal_pending_bytes`、`wal_max_pending_bytes`。前者是当前待落盘字节数,后者是配置上限,配置为 `0` 表示不限制。`wal_admission_unavailable` 表示 WAL 因未运行、致命错误或磁盘进入 `CRITICAL` 而拒绝接入尝试的次数;TCP 会保留并重试待处理帧,因此该值不等于 TCP 丢失消息数。`tcp_pending_frames_current` 是当前在 TCP Handler 内等待进入 WAL 的帧数,`tcp_pending_frames_max` 是当前进程启动以来的峰值;连接关闭时未处理帧会从 current 中回减。 ### 第三步:查询当天历史 直接在宿主机按 IP 查询: ```bash grep -F '"source_ip":"10.56.170.107"' \ /home/syslog/logs/syslog-monitor/ip-snapshots/syslog-ip-status-2026-09-16.jsonl ``` 查询该 IP 的异常事件: ```bash grep -F '"source_ip":"10.56.170.107"' \ /home/syslog/logs/syslog-monitor/events/syslog-events-2026-09-16.jsonl ``` 也可以通过 HTTP 下载: ```text GET /syslogserve/api/syslog/wal/diagnostics/history?date=2026-09-16&type=snapshots GET /syslogserve/api/syslog/wal/diagnostics/history?date=2026-09-16&type=ip GET /syslogserve/api/syslog/wal/diagnostics/history?date=2026-09-16&type=events ``` ## 计数对账 同一 `instance_id` 下: ```text 有效设备 WAL 持久化量 ≈ wal_appended 成功发往 Kafka 的数量 = kafka_acked 当前实例尚未 ACK 的近似数量 = wal_appended - kafka_acked - dispatch_terminal_dropped ``` 重启后可能重放旧 WAL,因此分 IP 的 `kafka_acked` 可能暂时大于本实例的 `wal_appended`。此时以全局 `wal_pending_approx`、WAL 序号以及 `instance_id` 为准,不应把负差值解释为异常。