关于 error-tracking
面向将 Sentry 接入项目的开发者,提供错误跟踪配置与运维指南,重点说明敏感信息脱敏、版本关联和认证故障处理。
主要功能
- 01配置 Sentry SDK 与 DSN
- 02使用两层规则清理事件数据
- 03将发布版本关联到提交
- 04区分认证故障并指导恢复
- 05说明 Sentry CLI 与 MCP 用法
适用场景
- 01首次为项目接入 Sentry
- 02防止事件中的 URL 凭据泄露
- 03为发布配置提交归属
- 04排查令牌失效导致的服务降级
MCP 相关
说明 Sentry MCP 使用 OAuth,并指导将其配置在 Agent 自身而非共享 MCP 网关中;可在会话内读取和整理问题。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ssheleg/ sheleg-dev --skill error-tracking安装后在 Claude Code 中输入/error-tracking确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/releases.mdscrubbing.mdsetup.md详细介绍
error-tracking — 接入 Sentry,防止信息泄露,并让堆栈跟踪指向提交记录
接入 Sentry 只需 4 行 SDK 配置,这也是它通常做得不好的原因。 下面的 4 种失败都发生在这台机器上,由一个未使用此技能的 Agent 在 一次会话中亲历。
| 观察到的失败 | 造成的后果 |
|---|---|
| 把“获取 DSN”说成需要人工操作的步骤,还说必须先创建账号 | 账号已经存在,CLI 也已完成身份验证。错误跟踪功能无故处于关闭状态 |
不知道 EventScrubber 存在且默认运行,就编写了 before_send 清理器 | 无法说明哪一层负责什么,也就无法判断代码是多余的还是不可或缺的 |
| 不知道 MCP 使用 OAuth | 本来会在机器的共享网关中声明它,但 OAuth 流程无法在那儿完成 |
| 只设置 DSN 就停止 | 所有问题都会关联到没有提交记录的版本,始终无法归因到疑似提交 |
真正会泄露的情况
Sentry 内置的清理器会匹配键名,不会检查字符串值的内容。 凭据如果嵌在 URL 中——无论是在消息、异常值 还是面包屑里——都会原样通过。
基于 2026-08-24 的 sentry-sdk 2.19.2 测量结果:
from sentry_sdk.scrubber import EventScrubber
event = {"message": "could not connect to postgresql://u:SUPERSECRET@host/db"}
EventScrubber().scrub_event(event)
assert "SUPERSECRET" in str(event) # passes — it was NOT scrubbed
EventScrubber 默认启用,其拒绝列表包含 32 个键(password、
token、api_key、auth、secret、authorization 等),但不包括 dsn 和
database_url。
因此,如果某项服务已经会将数据库 URL 写入日志——这类错误并不少见——添加 Sentry 后,它就会开始把同一个密码转发给第三方,影响范围比日志更大。
始终使用两层防护:
from sentry_sdk.scrubber import DEFAULT_DENYLIST, EventScrubber
sentry_sdk.init(
dsn=..., environment=..., release=...,
event_scrubber=EventScrubber( # layer 1 — keys
denylist=DEFAULT_DENYLIST + ["dsn", "database_url", "auth_key"],
recursive=True,
),
before_send=scrub_values, # layer 2 — values
send_default_pii=False,
)
第 2 层是针对 URL 凭据的正则表达式。编写一个测试,断言仅使用第 1 层时仍会泄露——如果这个测试有朝一日变红,就说明 Sentry 开始清理值,第 2 层可能已是多余的。这种变化应该通过变红的测试来发现,而不是永远无人察觉。这两层防护,包括正则表达式和该测试,见 references/scrubbing.md。
DSN 不是身份验证令牌
它们是两种不同的对象,混为一谈会导致在不该紧张的地方过度紧张,在该谨慎的地方疏忽大意。
| DSN | 身份验证令牌 | |
|---|---|---|
| 方向 | 仅用于写入和接收数据 | 完整 API 访问权限 |
| 存放位置 | 构建产物中,包括客户端 | CI 密钥、开发者的密钥链 |
| 泄露后果 | 他人可以向你发送垃圾事件;可通过限流和轮换应对 | 他人可以读取你的问题并更改你的组织 |
| 用途 | 报告错误 | 创建项目、读取问题、发布版本 |
将 DSN 放在代码仓库中不够整洁;将身份验证令牌放进代码仓库则属于安全事件。CLI 和 MCP 都无法替代 DSN——它们负责操作 Sentry,而不是为你的应用添加监控。它们省去的是手动获取 DSN 这一步。
无需人工介入的设置方式
在把下面任何一项说成需要人工操作之前,先检查一下——答案往往是它已经设置好了:
sentry auth status # already authenticated? (credentials in ~/.sentry)
sentry org list --json # which orgs this token can see
sentry project list --json # what already exists
要为现有项目获取 DSN,也就是应用所需的 DSN:
sentry project view <org>/<project> --json | python3 -c "import json,sys; print(json.load(sys.stdin)[0]['dsn'])"
完整流程——安装、身份验证、创建项目、将 DSN 接入主机配置,以及 MCP 声明:首次为项目添加
Sentry 时,请阅读 references/setup.md。
看起来像身份验证问题、实际并非如此的 403
即使你是该组织的所有者,sentry project create 也可能失败并显示:
Your organization has disabled this feature for members.
测量日期:2026-08-24。原因是组织策略 allowMemberProjectCreation: false,它根据令牌的作用域而非用户的角色进行评估;而 sentry auth 保存的 OAuth 设备流令牌包含 project:admin 和 team:write,但没有 org:write 或 org:admin。团队作用域的端点(POST /teams/{org}/{team}/projects/)也会以同样的方式失败;这是同一项策略。
在认定是 bug 之前先检查:
sentry org view <org> --json | grep allowMemberProjectCreation
sentry api "/" --json # prints the token's actual scopes
有三种解决办法,按值得尝试的顺序排列:先在网页 UI 中创建一次项目;更改组织设置;或者签发内部集成令牌,这是 Sentry 文档中唯一明确说明可授予程序化创建项目所需组织级 API 访问权限的令牌类型。组织令牌是 CI 场景的推荐选择,但不能执行组织级操作;个人令牌则被明确不建议用于 CI。权衡对照表:references/setup.md。
有两个不同的工具都叫 sentry
把它们混为一谈会浪费一轮调试时间,因为其中一个工具的命令在另一个工具中并不存在,而且不会给出提示。
sentry | sentry-cli | |
|---|---|---|
| 来源 | cli.sentry.dev、brew install getsentry/tools/sentry | github.com/getsentry/sentry-cli |
| 特点 | 面向 Agent;提供 issue explain、issue plan,以及类似 gh api 的 api | 面向构建;处理源映射、调试文件 |
| 身份验证 | sentry auth — OAuth 设备流,存储于 ~/.sentry/ | SENTRY_AUTH_TOKEN |
| 两者都支持 | release create / set-commits / finalize / deploy、project、org |
两者都能执行发布命令。每个仓库选用其中一个,并在 README 中说明;否则,两个人可能会分别接入两套工具的不同部分。
确认没有被其他版本遮蔽,再信任版本号。 两者安装在不同的前缀目录中;~/.local/bin 通常优先于 /opt/homebrew/bin,因此较旧的副本会悄然生效:
which -a sentry | while read p; do printf '%-34s %s\n' "$p" "$("$p" --version 2>&1 | head -1)"; done
此处观察到的情况:0.38.0 遮蔽了 0.43.0。凭据存放在 ~/.sentry/,而非二进制文件旁边,因此删除过期副本不会让你退出登录。
MCP 使用 OAuth,这决定了它应声明在哪里
https://mcp.sentry.dev/mcp 对未经身份验证的请求会返回:
401 www-authenticate: Bearer realm="OAuth", …, resource_metadata="https://mcp.sentry.dev/.well-known/oauth-protected-resource/mcp"
携带 resource_metadata 的 www-authenticate 标头就是检测 OAuth 的依据。OAuth 上游会在自身地址将自己声明为资源,因此,指向本地网关的客户端必须拒绝这种不匹配,流程也就无法启动。OAuth MCP 服务应当配置在 Agent 自身的配置中,绝不能放在共享 MCP 网关后面。 选择接入方式之前先运行 curl;静态令牌上游应接入网关,OAuth 上游则不应如此。
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp/<org>/<project>
MCP 用于在会话中读取信息并进行分类处理。它只是一个加速工具:它能做的事,CLI 也都能做;没有它的机器不会损失任何能力。
发布,否则堆栈跟踪里什么也没有
只有当 Sentry 中的发布版本字符串与 SDK 报告为 release 的字符串完全一致时,这个发布才有用。两者不一致时,问题会关联到没有提交记录的发布,疑似提交归因也会悄然失效——这看起来像是“Sentry 不太好用”,而不是接入配置有问题。
选定一个版本来源,并在两端使用它。在 Heroku 上,这个来源是 slug 提交:
RELEASE = os.getenv("HEROKU_SLUG_COMMIT") or os.getenv("RELEASE")
VERSION="$(git rev-parse HEAD)" # the same value
sentry release create "<org>/$VERSION" --project <project> --finalize
sentry release set-commits "<org>/$VERSION" --auto
sentry release deploy "<org>/$VERSION" production
发布记录操作失败不应导致部署失败。 已进入生产环境的部署,不应仅仅因为发布调用未成功就被报告为失败。对每条命令进行保护,让它记录日志后继续执行;部署脚本示例见 references/releases.md,其中也说明了 --auto 对仓库集成的要求。
运行中的进程不等于正常工作的服务
观察于 2026-08-24:一个机器人令牌被轮换,平台有十分钟报告 dyno 处于 up 状态,日志也没有异常,但 API 对每次调用都返回 401,没有用户得到服务。系统中没有任何东西能分辨这种情况。
三种健康状态,因为“运行中”并非一个问题。 存活状态——进程存在且循环正常运行。就绪状态——当前可以完成工作(凭据有效);存活但凭据失效的进程是存活但尚未就绪,负载均衡器或监控程序应读取就绪状态,而非存活状态。degraded_auth——身份验证失败,其两个子情况需要采取截然相反的措施:
- 暂时性(令牌已轮换、网络短暂中断、重新连接即可修复的
401):进行有界重试并采用退避策略;重启是合理的,因为下次启动会使用新凭据——这正是“以非零状态退出,让崩溃循环显现出来”适用的情况。 - 终止性 / 已撤销(会话在服务端被终止):重启只会再次进入永远无法成功的登录循环。停止工作,转为未就绪状态,发出包含账户名称的告警,并等待新的身份验证——绝不进入重启循环。通过有界重试次数区分两者:针对相同身份验证错误的重试耗尽后,视为终止性错误,而不是“继续努力”。
恢复约定——两种技能都遵循同一张决策表。 仅当策略为 recoverable 时,监控程序才执行重启;无论哪个技能先发现事件,terminal 事件都绝不重启:
| 事件 | 策略 | 监控程序操作 | 就绪状态 |
|---|---|---|---|
暂时性身份验证失败(令牌已轮换、网络导致的 401) | recoverable | 重启 / 有界重试 | 未就绪 → 成功后就绪 |
| 针对相同身份验证错误的重试耗尽 | terminal | 停止、发出告警、等待新的身份验证 | 重新身份验证前保持未就绪 |
| 会话已撤销 / 已终止(MTProto 或 bearer) | terminal | 停止、发出告警、等待新的身份验证 | 重新身份验证前保持未就绪 |
已撤销会话对应的行在两个技能包中完全相同,因此相同事件不会触发相反操作:错误跟踪和 telegram-userbots 都遵循这项约定;监控程序重启 terminal 策略事件,就是这张表要禁止的错误。
只有在发生错误时,Sentry 才能提供帮助;连接停止工作但没有抛出错误时,不会产生任何事件。Cron 监控(sentry monitor)可覆盖作业停止运行的情况。
降级处理
- **主机能力各不相同:**检查当前客户端的 shell、网络、软件包安装权限,以及对 MCP 和技能调用的支持情况。不要仅凭非 Claude 主机名就推断这些能力不存在。如果满足前置条件,使用 CLI/SDK 途径;在受限容器中,说明无法执行的步骤,并准备好配置,但不要声称已完成设置。仅安装技能不会注册插件命令、MCP 服务或钩子。
- 没有
sentryCLI:说明一次,然后使用令牌直接调用 REST API(curl https://sentry.io/api/0/…),或使用 Web UI 一次性处理。不要反复尝试缺失的二进制文件。 - 没有 MCP:不会失去任何能力——使用
sentry issue list查看问题。 - 未通过身份验证,或缺少某项权限范围:交互式身份验证需要由人工完成。准确说明一次命令,指出受阻的内容,并继续处理所有不需要它的事项。
验证,而非假设
sentry auth status # authenticated, and as whom
sentry api "/" --json # the token's real scopes
sentry project view <org>/<project> --json # the DSN, and that it exists
sentry release list <org>/<project> --limit 3 # releases arriving at all
python3 -c "import sentry_sdk; print(sentry_sdk.VERSION)"
有两项说法值得重新测量,而不是直接相信本页内容,因为两者都取决于版本:默认拒绝列表的内容,以及 SDK 是否已开始清除值。references/scrubbing.md 中提供了对应的命令。
触发语
其他会转到此处的短语:“设置错误跟踪”、“sentry mcp”、“清除错误中的密钥”、“可疑提交”、“为什么 Sentry 为空”、“релизы в Sentry”、“наблюдаемость”。
已从 0.16.2 的描述移至此处:“release tracking”、“секреты в Sentry”。