1. 简介
本文将介绍如何在基于 Java 的服务端应用中集成 Sentry,实现错误自动追踪与上报。
2. 什么是 Sentry?
✅ Sentry 是一个错误追踪平台,用于帮助开发者实时监控应用程序中的异常行为。它可以自动捕获并报告 Java 应用中的错误或异常,并提供详细的上下文信息,便于复现、定位和修复问题。
Sentry 提供两种使用方式:
- 开源版本:需要自行部署、维护所有依赖的基础设施
- SaaS 服务:由 Sentry 官方托管,省去部署与维护成本
对于小型项目或评估用途,推荐使用 SaaS 模式。Sentry 提供了免费版(功能受限,如仅保留 24 小时错误记录),非常适合入门学习和测试。
3. Sentry 集成概览
无论使用哪种语言或框架,Sentry 的集成流程基本一致:
- 添加项目依赖
- 初始化 Sentry SDK
- 配置 API Key
此外,还可以选择性地:
- 添加额外标签或属性以丰富事件信息
- 主动上报某些业务逻辑中的关键事件
- 过滤某些不需要上报的事件
集成完成后,我们可以在 Sentry 的控制台看到错误信息。以下是一个典型的项目视图:
我们还可以配置告警规则,比如每当出现新错误时发送邮件通知:
4. 在 Java Web 应用中集成 Sentry
本文以标准的 Servlet 应用为例,演示如何集成 Sentry(Spring Boot 项目也有专用集成方式,此处暂不展开)。
4.1 Maven 依赖
对于标准的 Maven Web 项目,只需添加如下依赖:
<dependency>
<groupId>io.sentry</groupId>
<artifactId>sentry-servlet</artifactId>
<version>6.11.0</version>
</dependency>
✅ 最新版本可在 Maven Central 查看
4.2 测试 Servlet
我们创建一个简单的 FaultyServlet
,用于模拟以下三种行为:
- 无参数:返回 200 OK
op=fault
:返回 500 错误信息op=exception
:抛出未检查异常
代码如下:
@WebServlet(urlPatterns = "/fault", loadOnStartup = 1)
public class FaultyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String op = req.getParameter("op");
if("fault".equals(op)) {
resp.sendError(500, "Something bad happened!");
}
else if ("exception".equals(op)) {
throw new IllegalArgumentException("Internal error");
}
else {
resp.setStatus(200);
resp.setContentType("text/plain");
resp.getWriter().println("OK");
}
}
}
}
⚠️ 注意:这段代码本身 完全不知道 Sentry 的存在,这是为了模拟在已有项目中新增 Sentry 的场景。
4.3 SDK 初始化
Sentry 的 servlet 支持库包含了一个 ServletContainerInitializer
,容器会自动加载它。但这个初始化器 并不会自动启用 SDK,它仅用于注册一个 RequestListener
,以丰富事件上下文信息。
根据官方文档,SDK 的初始化需要手动调用 Sentry.init()
方法。初始化所需的关键信息是 DSN(Data Source Name),它是 Sentry 为每个项目生成的唯一标识,用于指定事件上报地址和认证。
DSN 示例:
https://[email protected]/161906
我们可以通过创建一个 ServletContextListener
来初始化 SDK:
@WebListener
public class SentryContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
Sentry.init();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
Sentry.close();
}
}
Sentry.init()
会从多个来源加载配置,包括:
- Java 系统属性
- 环境变量
- 当前目录下的
sentry.properties
- classpath 下的
sentry.properties
你也可以通过 sentry.properties.file
属性或 SENTRY_PROPERTIES_FILE
环境变量指定配置文件路径。
完整配置项详见:Sentry Java SDK Configuration
4.4 事件上报
SDK 初始化完成后,我们需要添加事件捕获逻辑。通常我们关注以下两类错误:
- 返回 5xx 状态码的请求
- 未处理的异常
对于 Servlet 应用,推荐通过 Filter
实现事件捕获:
@WebFilter(urlPatterns = "/*")
public class SentryFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
try {
chain.doFilter(request, response);
int rc = ((HttpServletResponse)response).getStatus();
if (rc / 100 == 5) {
Sentry.captureMessage("Application error: code=" + rc, SentryLevel.ERROR);
}
}
catch(Throwable t) {
Sentry.captureException(t);
throw t;
}
}
}
这段代码做了两件事:
- 如果响应状态码是 5xx,则通过
captureMessage()
上报错误信息 - 如果出现异常,则通过
captureException()
上报异常,并重新抛出以不影响原有错误处理逻辑
⚠️ 注意:该 Filter 仅处理同步请求,异步请求需要额外处理。
4.5 生成 DSN
要让应用能将事件发送给 Sentry,我们需要生成项目的 DSN:
- 登录 Sentry 控制台
- 点击左侧菜单中的 Projects
- 点击 Create Project
- 填写如下信息:
- Platform: Java
- Alert frequency: Alert me on every new issue
- Project name: sentry-servlet
点击创建后,进入项目设置页面,找到 SDK Instrumentation / Client Keys (DSN) 区域即可看到 DSN:
5. 测试 SDK 集成
将 DSN 添加到 sentry.properties
文件中:
# Sentry configuration file
dsn=https://[email protected]/161906
使用 Maven + Cargo 启动 Tomcat 嵌入服务器:
$ mvn package cargo:run
... many messages omitted
[INFO] [beddedLocalContainer] Tomcat 9.x Embedded started on port [8080]
[INFO] Press Ctrl-C to stop the container...
使用 curl 测试不同场景:
✅ 正常访问:
$ curl http://localhost:8080/sentry-servlet/fault
返回 200 和 "OK"
❌ 500 错误:
$ curl -v "http://localhost:8080/sentry-servlet/fault?op=fault"
进入 Sentry 控制台查看事件是否已捕获:
点击事件查看详细信息,包括我们通过 captureMessage()
上报的消息:
❌ 未处理异常:
$ curl -v "http://localhost:8080/sentry-servlet/fault?op=exception"
查看 Sentry 控制台确认异常被捕获,堆栈信息与代码中抛出位置一致:
6. 总结
本文演示了如何在标准 Servlet 应用中集成 Sentry SDK,并通过其 SaaS 服务实现错误自动上报。尽管我们只使用了基础功能,但 Sentry 提供的详细错误信息已足以显著提升开发者的错误分析效率。
完整代码可在 GitHub 获取。