私有部署与观测

GrowthBook · Sentry

两个可配置、可关闭的观测与门控系统:GrowthBook 负责运行时的特性开关与 A-B 分组, Sentry 负责运行时异常捕获与上报。未配置时两者都完全静默,不产生任何网络请求。

  • 特性开关
  • 错误追踪
  • 可配置 / 可关闭

这是什么

本页覆盖两个相互独立的系统,它们都不依赖千手大师的默认构建行为,而是按配置启用:

GrowthBook 是一个运行时的、基于用户属性的功能门控与 A-B 测试系统。它与构建时的 feature() 宏互补:feature() 是「全有或全无」的编译期开关,而 GrowthBook 支持按用户、设备、组织、订阅类型等属性细粒度灰度。业务代码通过 getFeatureValue_CACHED_MAY_BE_STALE(feature, defaultValue) 查询以 tengu_* 前缀命名的开关;每个调用都带默认值,因此不配置任何 feature 也能正常运行。

Sentry 用于捕获运行时异常并上报到指定的 Sentry 实例。启用后自动捕获未处理异常和关键错误, 上报前会剥离敏感请求头,并忽略网络不可达与用户主动取消类噪声错误;未配置时所有导出均为 no-op。

i
GrowthBook 依赖 1P 事件日志

isGrowthBookEnabled() 在没有自定义服务器配置时,回退到 is1PEventLoggingEnabled()。在当前构建中该方法为 stub(恒返回 false), 因此 GrowthBook 默认不启用;只有同时设置 CLAUDE_GB_ADAPTER_URL 与 CLAUDE_GB_ADAPTER_KEY(适配器模式)时才会真正拉取远程配置。

前置条件

GrowthBook

  • 一个 GrowthBook 实例:自部署(Docker / Kubernetes)或 GrowthBook Cloud 均可。
  • 实例中的 SDK Connection 及其 SDK Key(形如 sdk-xxxxx), 作为 CLAUDE_GB_ADAPTER_KEY。
  • 实例的 API 地址,形如 https://gb.example.com/,作为 CLAUDE_GB_ADAPTER_URL。两个变量必须同时提供。

Sentry

  • 一个 Sentry 实例:自托管或 sentry.io Cloud 均可。
  • 在实例中创建一个 Node.js 平台的 Project,并从 Settings → Projects → Client Keys 取得该项目的 DSN。
  • 运行环境网络可访问 DSN 指向的主机。

安装 / 启用

启用 GrowthBook(适配器模式)

  1. 部署或选择一个 GrowthBook 实例

    自部署可用官方 Docker 镜像;也可以直接用 GrowthBook Cloud。

  2. 创建 SDK Connection,取得 SDK Key

    在实例中创建一个 Environment(如 production),再创建 SDK Connection。

  3. 设置两个适配器环境变量

    两个变量都设置时启用适配器模式,否则完全跳过 GrowthBook。

    Terminal
    CLAUDE_GB_ADAPTER_URL=https://gb.example.com/ \
    CLAUDE_GB_ADAPTER_KEY=sdk-abc123 \
    qsdashi
  4. 按需创建 Feature

    Feature Key 与类型须与代码中查询的 key 一致(见配置一节);未创建的 key 一律走代码默认值。

启用 Sentry

  1. 获取项目 DSN

    从 Sentry Project 的 Client Keys 页面复制 DSN。

  2. 设置 SENTRY_DSN

    只需这一个变量,设置后 initSentry() 即自动初始化。不设置则完全静默。

    Terminal
    SENTRY_DSN=https://public_key@your-sentry.example.com/123 qsdashi

配置

GrowthBook 环境变量

环境变量 必填 说明
CLAUDE_GB_ADAPTER_URL 是 GrowthBook API 地址,如 https://gb.example.com/(优先于内置默认地址)
CLAUDE_GB_ADAPTER_KEY 是 GrowthBook SDK Client Key,如 sdk-xxxxx(优先级高于内置 client key)
CLAUDE_INTERNAL_FC_OVERRIDES 否 传入 JSON 对象直接覆盖任意 flag 值,例如 '{"tengu_kairos": true}';仅在 USER_TYPE=ant 的构建中生效
QS_DISABLE_LOCAL_GATES 否 设置后禁用本地 gate 默认值,查询直接回退到调用方默认值
QS_GB_BASE_URL 否 仅 ant 构建使用的内置地址覆盖,优先级低于 CLAUDE_GB_ADAPTER_URL

GrowthBook 缓存与失效策略

机制 说明
内存缓存 进程内 remoteEvalFeatureValues,读取时最先命中
磁盘缓存 ~/.claude.json 的 cachedGrowthBookFeatures 字段,跨进程持久化
周期刷新 外部用户每 6 小时、ant 构建每 20 分钟自动重新拉取(定时器 unref,不阻止进程退出)
初始化超时 首次连接超时 5000 ms,超时后使用磁盘缓存或代码默认值
Auth 变更 登录 / 登出时销毁并重建客户端,并刷新配置

GrowthBook 取值优先级(第一个命中即返回):

读取链
1. CLAUDE_INTERNAL_FC_OVERRIDES 环境变量(JSON 覆盖)
   ↓ 未命中
2. growthBookOverrides 配置(~/.claude.json,仅 ant 构建)
   ↓ 未命中
3. 内存缓存(本次进程从服务器拉取)
   ↓ 未命中
4. 磁盘缓存(~/.claude.json 的 cachedGrowthBookFeatures)
   ↓ 未命中
