全局异常处理器监控埋点的核心是让异常携带可分析上下文并自动采集上报,需提取请求路径、用户ID、客户端信息、TraceId及异常标签;通过内存计数器聚合高频异常,异步上报并脱敏敏感字段;告警联动Prometheus实现快速归因与技术债治理。

在全局异常处理器中做监控埋点,核心目标不是“记录所有异常”,而是让每次异常都携带可分析的上下文,并自动触发指标采集与上报。这需要把异常处理逻辑和可观测性链路打通,而不是简单加几行日志。
关键上下文变量要自动提取
异常本身是静态的,但发生异常的场景是动态的。以下变量建议在 @ExceptionHandler 方法内统一提取,避免业务层手动传参:
-
请求路径与 HTTP 方法:从
HttpServletRequest获取request.getRequestURI()和request.getMethod() -
用户身份标识:从 token、session 或请求头(如
X-User-ID)中解析,不依赖登录态完整与否,有就取,无则记为anonymous -
客户端信息:包括
User-Agent、X-Forwarded-For(真实 IP)、设备类型(可简单 UA 判断) -
调用链路 ID:若已集成 Sleuth/Baggage 或 OpenTelemetry,直接取
TraceId和SpanId,这是关联日志、指标、链路的关键 -
异常分类标签:比如
type=validation、type=timeout、type=db-connection,靠异常类型 + 消息关键词做轻量打标,不依赖人工枚举
频率统计要轻量且线程安全
高频异常(如每秒数十次)若每次上报都走网络或写磁盘,会拖垮服务。推荐两级聚合:
使用 ImageMagick 的 convert 和 mogrify 命令进行批量图像处理,支持调整大小、裁剪、水印和格式转换。与 libvips 集成以实现高性能缩略图生成。
- 内存计数器用
ConcurrentHashMap<string atomiclong></string>存储,key 可设计为异常类名:HTTP方法:路径前缀(例如ValidationException:POST:/api/v1/order) - 每 10 秒触发一次汇总任务,将当前窗口内各 key 的计数清零并推送到指标系统(如 Prometheus 的
Counter或 Micrometer 的Timer) - 对单个异常实例,只上报首次出现的完整堆栈(用于归因),后续同类型异常仅更新计数,避免日志爆炸
上报动作必须异步且带失败兜底
异常处理流程本身不能因上报失败而阻塞或失败——否则可能掩盖原始问题:
- 使用独立线程池(非 Tomcat 线程池)执行上报,防止 I/O 阻塞主线程
- 上报失败时,降级写入本地 RingBuffer(如 Log4j2 的
AsyncLogger)或临时文件,由后台巡检脚本定期补传 - 对敏感字段(如手机号、身份证号)在上报前做脱敏,规则写死在埋点工具类里,不交由业务判断
和告警策略联动才有实际价值
光有埋点不够,得让数据驱动响应:
- 对
5xx 异常率 > 1%或某接口 1 分钟内异常突增 5 倍这类指标配置 Prometheus Alertmanager 规则 - 在告警通知中直接附带最近 3 条异常的上下文摘要(用户 ID、路径、TraceId),方便值班人快速跳转到链路追踪平台
- 对高频重复异常(如每天固定时间出现的定时任务 DB 连接超时),自动归类为“待治理项”,推送到内部技术债看板

















