1. 简介

本文将介绍如何在基于 Java 的服务端应用中集成 Sentry,实现错误自动追踪与上报。

2. 什么是 Sentry?

Sentry 是一个错误追踪平台,用于帮助开发者实时监控应用程序中的异常行为。它可以自动捕获并报告 Java 应用中的错误或异常,并提供详细的上下文信息,便于复现、定位和修复问题。

Sentry 提供两种使用方式:

  • 开源版本:需要自行部署、维护所有依赖的基础设施
  • SaaS 服务:由 Sentry 官方托管,省去部署与维护成本

对于小型项目或评估用途,推荐使用 SaaS 模式。Sentry 提供了免费版(功能受限,如仅保留 24 小时错误记录),非常适合入门学习和测试。

3. Sentry 集成概览

无论使用哪种语言或框架,Sentry 的集成流程基本一致:

  1. 添加项目依赖
  2. 初始化 Sentry SDK
  3. 配置 API Key

此外,还可以选择性地:

  • 添加额外标签或属性以丰富事件信息
  • 主动上报某些业务逻辑中的关键事件
  • 过滤某些不需要上报的事件

集成完成后,我们可以在 Sentry 的控制台看到错误信息。以下是一个典型的项目视图:

typical project

我们还可以配置告警规则,比如每当出现新错误时发送邮件通知:

formatted message

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:

  1. 登录 Sentry 控制台
  2. 点击左侧菜单中的 Projects
  3. 点击 Create Project
  4. 填写如下信息:
    • Platform: Java
    • Alert frequency: Alert me on every new issue
    • Project name: sentry-servlet

点击创建后,进入项目设置页面,找到 SDK Instrumentation / Client Keys (DSN) 区域即可看到 DSN:

project keys

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 控制台查看事件是否已捕获:

project issues

点击事件查看详细信息,包括我们通过 captureMessage() 上报的消息:

issue detail

❌ 未处理异常:

$ curl -v "http://localhost:8080/sentry-servlet/fault?op=exception"

查看 Sentry 控制台确认异常被捕获,堆栈信息与代码中抛出位置一致:

issue undlandled exception

6. 总结

本文演示了如何在标准 Servlet 应用中集成 Sentry SDK,并通过其 SaaS 服务实现错误自动上报。尽管我们只使用了基础功能,但 Sentry 提供的详细错误信息已足以显著提升开发者的错误分析效率。

完整代码可在 GitHub 获取。


原始标题:Quick Guide to Sentry