5. 代码中的 defaultValue 参数

Sentry 环境变量与行为

项 说明
SENTRY_DSN 唯一的启用开关;未设置则所有 Sentry 调用为 no-op
全局关闭 DISABLE_ERROR_REPORTING 让 logError 路径跳过上报(含 Sentry); DISABLE_TELEMETRY 关闭遥测侧;QS_DISABLE_NONESSENTIAL_TRAFFIC 进入 essential-traffic 级别,同样跳过该路径
3P Provider 设置 QS_USE_BEDROCK / QS_USE_VERTEX / QS_USE_FOUNDRY 时 logError 直接返回,不上报
release 取自 MACRO.VERSION,自动附带
environment 构建环境值,缺省回退到 NODE_ENV 或 development
sampleRate 1.0(捕获全部错误事件)
maxBreadcrumbs 20(控制 payload 体积)
性能事务 已关闭(beforeSendTransaction 返回 null),仅上报错误

安全过滤:beforeSend 会剥离 authorization、 x-api-key、cookie、set-cookie 请求头。 忽略错误:ECONNREFUSED / ECONNRESET / ENOTFOUND / ETIMEDOUT(网络不可达)、 AbortError / The user aborted a request(用户取消)、 CancelError(交互式取消)。

常用命令与参数

两个系统都没有独立的 CLI 子命令:GrowthBook 由启动流程中的 initializeGrowthBook() 惰性初始化,Sentry 由 initSentry() 在 src/entrypoints/init.ts 启动时调用。开关与参数全部走环境变量。

项 说明
getFeatureValue_CACHED_MAY_BE_STALE(key, default) 业务代码读取开关值的标准入口,非阻塞;未启用时直接返回默认值
initializeGrowthBook() 初始化客户端并等待就绪;auth 条件变化时重建
refreshGrowthBookFeatures() 轻量刷新:不重建客户端,仅重新拉取并重建内存缓存
initSentry() 初始化 Sentry SDK;SENTRY_DSN 缺失时为 no-op
captureException(error, context?) 手动上报异常,可附加额外上下文
setTag(key, value) / setUser({...}) 设置标签或用户上下文,用于面板分组与归因
closeSentry(timeoutMs?) 优雅退出时刷出队列并关闭客户端(默认 2000 ms)
isSentryInitialized() 检查 Sentry 是否已初始化,可用于条件渲染
*
常用 Feature Key 命名约定

运行时开关统一以 tengu_ 前缀命名(如 tengu_auto_background_agents、tengu_birch_trellis), 名称刻意保持不透明。在 GrowthBook 实例中创建的 Feature Key 必须与代码查询的 key 完全一致; 类型也需匹配(boolean / number / object / string)。

实战示例

指向自建 GrowthBook 实例并覆盖一个开关(ant 构建):

Terminal
CLAUDE_GB_ADAPTER_URL=https://gb.internal.example.com/ \
CLAUDE_GB_ADAPTER_KEY=sdk-abc123 \
CLAUDE_INTERNAL_FC_OVERRIDES='{"tengu_auto_background_agents": true}' \
qsdashi

不使用 GrowthBook(默认行为,读取直接返回代码默认值,零网络请求):

Terminal
qsdashi
# 所有 getFeatureValue_CACHED_MAY_BE_STALE("xxx", defaultValue) 直接返回 defaultValue

启用 Sentry 并同时关闭遥测侧的其余上报:

Terminal
SENTRY_DSN=https://public_key@sentry.example.com/123 \
DISABLE_TELEMETRY=1 \
qsdashi
# Sentry 仍会初始化并上报;Datadog / 1P 事件等遥测被关闭

在项目外彻底关闭两者(不设任何相关环境变量):

Terminal
# 不设置 CLAUDE_GB_ADAPTER_* 与 SENTRY_DSN 即可
qsdashi

常见问题排错

!
设置了适配器 URL 但 GrowthBook 仍未生效

CLAUDE_GB_ADAPTER_URL 与 CLAUDE_GB_ADAPTER_KEY 必须同时设置才启用适配器模式。只设其一会被视为未配置,直接跳过 GrowthBook。

!
开关值没有立刻更新

取值优先读内存缓存,其次是 ~/.claude.json 的 cachedGrowthBookFeatures 磁盘缓存;远程刷新为每 6 小时(外部)/ 20 分钟(ant)。 在 GrowthBook 侧改动后需要等待周期刷新,或重启进程重新拉取。

!
首次连接超时

客户端 init 超时为 5000 ms。超时不会报错中断,而是回退到磁盘缓存或代码默认值。 若实例不可达,检查网络与 CLAUDE_GB_ADAPTER_URL 地址是否正确。

!
Sentry 没有收到任何事件

依次确认:SENTRY_DSN 未设置会导致全部 no-op;设置了 DISABLE_ERROR_REPORTING 或 QS_DISABLE_NONESSENTIAL_TRAFFIC (essential-traffic 级别)会跳过 logError 上报;使用 Bedrock / Vertex / Foundry 时该路径也会直接返回。注意 DISABLE_TELEMETRY 只关闭 Datadog / 1P 遥测, 并不会阻止 Sentry 经 logError 上报。

*
Sentry 与遥测的关系

Sentry 是独立的错误上报通道,不与 GrowthBook 或 1P 事件日志共用开关: GrowthBook 依赖 1P 事件日志(本构建中为 stub,故默认关闭),而 Sentry 只需 SENTRY_DSN 即可工作。两者可分别单独启用,互不影响。