Sentry 是一个错误跟踪和性能监控服务。每当发生错误时,应用程序会向它发送一份报告。Sentry 会将相同的错误归并为一个 issue,显示堆栈跟踪和上下文,并在出现新 issue 时提醒团队。你可以使用 sentry.io 上的托管服务,也可以自行部署。借助 Sentry,你可以在一个地方找到所有站点的生产环境错误,而不必逐个搜索每个站点的错误日志。
概述
当你设置一个环境变量并且站点选择启用遥测后,Frappe 会将意外的服务器错误和 desk JavaScript 错误发送到 Sentry 项目。可选变量可以添加性能跟踪、性能分析和 SQL span。
- 每个 bench 一个 DSN。 DSN 来自进程环境,而不是来自
site_config.json。由同一组 web 和 worker 进程服务的所有站点都会报告到同一个 Sentry 项目。 - 两个开关。 DSN 为进程开启 Sentry SDK。系统设置中的复选框允许发送使用数据以改进应用程序(
enable_telemetry)决定每个站点是否发送任何内容。 - 错误跟随错误日志。 在服务器上,当 Frappe 写入一条错误日志时,事件会发送到 Sentry。如果你看到一条错误日志,Sentry 应该也有。
- 站点通过名称区分。 每个事件都会将 Sentry 用户 ID 设置为站点名称,因此你可以在 Sentry 中按站点筛选。
设置
为 web 和 worker 进程设置 FRAPPE_SENTRY_DSN,重启它们,然后在每个应报告的站点上启用遥测。
| 变量 | 值 | 效果 |
|---|---|---|
FRAPPE_SENTRY_DSN |
你项目的 DSN | 必需。在 web 服务器和后台 worker 中启动 Sentry SDK,并在 desk 中加载浏览器 SDK。 |
SENTRY_TRACING_SAMPLE_RATE |
0.0 到 1.0 之间的浮点数,例如 0.1 |
可选。为该比例的 web 请求和作业发送性能跟踪。 |
SENTRY_PROFILING_SAMPLE_RATE |
0.0 到 1.0 之间的浮点数 | 可选。为该比例的被跟踪事务发送 CPU 性能分析。需要启用跟踪。 |
ENABLE_SENTRY_DB_MONITORING |
任意非空值,例如 1 |
可选。将每个 SQL 查询记录为一个 span,并将每次数据库连接记录为一个面包屑。 |
- 在 Sentry 中创建一个项目(平台:Python)并复制其 DSN。
- 将这些变量添加到 Frappe web 服务器(gunicorn)以及每个
bench worker进程的环境中。使用 supervisor 时,使用每个程序的environment=行。使用 Docker 时,在后端和 worker 容器上设置它们。 - 重启进程。Frappe 仅在进程启动时读取这些变量。
- 在每个站点上,打开系统设置并勾选允许发送使用数据以改进应用程序。从 CLI 执行:
bench --site <site> execute frappe.db.set_single_value --args "['System Settings', 'enable_telemetry', 1]"</site>。 - 在浏览器中重新加载 desk,以便加载浏览器 SDK。
如果设置了 DSN 但站点的 enable_telemetry 处于关闭状态,该站点不会发送任何内容:没有服务器事件,没有浏览器事件,并且 desk 不会加载 SDK。
捕获的内容
Sentry 会获取开发者可以在代码中修复的错误。Frappe 有意向用户显示的错误则被排除在外。
| 来源 | 发送到 Sentry | 不发送 |
|---|---|---|
| Web 请求 | 以 HTTP 5xx 结束的未捕获异常。在开发者模式下,Frappe 记录的每个错误。 | frappe.ValidationError、frappe.PermissionError 及其子类(例如 frappe.throw() 消息、必填字段错误)。正常的 4xx 响应。 |
| 后台作业 | 失败并写入错误日志的作业。Worker 在每个作业后刷新事件。 | 与 web 请求相同的异常过滤器。 |
frappe.log_error() |
来自应用代码的每次调用,如果有活动异常则作为异常事件,否则作为带有标题和回溯的消息。 | 错误日志插入本身失败的调用。 |
| Desk(浏览器) | /desk 上的未捕获 JavaScript 错误和未处理的 promise 拒绝。 |
JS 中由 frappe.throw() 引发的错误。门户和网站页面:SDK 仅在 desk 中加载。会话跟踪已关闭。 |
服务器 SDK 运行时关闭了 Sentry 的默认集成。它不会挂钩 Python logging,因此 frappe.logger().error(...) 不会创建 Sentry 事件。来自 CSSUTILS 日志记录器的事件会被丢弃。
发布版本是 Frappe 版本(服务器上为 frappe.__version__,浏览器中为 frappe.boot.versions.frappe),因此你可以看到是哪个版本引入了错误。
性能监控
设置 SENTRY_TRACING_SAMPLE_RATE 以在 Sentry 中查看缓慢的端点和作业。在繁忙的站点上从低值开始(0.01 到 0.1),因为每个被跟踪的请求都会作为事务计费。
- Web 请求。 Frappe 将 WSGI 应用包装在 Sentry 的中间件中。事务按端点命名:RPC 调用为
/api/method/<dotted.path></dotted.path>,否则为 URL 路径。 - 后台任务。事务以任务的方法命名。计划任务则使用调度器任务类型。任务上下文包含任务 ID、其参数、是否为计划任务,以及它在队列中的等待时间(秒)。
- SQL span。启用
ENABLE_SENTRY_DB_MONITORING后,每次frappe.db.sql()调用都会变成一个带有查询文本的 span,并且每次数据库连接都会添加一条面包屑。这就是你查找 N+1 查询的方法。它也会给每次查询增加开销,所以在繁忙的生产环境中启用前请先测量。 - 性能分析。
SENTRY_PROFILING_SAMPLE_RATE是被追踪事务的一部分,因此0.5在追踪率为0.1时会分析 5% 的请求。
当这三个变量中的任意一个被设置时,Frappe 还会在每个请求和任务开始时标记作用域(事务名称、站点、用户、追踪 ID)。这仅在启用了遥测的站点上发生。
数据与隐私
错误事件可能包含业务和个人数据。请像对待生产数据库一样对待你的 Sentry 项目,并限制可以读取它的人员。
| Sentry 中的字段 | 内容 |
|---|---|
| 用户 ID | 站点名称,例如 “erp.example.com” |
标签 frappe_user |
已登录用户,例如 “jane@example.com”,或 “Guest” |
标签 frappe_trace_id |
X-Frappe-Request-ID 标头(如果请求带有的话) |
| 请求 | URL、方法、查询字符串和标头。SDK 会剥离 Cookie、Authorization 和其他敏感标头。不包含客户端 IP。 |
| 上下文 “JSON Body” / “Form Data” | 完整的请求负载,未经过滤。这可能包含文档数据和个人数据。 |
额外 job |
任务 ID、方法、所有任务参数、队列等待时间 |
| 堆栈跟踪 | 带有局部变量的代码帧(Sentry SDK 默认) |
| 消息 | 对于 frappe.log_error() 调用:Error Log 标题和回溯 |
| 模块、argv | 已安装的 Python 包和进程命令行 |
| SQL span | 仅查询文本。查询值不会被发送。 |
遥测复选框不涵盖性能数据。选择性加入检查针对错误事件和作用域标签运行。追踪、性能分析和 SQL span 会为进程中的每个请求和任务启动。如果一个 bench 托管了未选择加入的站点,请不要在其上设置这三个性能变量。
对于其他你绝不能存储的内容(例如包含国民身份证号或银行详细信息的字段),请使用 Sentry 的服务器端数据擦除功能。
故障排除
| 症状 | 检查项 |
|---|---|
| 完全没有事件 | FRAPPE_SENTRY_DSN 是否在运行进程的环境中,而不仅仅是你的 shell 中?设置后你是否重启了 Web 和工作进程?站点的 enable_telemetry 是否开启? |
| 存在 Error Log,但 Sentry 中没有任何内容 | 该异常是否是 ValidationError 或 PermissionError 的子类?这些会被有意跳过。 |
| Sentry 中有 500 错误,但没有 Error Log | 几秒后再检查。请求错误会以延迟插入的方式写入 Error Log。 |
| 缺少任务错误 | 检查工作进程是否具有 DSN。工作进程在启动时会启动自己的 SDK。 |
| 没有浏览器错误 | 打开 desk 并检查浏览器控制台中 frappe.boot.sentry_dsn 是否有值。如果为空,则站点的遥测已关闭。Content-Security-Policy 规则必须允许向你的 Sentry 主机发起请求。 |
| 事务过多或 Sentry 账单过高 | 降低 SENTRY_TRACING_SAMPLE_RATE 或将其移除,然后重启。 |
缺少来自脚本或 bench console 的错误 |
只有 Web 服务器和 bench worker 会启动 SDK。其他 CLI 命令不会向 Sentry 报告。 |
代码位于 frappe/utils/sentry.py、frappe/app.py(Web)、frappe/utils/background_jobs.py(工作进程)、frappe/utils/error.py(log_error 钩子)和 frappe/public/js/sentry.bundle.js(浏览器)中。