用户体验监控兼容 Sentry SDK 支持上报以下类型的数据:
自动采集 — 页面加载(包含 Webvitals 指标)、资源请求(Resource)、卡顿(LongTask)、行为事件(Action)。
Custom Event(自定义事件) — 追踪业务流程与关键操作。
Custom Log(自定义日志) — 记录业务日志与关键节点信息。
Exception(自定义异常/错误) — 捕获并上报 JS 异常。
User(用户身份) — 关联用户信息,按用户维度检索分析。
一、SDK 初始化推荐配置
要获得尽可能完整的 RUM 数据,需要在 Sentry.init 时开启以下配置。
原生 JavaScript (Browser) 项目示例
import * as Sentry from "@sentry/browser";
Sentry.init({
dsn: "https://key@<YOUR-ENDPOINT>/0",
// ─── 基础配置 ───
release: "my-web-app@1.2.0",
environment: "production",
// ─── Performance Tracing(性能追踪) ───
tracesSampleRate: 1.0, // 生产环境建议按需调整,例如 0.2
integrations:[
// 自动采集 pageload / navigation / resource / Web Vitals 等
Sentry.browserTracingIntegration(),
],
});Android 项目完整示例 (Kotlin)
import android.app.Application
import io.sentry.android.core.SentryAndroid
import io.sentry.android.core.SentryAndroidOptions
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
SentryAndroid.init(this) { options ->
options.dsn = "https://key@<YOUR-ENDPOINT>/0"
// ─── 基础配置 ───
options.release = "my-android-app@1.2.0"
options.environment = "production"
// ─── Performance Tracing(性能追踪) ───
options.tracesSampleRate = 1.0
}
}
}Android 补充提示: 对于网络请求(Resource 事件),如果您使用的是 OkHttp 或 Retrofit,必须在构建 OkHttpClient 时添加 SentryOkHttpInterceptor(),否则无法自动采集接口请求耗时。
iOS (Swift) 项目完整示例
import UIKit
import Sentry
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
SentrySDK.start { options in
options.dsn = "https://key@<YOUR-ENDPOINT>/0"
// ─── 基础配置 ───
options.environment = "production"
options.releaseName = "my-ios-app@1.2.0"
// ─── Performance Tracing(性能追踪) ───
options.tracesSampleRate = 1.0
}
return true
}
}关键配置项说明
配置项 | 推荐值 | 对应 RUM 数据 | 说明 |
|
| View, Resource, LongTask, Action, Custom Event | 性能追踪采样率,必须设置 > 0 才能采集性能数据。 |
| 启用 | View(pageload/navigation), Resource, LongTask, Web Vitals | 自动创建页面加载和路由跳转的 transaction,采集 FCP/LCP/FID/CLS/INP 等指标。 |
| 版本号字符串 | 所有事件 | 应用版本号,用于版本维度分析和 SourceMap 关联。 |
|
| 所有事件 | 环境标识,用于区分生产/测试环境。 |
自动采集的 RUM 数据总览
开启上述配置后,以下数据会被自动采集,无需额外代码:
RUM 事件类型 | 数据来源 | 说明 |
View |
| 页面加载和路由切换,包含 Web Vitals(FP, FCP, LCP, FID, CLS, INP, TTFB) |
Resource | transaction 内 | XHR/Fetch 请求、静态资源(JS/CSS/图片等)加载 |
LongTask |
或 Vue/React 组件渲染(≥ 50ms) | 主线程阻塞任务 |
Action |
| 用户点击、输入、滚动等交互操作,含 INP |
Application |
| 应用生命周期事件(前台/后台切换等,移动端场景) |
不需要开启的配置
配置项 | 说明 |
| Session Replay 数据当前不落盘,无需开启 |
| Profiling 数据当前不落盘,无需开启 |
| 仅影响 |
二、Custom Event — 自定义事件(手动上报)
适用于追踪业务流程、关键操作的耗时和状态,例如支付流程、表单提交、搜索请求等。
使用方式
通过 Sentry.startSpan 上报,op 固定为 rum.custom:
import * as Sentry from "@sentry/vue"; // 或 @sentry/react、@sentry/browser 等
// 基础用法
Sentry.startSpan(
{
op: "rum.custom",
name: "支付流程",
attributes: {
"custom.group": "payment",
"custom.value": "99.9",
},
},
() => {
// 业务逻辑...
}
);
// 携带自定义业务属性
Sentry.startSpan(
{
op: "rum.custom",
name: "商品搜索",
attributes: {
"custom.group": "search",
"custom.value": "42",
// 以下属性会自动落入 properties,可在控制台查询
"keyword": "蓝牙耳机",
"result_count": 42,
"search_type": "full_text",
},
},
() => {
// 搜索逻辑...
}
);异步场景
如果业务逻辑是异步的,回调函数返回 Promise 即可,SDK 会自动等待完成后计算耗时:
await Sentry.startSpan(
{
op: "rum.custom",
name: "上传文件",
attributes: {
"custom.group": "upload",
"file_type": "image",
"file_size": 1024000,
},
},
async () => {
await uploadFile(file);
}
);字段说明
参数 | 是否必填 | 落盘字段 | 说明 |
| 必填 | — | 固定为 |
| 必填 |
| 事件名称,用于控制台展示和检索 |
| 选填 |
| 事件分组,用于聚合统计(如 |
| 选填 |
| 事件值,用于数值分析(如金额、数量) |
| 选填 |
| 自定义业务属性,支持 string / number / boolean |
自动计算 | — |
| 回调函数执行耗时(毫秒),SDK 自动采集 |
三、Custom Log — 自定义日志(手动上报)
适用于记录业务日志、关键节点信息、非异常的警告消息等。
使用方式
通过 Sentry.captureMessage 上报:
import * as Sentry from "@sentry/vue";
// 基础用法(默认 level 为 "info")
Sentry.captureMessage("用户完成了新手引导流程");
// 指定日志级别
Sentry.captureMessage("支付重试超过最大次数", "warning");
字段说明
参数 | 是否必填 | 落盘字段 | 说明 |
| 必填 |
| 日志内容 |
| 选填 |
| 日志级别,支持 |
四、Exception — 异常/错误上报(手动上报)
适用于捕获运行时异常、业务逻辑错误、Promise 拒绝等场景。落盘为 RUM 的 Exception 事件,包含错误类型、错误消息和完整堆栈信息,并自动进行错误聚合分组。
使用方式
通过 Sentry.captureException 上报:
import * as Sentry from "@sentry/vue";
// 基础用法 — 捕获一个 Error 对象
try {
riskyOperation();
} catch (err) {
Sentry.captureException(err);
}
// 手动构造 Error 上报
Sentry.captureException(new Error("支付接口返回异常状态码"));
// 捕获 Promise 异常
fetchOrder(orderId).catch((err) => {
Sentry.captureException(err);
});
落盘说明
captureException 上报的事件会生成以下 RUM 数据:
落盘模型 | 说明 |
ExceptionModel | 主体错误事件,包含错误类型( |
NodeStore | 存储完整的原始 Sentry Event JSON,用于控制台详情页展示 |
GroupMessage | 错误聚合分组信息,用于错误列表的聚合展示 |
注意事项
始终传入 Error 对象:
captureException(new Error("msg"))比captureException("msg")更好,前者会包含完整堆栈信息。与 captureMessage 的区别:
captureException走 Exception 链路,有堆栈和错误分组;captureMessage走 Custom Log 链路,是轻量日志。不要用 captureMessage 上报错误:错误场景请使用
captureException,以便在控制台获得完整的错误分析能力。
五、User — 用户身份配置
通过 Sentry.setUser 设置当前用户信息后,后续上报的所有事件(Custom Event、Custom Log、Exception 等)都会自动携带用户标识,用于在控制台按用户维度检索和分析。
使用方式
import * as Sentry from "@sentry/vue";
// 用户登录后设置
Sentry.setUser({
id: "user-12345",
username: "张三",
data: {
vip_level: "gold",
department: "engineering",
},
});
// 用户退出后清除
Sentry.setUser(null);
字段说明
Sentry User 字段 | 落盘字段 | 说明 |
|
| 用户唯一标识,推荐设置,用于控制台按用户检索 |
|
| 用户名,用于控制台展示 |
|
| 自定义用户属性(如会员等级、部门等),用于多维分析 |
| — | 当前未落盘,不建议依赖此字段 |
| — | 当前由服务端从 HTTP 请求头自动采集,无需手动设置 |
注意事项
尽早调用
setUser:建议在用户登录完成后立即设置,确保后续事件都能关联到用户。id是最重要的字段:控制台按用户维度检索依赖此字段,建议使用业务系统的用户 ID。data适合放业务属性:如会员等级、用户角色、所属组织等,会以 JSON 格式存储在userTags中。退出时清除用户信息:调用
Sentry.setUser(null)避免事件错误关联到已退出的用户。
六、选择指引
场景 | 推荐方式 | 落盘类型 | 理由 |
追踪某个操作的耗时 |
| Custom Event | 自动采集 duration,适合性能分析 |
记录业务流程的关键节点 |
| Custom Event | 可携带 group/value/自定义属性,适合聚合分析 |
记录一条日志消息 |
| Custom Log | 轻量,带日志级别,适合日志类场景 |
记录非异常的警告或提示 |
| Custom Log | 语义清晰,区别于 captureException |
捕获 JS 异常/运行时错误 |
| Exception | 包含堆栈、错误分组、趋势分析 |
捕获 Promise 异常 |
| Exception | 同上,保留完整调用链 |
捕获 业务逻辑错误(如接口 500) |
| Exception | 有堆栈定位,有聚合分组 |
七、注意事项
op必须为rum.custom:其他 op 值的独立 Span 不会被转换为自定义事件。name建议简洁且可聚合:避免将变量(如用户 ID、订单号)直接写入 name,应放入 attributes。attributes 的 value 类型:支持
string、number、boolean,不支持对象或数组。captureMessage 不是 captureException:如果要上报错误,请使用
Sentry.captureException(new Error("...")),它会走 Exception 链路并包含堆栈信息。captureException 始终传入 Error 对象:
captureException(new Error("msg"))比captureException("msg")更好,前者包含完整堆栈。