概述

本项目使用 sentry-uniapp 进行错误监控和上报,支持 H5、小程序、APP 多平台。Sentry 会自动捕获未处理的异常,同时提供手动上报接口用于业务错误和异常。

核心特性
  • ✅ 自动捕获全局异常
  • ✅ HTTP 请求错误自动上报
  • ✅ 业务错误码上报
  • ✅ 用户信息关联
  • ✅ 环境开关控制
  • ✅ 多平台支持

依赖安装

项目已安装 Sentry 依赖包:


{ "dependencies": { "sentry-uniapp": "^1.0.12" } }


环境配置

1. 环境变量配置

在 .env 文件中配置 Sentry DSN:


# Sentry DSN(必填,用于错误上报) VITE_SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id # 是否启用 Sentry(可选,默认从 profile 读取) VITE_SENTRY_ENABLE=true

类型定义 (typings/env.d.ts):


/** Sentry DSN */ readonly VITE_SENTRY_DSN?: string /** 是否启用 Sentry */ readonly VITE_SENTRY_ENABLE?: 'true' | 'false'

2. Profile 配置

在 env-conf.ts 中配置各环境的 Sentry 开关:


// 是否启用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 的核心配置文件,提供了初始化、错误捕获、用户信息设置等功能。以下是完整的代码:


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 }

代码说明

  1. isSentryEnabled(): 检查是否启用 Sentry,必须同时满足 profile.SENTRY_ENABLE === true 和 VITE_SENTRY_DSN 已配置

  2. initSentry(): 初始化 Sentry

    • 检查启用开关和 DSN 配置
    • APP 平台需要特殊配置 extraOptions 来禁用某些钩子,避免与 App.onError 冲突
  3. setSentryUser(): 设置或清除 Sentry 用户信息

    • 用于关联错误和用户,便于问题追踪
    • 登出时传入 undefined 清除用户信息
  4. captureException(): 捕获异常

    • 用于真正的异常(网络错误、代码错误等)
    • 支持附加额外上下文信息
  5. captureMessage(): 捕获消息

    • 用于业务逻辑错误(错误码等,不是异常)
    • 支持附加额外上下文信息
  6. 导出 Sentry 对象: 允许在特殊场景下直接使用 Sentry 的原生 API


初始化流程

App.vue 中的初始化

在 src/App.vue 的 onLaunch 钩子中初始化 Sentry:


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 钩子中捕获全局异常:


// 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. 导入函数

import { captureException, captureMessage, setSentryUser } from '@/sentry'

2. 捕获异常

用于捕获真正的异常(如网络错误、代码错误等):


try { // 可能出错的代码 await someAsyncOperation() } catch (error) { captureException(error, { // 可选的额外信息 operation: 'someOperation', userId: '123', }) }

3. 捕获业务错误

用于捕获业务逻辑返回的错误(不是异常,而是业务错误码):


const response = await apiCall() if (!response.succeed) { captureMessage(`业务返回错误码: ${response.code}`, { errorCode: response.code, traceId: response.traceId, url: '/api/endpoint', }) }

4. 设置用户信息

// 设置用户信息 setSentryUser({ id: '123', username: 'john_doe' }) // 清除用户信息(登出时) setSentryUser()


错误上报场景

1. HTTP 请求错误上报

在 src/service/index.ts 中,HTTP 请求拦截器会自动上报错误:

业务错误上报(使用 captureMessage)

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, }) }

使用场景


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)

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, }) }

使用场景


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)

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:


public handleError(errCode: string, errorData?: any): void { switch (errCode) { case 'ACOM10000': this.handlePermissionUpdated() break // 可以添加其他错误码的处理 default: // 未处理的错误码已在 service/index.ts 中统一上报到 Sentry break } }


用户信息关联

自动设置用户信息

在用户登录或获取用户信息后,自动设置 Sentry 用户信息:

1. 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:


const setUserInfo = (val: UserModel) => { userInfo.value = val // 设置 Sentry 用户信息 if (val.userId && val.username) { setSentryUser({ id: val.userId, username: val.username, }) } }

3. 清除用户信息

登出时清除 Sentry 用户信息:


const clearAll = () => { userInfo.value = { ...initState } companyInfo.value = {} realNameInfo.value = {} hasCompanyList.value = false // 清除 Sentry 用户信息 setSentryUser() }


平台差异说明

APP 平台特殊配置

APP 平台(Android/iOS)需要在初始化时禁用某些钩子,避免与 App.onError 冲突:


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()
最佳实践
  1. 异常 vs 业务错误

    • 真正的异常(网络错误、代码错误)使用 captureException
    • 业务逻辑错误(错误码)使用 captureMessage
  2. 用户信息关联

    • 登录后立即设置用户信息
    • 登出时清除用户信息
  3. 额外信息

    • 上报时尽量提供上下文信息(URL、参数、traceId 等)
    • 便于在 Sentry 后台快速定位问题
  4. 环境控制

    • 开发环境可以启用,方便调试
    • 测试环境建议关闭,避免测试数据污染
    • 生产环境必须启用,用于监控线上问题

相关文件清单

  • 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 - 依赖包配置
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