sentry 默认按异常类名自动聚合错误,但需避免包装异常、重写消息等干扰,可通过 beforesend 强制设置 exception.type、用 fingerprint 和 tags 辅助分组,并通过 debug 模式和 ui 分组规则验证。

Sentry 默认按异常类型(即类名)自动聚合错误,所以只要抛出的是不同自定义异常类,Sentry 就会天然按类名分组。但实际中常因堆栈干扰、消息覆盖或配置问题导致分类不准,需针对性调整。
确保异常类名不被 Sentry 误覆盖
Sentry 默认提取 exception.type 字段作为分组依据,该值来自异常对象的 getClass().getName()。若手动调用 Sentry.captureException(e) 或使用自动拦截(如 Spring Boot Sentry Starter),只要异常是标准 Java 异常子类,类名就会被正确识别。
常见干扰项:
- 不要在捕获后包装成
RuntimeException并丢弃原始类型,例如:throw new RuntimeException("xxx", originalException)—— 这会让 Sentry 记录为java.lang.RuntimeException,丢失原始类名 - 避免重写
toString()或getMessage()并在 Sentry 中强制设置message,否则可能触发基于消息的错误合并(尤其当多个类抛出相同 message 时)
用 beforeSend 显式强化类型标识
若业务中存在动态代理、统一异常处理器或框架封装(如 Spring 的 @ControllerAdvice),原始异常可能被包裹。此时可在 Sentry 初始化时通过 beforeSend 钩子还原真实异常类型:
Sentry.init(options -> {
options.setDsn("https://xxx@o123.ingest.sentry.io/456");
options.setBeforeSend((event, hint) -> {
Throwable throwable = hint.getOriginalException();
if (throwable != null) {
// 强制将 exception.type 设为最内层异常的真实类名
event.getExceptions().getData().forEach(exception ->
exception.setType(throwable.getClass().getName())
);
}
return event;
});
});
利用 tags 和 fingerprint 辅助精细分组
当多个自定义异常类语义相近(如 OrderValidationException 和 PaymentValidationException),而你希望它们归入同一逻辑组,可配合 fingerprint 控制聚合逻辑:
- 添加业务标签便于筛选:
event.setTag("biz-module", "order") - 自定义 fingerprint 强制合并:
event.setFingerprint(Arrays.asList("{{ default }}", "order-validation")),这样不同类但同 fingerprint 的事件会聚到一起 - 反向操作:若同一异常类因不同场景需拆分(如按 HTTP 状态码),可在
beforeSend中动态设 fingerprint:Arrays.asList("{{ default }}", statusCode)
验证与调试技巧
上线前建议做两件事:
- 在本地启用 Sentry debug 模式:
options.setDebug(true),查看控制台输出的eventJSON,确认exception.type字段是否为你期望的自定义类全限定名 - 在 Sentry UI 的 Issue 页面点击「Grouping」→「View Rules」,检查当前分组规则是否依赖
exception.type;若看到message或stacktrace占主导,说明类名未生效,需回溯异常抛出链路
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











