可观测性

配置分析、崩溃上报、日志和 tracking 权限。

可观测性由 PostHog analytics、Sentry crash reporting、一层轻量 logger,以及 iOS App Tracking Transparency 权限 helper 组成。每个服务在缺少 key 时都会 no-op。

提供什么

Surface状态说明
AnalyticsProviderIntegrated封装 PostHog;缺少 key 时禁用 capture;手动跟踪 screen;识别已登录用户
track() / useTrack()Integrated带类型的 product analytics events
Feature flagsIntegrateduseFlag()useFlagPayload() 包装 PostHog feature flag hooks
lib/sentry.tsIntegrated初始化 Sentry、navigation tracing、Expo update tags、sample rates,并处理 Expo Go 降级
loggerIntegrated开发环境打印 console;生产环境写 Sentry breadcrumbs 并捕获错误
ATT helperNative-onlyiOS 使用 expo-tracking-transparency;web 返回 granted 的 no-op fallback

PostHog

配置公开 PostHog keys:

EXPO_PUBLIC_POSTHOG_API_KEY=phc_xxxxxxxxxxxxx
EXPO_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
EXPO_PUBLIC_POSTHOG_DISABLED=false
EXPO_PUBLIC_POSTHOG_DEBUG=false

只有存在 key 且 EXPO_PUBLIC_POSTHOG_DISABLED !== "true" 时, isAnalyticsEnabled() 才返回 true。禁用时,track() 只记录 debug skip,不会 capture。

Provider 选项比较克制:

autocapture screens: false
autocapture touches:  false
session replay:       false
lifecycle events:     true
feature flags:        preloaded

ScreenTracker 通过 posthog.screen(pathname, { path, params }) 发送路由变化。AnalyticsIdentity 用 Supabase UUID identify 已登录用户,并在退出登录时 reset PostHog。

类型化 events

AnalyticsEvents 当前定义了:

EventProperties
screen viewedpath,可选 params
onboarding completedslideCount
paywall viewed可选 source
referral invite shared可选 channel
purchase restored可选 source
purchase completedtierperiod

React 组件外使用 track(),组件内使用 useTrack()。新增 event 时先扩展 AnalyticsEvents,这样 payload 会保持类型安全。

Legal ConsentGate 会阻止用户继续使用 app,直到接受当前 legal version。但当前 analytics 实现不会等这个 consent 再挂载 PostHog。如果你需要严格的 analytics consent,请在发布前让 PostHog enablement 依赖 consent 值。

ATT 是另一件事。app/permissions.tsx 通过 lib/tracking-permissions.ts 请求 tracking permission;web 端的 tracking-permissions.web.ts 返回 granted 的 no-op 结果。ATT 权限不能替代你的 analytics consent policy 或隐私披露。

Sentry

配置公开 DSN 和 sample rates:

EXPO_PUBLIC_SENTRY_DSN=https://example@sentry.io/123
EXPO_PUBLIC_SENTRY_DEBUG=false
EXPO_PUBLIC_SENTRY_TRACES_SAMPLE_RATE=0.2
EXPO_PUBLIC_SENTRY_PROFILES_SAMPLE_RATE=0

服务端/CI 值要保持私密:

SENTRY_ORG=
SENTRY_PROJECT=
SENTRY_URL=https://sentry.io/
SENTRY_AUTH_TOKEN=

lib/sentry.ts 在 module load 时调用 Sentry.init()。runtime Sentry environment 来自 Constants.expoConfig.extra.appVariant

development -> development
preview     -> preview
production  -> production

它注册 reactNavigationIntegration,在 Expo Go 中禁用 native frame tracking,在生产环境默认 trace sample rate 为 0.2、非生产为 1,并在可用时标记 Expo update ID、是否 embedded update、update group 和 debug URL。

app/_layout.tsx 注册 navigation container,并导出:

export default Sentry.wrap(RootLayout);

Sourcemaps

脚本是:

pnpm sentry:upload-sourcemaps

它运行 sentry-expo-upload-sourcemaps dist。把 SENTRY_AUTH_TOKEN 放在 EAS secret 或 CI secret 中,不要放进 EXPO_PUBLIC_*eas.json 会按 profile 设置 SENTRY_ENVIRONMENT,但当前 runtime 代码使用 Expo config 中的 variant 作为 Sentry.init({ environment })

Logger

生产代码中优先使用 logger,而不是直接写 console

logger.info("rating.prompt_requested", { reason });
logger.warn("notifications.channels.register_failed", { error });
logger.error("profile.save_failed", error, { userId });

开发环境中它会打印到 console。生产环境中它会添加 Sentry breadcrumb,并捕获传给 logger.error()Error 实例。

隐私表单

商店提交前,要按你的实际使用情况填写:

服务常见披露范围
PostHogAnalytics、diagnostics、产品交互事件、identify 后的账号标识
Sentry崩溃诊断、性能 traces、breadcrumbs、设备和 app metadata
RevenueCat购买历史和订阅状态
Supabase账号、profile、app 数据、上传文件

不使用的服务可以留空 key,或设置明确的 kill switch。App Privacy 和 Data Safety 表单要和你实际发布的 build 保持一致。

相关页面

On this page