Sentry 接入使用文档
📋 目录
概述
本项目使用 sentry-uniapp 进行错误监控和上报,支持 H5、小程序、APP 多平台。Sentry 会自动捕获未处理的异常,同时提供手动上报接口用于业务错误和异常。
核心特性
- ✅ 自动捕获全局异常
- ✅ HTTP 请求错误自动上报
- ✅ 业务错误码上报
- ✅ 用户信息关联
- ✅ 环境开关控制
- ✅ 多平台支持
依赖安装
项目已安装 Sentry 依赖包:
json
{
"dependencies": {
"sentry-uniapp": "^1.0.12"
}
}
环境配置
1. 环境变量配置
在 .env 文件中配置 Sentry DSN:
bash
# Sentry DSN(必填,用于错误上报)
VITE_SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id
# 是否启用 Sentry(可选,默认从 profile 读取)
VITE_SENTRY_ENABLE=true
类型定义 (typings/env.d.ts):
36:39:typings/env.d.ts
/** Sentry DSN */
readonly VITE_SENTRY_DSN?: string
/** 是否启用 Sentry */
readonly VITE_SENTRY_ENABLE?: 'true' | 'false'
2. Profile 配置
在 env-conf.ts 中配置各环境的 Sentry 开关:
15:33:env-conf.ts
// 是否启用Sentry
SENTRY_ENABLE: true,
},
uat: {
DELETE_CONSOLE: false,
SHOW_SOURCEMAP: false,
APP_PROXY_ENABLE: false,
CLIENT_TYPE_BUYER: 'buyer',
CLIENT_TYPE_SELLER: 'seller',
SENTRY_ENABLE: false,
},
production: {
DELETE_CONSOLE: false,
SHOW_SOURCEMAP: false,
APP_PROXY_ENABLE: false,
CLIENT_TYPE_BUYER: 'buyer',
CLIENT_TYPE_SELLER: 'seller',
SENTRY_ENABLE: true,
},
配置说明:
development: 开发环境,默认启用uat: 测试环境,默认关闭production: 生产环境,默认启用
核心配置
Sentry 核心文件 (src/sentry.ts)
这是 Sentry 的核心配置文件,提供了初始化、错误捕获、用户信息设置等功能。以下是完整的代码:
typescript
import * as Sentry from 'sentry-uniapp'
import { profile } from '@/profile'
/**
* 检查是否启用 Sentry
*/
function isSentryEnabled(): boolean {
const { VITE_SENTRY_DSN } = import.meta.env
// 必须同时满足:profile 中启用开关为 true 且 DSN 已配置
return profile.SENTRY_ENABLE && !!VITE_SENTRY_DSN
}
/**
* 初始化 Sentry
* 在 App.vue 的 onLaunch 中调用
*/
export function initSentry() {
const { VITE_SENTRY_DSN } = import.meta.env
// 检查是否启用
if (!profile.SENTRY_ENABLE) {
return
}
// 检查 DSN 是否配置
if (!VITE_SENTRY_DSN) {
console.warn('[Sentry] 已启用但 DSN 未配置,Sentry 初始化失败')
return
}
const isAppPlatform =
String(__UNI_PLATFORM__) === 'app' || String(__UNI_PLATFORM__) === 'app-harmony'
Sentry.init({
dsn: VITE_SENTRY_DSN,
// extraOptions 主要是解决平台差异问题的
// 非 APP 平台,可以不使用
extraOptions: isAppPlatform
? {
onmemorywarning: false,
onerror: false,
}
: undefined,
})
}
/**
* 设置 Sentry 用户信息
* 保留此函数,因为 src/stores/user.ts 中需要使用
*/
export function setSentryUser(userInfo?: { id?: string; username?: string }) {
if (!isSentryEnabled()) return
if (userInfo?.id && userInfo?.username) {
Sentry.configureScope(scope => {
scope.setUser({
id: String(userInfo.id), // 确保 id 是字符串
username: userInfo.username,
})
})
} else {
Sentry.configureScope(scope => {
scope.setUser(null)
})
}
}
/**
* 捕获异常
* 在 App.vue 的 onError 中调用
*/
export function captureException(error: unknown, extra?: Record<string, unknown>) {
if (!isSentryEnabled()) return
// 使用 withScope 确保额外信息能够正确附加
Sentry.withScope(scope => {
if (extra) {
Object.keys(extra).forEach(key => {
scope.setExtra(key, extra[key])
})
}
Sentry.captureException(error)
})
}
/**
* 捕获消息
*/
export function captureMessage(message: string, extra?: Record<string, unknown>) {
if (!isSentryEnabled()) return
// 使用 withScope 确保额外信息(包括 traceId)能够正确附加
Sentry.withScope(scope => {
if (extra) {
console.log('extra', extra)
Object.keys(extra).forEach(key => {
scope.setExtra(key, extra[key])
})
}
Sentry.captureMessage(message)
})
}
// 导出 Sentry 对象,以便在需要时直接使用
export { Sentry }
代码说明:
-
isSentryEnabled(): 检查是否启用 Sentry,必须同时满足profile.SENTRY_ENABLE === true和VITE_SENTRY_DSN已配置 -
initSentry(): 初始化 Sentry- 检查启用开关和 DSN 配置
- APP 平台需要特殊配置
extraOptions来禁用某些钩子,避免与App.onError冲突
-
setSentryUser(): 设置或清除 Sentry 用户信息- 用于关联错误和用户,便于问题追踪
- 登出时传入
undefined清除用户信息
-
captureException(): 捕获异常- 用于真正的异常(网络错误、代码错误等)
- 支持附加额外上下文信息
-
captureMessage(): 捕获消息- 用于业务逻辑错误(错误码等,不是异常)
- 支持附加额外上下文信息
-
导出 Sentry 对象: 允许在特殊场景下直接使用 Sentry 的原生 API
初始化流程
App.vue 中的初始化
在 src/App.vue 的 onLaunch 钩子中初始化 Sentry:
87:111:src/App.vue
onLaunch(() => {
console.log('App Launch')
// 初始化 Sentry
initSentry()
// 安全初始化埋点SDK(内部会等待 App 实例准备好)
safeInitTrack()
// 延迟检查和测试(给足够时间让埋点初始化完成)
setTimeout(() => {
if (checkTrackInit()) {
// 开发环境下测试埋点
if (import.meta.env.MODE === 'dev') {
testTrack()
}
}
// 设置 Sentry 用户信息
const userStore = useUserStore()
const { userId, username } = userStore.userInfo || {}
if (userId && username) {
setSentryUser({ id: userId, username })
}
}, 3500) // 增加到 3.5 秒,确保 waitForAppReady 完成
全局错误捕获
在 src/App.vue 的 onError 钩子中捕获全局异常:
146:155:src/App.vue
// sentry-uniapp 内部是通过 uni.onError 钩子函数捕获错误的
// 但目前 uni.onError 暂不支持 App (android / ios),各平台支持情况参考:
// https://uniapp.dcloud.net.cn/api/application.html#onerror
//
// 通用方案:
// 可用 App.onError 自己处理,但需要先禁用 sentry 里的捕获
// 方法在 sentry.init 参数里加上 extraOptions: { onerror: false }
onError((error: unknown) => {
captureException(error)
})
注意:
sentry-uniapp内部通过uni.onError钩子捕获错误- 但
uni.onError暂不支持 APP 平台(Android/iOS) - APP 平台需要在
sentry.init中配置extraOptions: { onerror: false },然后使用App.onError手动捕获
使用方式
1. 导入函数
typescript
import { captureException, captureMessage, setSentryUser } from '@/sentry'
2. 捕获异常
用于捕获真正的异常(如网络错误、代码错误等):
typescript
try {
// 可能出错的代码
await someAsyncOperation()
} catch (error) {
captureException(error, {
// 可选的额外信息
operation: 'someOperation',
userId: '123',
})
}
3. 捕获业务错误
用于捕获业务逻辑返回的错误(不是异常,而是业务错误码):
typescript
const response = await apiCall()
if (!response.succeed) {
captureMessage(`业务返回错误码: ${response.code}`, {
errorCode: response.code,
traceId: response.traceId,
url: '/api/endpoint',
})
}
4. 设置用户信息
typescript
// 设置用户信息
setSentryUser({ id: '123', username: 'john_doe' })
// 清除用户信息(登出时)
setSentryUser()
错误上报场景
1. HTTP 请求错误上报
在 src/service/index.ts 中,HTTP 请求拦截器会自动上报错误:
业务错误上报(使用 captureMessage)
14:25:src/service/index.ts
function reportBusinessErrorToSentry(
message: string,
requestOptions: CustomRequestOptions,
extra?: Record<string, unknown>,
): void {
captureMessage(message, {
url: requestOptions.url,
method: requestOptions.method || 'GET',
requestParams: requestOptions.data || requestOptions.query || {},
...extra,
})
}
使用场景:
48:55:src/service/index.ts
function handleBusinessError<T>(data: BaseRes<T>, requestOptions: CustomRequestOptions): boolean {
globalErrorMonitor.handleError(data.code, data)
// 业务错误使用 captureMessage(不是异常,是业务逻辑返回的错误)
reportBusinessErrorToSentry(`业务返回错误码: ${data.code}`, requestOptions, {
errorCode: data.code,
traceId: data.traceId,
errorData: data,
})
HTTP 错误上报(使用 captureException)
30:42:src/service/index.ts
function reportExceptionToSentry(
message: string,
requestOptions: CustomRequestOptions,
extra?: Record<string, unknown>,
): void {
const error = new Error(message)
captureException(error, {
url: requestOptions.url,
method: requestOptions.method || 'GET',
requestParams: requestOptions.data || requestOptions.query || {},
...extra,
})
}
使用场景:
75:85:src/service/index.ts
function handleHttpError<T>(
statusCode: number,
data: BaseRes<T>,
requestOptions: CustomRequestOptions,
): void {
const message = data.message || (statusCode === 401 ? '未授权' : '请求错误')
// HTTP 错误使用 captureException(是真正的异常)
reportExceptionToSentry(`HTTP ${statusCode}: ${message}`, requestOptions, {
statusCode,
errorData: data,
})
网络错误上报(使用 captureException)
95:100:src/service/index.ts
function handleNetworkError<T>(err: unknown, requestOptions: CustomRequestOptions): BaseRes<T> {
uni.showToast({ icon: 'none', title: '网络错误,换个网络试试' })
const errorMessage = typeof err === 'string' ? err : JSON.stringify(err)
// 网络错误使用 captureException(是真正的异常)
reportExceptionToSentry(`网络请求失败: ${errorMessage}`, requestOptions, { errorData: err })
2. 全局错误监控
在 src/utils/globalErrorMonitor.ts 中,未处理的错误码会统一上报到 Sentry:
28:37:src/utils/globalErrorMonitor.ts
public handleError(errCode: string, errorData?: any): void {
switch (errCode) {
case 'ACOM10000':
this.handlePermissionUpdated()
break
// 可以添加其他错误码的处理
default:
// 未处理的错误码已在 service/index.ts 中统一上报到 Sentry
break
}
}
用户信息关联
自动设置用户信息
在用户登录或获取用户信息后,自动设置 Sentry 用户信息:
1. App.vue 中初始化时设置
105:110:src/App.vue
// 设置 Sentry 用户信息
const userStore = useUserStore()
const { userId, username } = userStore.userInfo || {}
if (userId && username) {
setSentryUser({ id: userId, username })
}
2. User Store 中设置
在 src/stores/user.ts 中,设置用户信息时自动关联 Sentry:
23:32:src/stores/user.ts
const setUserInfo = (val: UserModel) => {
userInfo.value = val
// 设置 Sentry 用户信息
if (val.userId && val.username) {
setSentryUser({
id: val.userId,
username: val.username,
})
}
}
3. 清除用户信息
登出时清除 Sentry 用户信息:
44:51:src/stores/user.ts
const clearAll = () => {
userInfo.value = { ...initState }
companyInfo.value = {}
realNameInfo.value = {}
hasCompanyList.value = false
// 清除 Sentry 用户信息
setSentryUser()
}
平台差异说明
APP 平台特殊配置
APP 平台(Android/iOS)需要在初始化时禁用某些钩子,避免与 App.onError 冲突:
31:44:src/sentry.ts
const isAppPlatform =
String(__UNI_PLATFORM__) === 'app' || String(__UNI_PLATFORM__) === 'app-harmony'
Sentry.init({
dsn: VITE_SENTRY_DSN,
// extraOptions 主要是解决平台差异问题的
// 非 APP 平台,可以不使用
extraOptions: isAppPlatform
? {
onmemorywarning: false,
onerror: false,
}
: undefined,
})
原因:
uni.onError在 APP 平台不支持- 需要在
App.onError中手动捕获错误 - 因此需要禁用 Sentry 内部的
onerror钩子
平台支持情况
参考 uni-app 官方文档:
- ✅ H5: 支持
uni.onError - ✅ 小程序: 支持
uni.onError - ❌ APP: 不支持
uni.onError,需要使用App.onError
总结
配置检查清单
- 在
.env文件中配置VITE_SENTRY_DSN - 在
env-conf.ts中配置各环境的SENTRY_ENABLE - 确保
src/App.vue中调用了initSentry() - 确保
src/App.vue中配置了onError钩子 - 确保用户登录后调用了
setSentryUser()
最佳实践
-
异常 vs 业务错误:
- 真正的异常(网络错误、代码错误)使用
captureException - 业务逻辑错误(错误码)使用
captureMessage
- 真正的异常(网络错误、代码错误)使用
-
用户信息关联:
- 登录后立即设置用户信息
- 登出时清除用户信息
-
额外信息:
- 上报时尽量提供上下文信息(URL、参数、traceId 等)
- 便于在 Sentry 后台快速定位问题
-
环境控制:
- 开发环境可以启用,方便调试
- 测试环境建议关闭,避免测试数据污染
- 生产环境必须启用,用于监控线上问题
相关文件清单
src/sentry.ts- Sentry 核心配置和工具函数src/App.vue- Sentry 初始化和全局错误捕获src/service/index.ts- HTTP 请求错误上报src/stores/user.ts- 用户信息关联env-conf.ts- 环境配置(Sentry 开关)typings/env.d.ts- 环境变量类型定义package.json- 依赖包配置
文档更新时间: 2025-01-24