应直接在异常发生点埋点计数并多维打标,用meter率替代counter告警,关联traceid与业务标签实现可追溯。

直接用Metrics(如Dropwizard Metrics、Micrometer等)监控异常抛出频率,核心是“捕获异常发生点 + 计数 + 暴露指标”,不是事后查日志,而是让异常本身变成可度量的信号。
在异常实际抛出处埋点计数
不要等全局异常处理器才统计——那里只能看到“被拦截的异常”,而忽略那些被局部try-catch吞掉、未传播出去但业务已出错的情况。真正要监控的,是代码中明确判定为异常逻辑的节点。
- 在service方法内,当校验失败、依赖返回非法值、状态不满足前置条件时,主动调用counter.increment(),再throw新异常或返回错误结果
- 对第三方SDK调用失败(如HTTP 5xx、DB timeout),在catch块里先记录metric,再按需重抛或降级
- 避免在finally或通用装饰器里无差别计数——会把正常流程中的预期异常(如Optional.empty()抛出NoSuchElementException)也计入,失真
按异常类型+业务维度多维打点
只用一个“exception.total”计数器毫无诊断价值。应结合标签(tag)或命名空间区分关键维度:
- 用MetricRegistry.counter("exception.payment.timeout", "service", "payment-gateway", "upstream", "alipay") 区分支付渠道超时场景
- 对同一类异常,按触发环节拆:”exception.order.create.validation“、”exception.order.create.persist“、”exception.order.create.notify“
- 敏感操作(如资金扣减)的异常必须单独指标,不与查询类异常混用
设置合理采样与告警阈值
异常频次本身是瞬时波动大的指标,直接告警原始计数值容易误报:
- 用Meter(每秒平均率)替代Counter做告警依据,例如meter.mark()每次异常后调用,告警看1分钟/5分钟rate.mean
- 对低流量接口,设“5分钟内≥3次”比“每秒≥0.01次”更实用;对高并发服务,关注P99延迟突增伴随的异常率跳升
- 将异常指标和关联健康信号(如下游响应时间、线程池活跃数)组合判断,避免单点误判
确保指标可观察、可追溯
埋点只是开始,关键是要能快速定位问题上下文:
- 把异常指标名与日志traceId字段对齐,例如logback中%replace(%X{traceId}){'^$','unknown'},确保指标暴涨时能按traceId查原始日志
- 暴露指标时保留业务标识:Prometheus中用label如exception_type="TimeoutException", business_code="REFUND_002"
- 定期清理不再维护的老异常指标,避免监控面板堆积无效项干扰判断










