mcpField
E
error-tracking

error-tracking

github.com/ssheleg开发4151 次安装2 天前更新
代码仓库

关于 error-tracking

面向将 Sentry 接入项目的开发者,提供错误跟踪配置与运维指南,重点说明敏感信息脱敏、版本关联和认证故障处理。

主要功能

  1. 01配置 Sentry SDK 与 DSN
  2. 02使用两层规则清理事件数据
  3. 03将发布版本关联到提交
  4. 04区分认证故障并指导恢复
  5. 05说明 Sentry CLI 与 MCP 用法

适用场景

  1. 01首次为项目接入 Sentry
  2. 02防止事件中的 URL 凭据泄露
  3. 03为发布配置提交归属
  4. 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.md
scrubbing.md
setup.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

把它们混为一谈会浪费一轮调试时间,因为其中一个工具的命令在另一个工具中并不存在,而且不会给出提示。

sentrysentry-cli
来源cli.sentry.dev、brew install getsentry/tools/sentrygithub.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 服务或钩子。
  • 没有 sentry CLI:说明一次,然后使用令牌直接调用 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”。

评论

支持 Markdown