Nuxt.js项目接入Sentry

1,525 阅读6分钟

Sentry简介

Sentry 是一个流行的错误监控平台,帮助开发者分析,修复问题,优化代码的性能。可以进行错误捕获,问题追踪,并提供问题详情,适用于多个平台,多种语言

sentry后台

  1. sentry默认是纯英文界面,左上角用户 > User settings > Account Details 修改中文,选择Simplified Chinese 即可;一并把时区修改为东八区;修改后刷新网页即可显示中文 提示:尽量第一次就把时区更改,否则下次再进行修改有可能一直修改失败(我就是这样)

    image.png
  2. 项目 > 右上角创建项目,选择一个平台; 官网的Platforms选项中是没有nuxt的,所以Platforms选择vue,其实配置上是一样的,配置文件不同而已(vue.config.js/nuxt.config.js

  3. 底部信息按实际填即可,项目名字即为实际项目名, 点击创建后,会自动跳转[接入文档指引]

    image.png

sentry接入

  1. 安装依赖:npm install --save @sentry/vue @sentry/tracing

  2. plugins目录新增sentry插件,记得nuxt.config.js中引入该插件

    image.png
  • dsn:项目唯一标识,由 协议+秘钥+服务器地址+项目编号组成; 当在Sentry平台新建一个项目后,Sentry会自动为该project分配一个dsn,dsn用于告诉Sentry将event发送到哪里,如果不设置dsn,Sentry也不会发送event;

    dsn遵从下面的格式

    {PROTOCOL}://{PUBLIC_KEY}:{SECRET_KEY}@{HOST}{PATH}/{PROJECT_ID}

    dsn查看步骤:点进你的的项目→Settings→ 客户端密钥(DSN)

    注意:这里有个坑,我排查了好久😭

    一般,sentry生成的dsn是这样的: http://bb8650f2e5ec5ba7c67930e73a68c9@10.1.10.211:9000/6

    即协议是http,服务器地址是ip地址,这在本地开发可能没问题,但是部署后就可能接口调不通; 所以根据需要把http换成https,ip改成域名;如下: https://bb8650f2e5ec5ba7c67930e73a68c9@sentry.baidu.com/6

  • environment:环境变量

详细配置参考官网configuration

  1. 写个bug测试一下

    handleTest() {
        const a = '11'
        a.forEach()
        console.log(g.f)
    },
    
    image.png image.png

    点进去就可看到详细信息 But 压缩混淆之后的代码就导致:即使代码报错了,我们也只能看到错误信息,还是非常难定位到具体是哪行代码出现的错误,如上图; 所以我们如果要定位到问题所在还需要上传sourcemap文件。

上传sourceMap

  1. 安装SentryWebpackPlugin插件
    npm install --save-dev @sentry/webpack-plugin
    
    @sentry/webpack-plugin是针对webpack项目,如果是vite项目使用vite-plugin-sentry插件
  2. 在nuxt.config.js文件的 build 参数添加
    build: {
        extend(config, { isClient, isDev }) {
            if (isClient && !isDev) {
                config.devtool = 'source-map'
            }
        },
        plugins: [
            new SentryWebpackPlugin({
                include: '.nuxt/dist/client',
                urlPrefix: '~/home/_nuxt/', // 上传sourceMaps文件的前缀
                ignore: ['node_modules', 'webpack.config.js'],
                project: 'demo',
                configFile: process.env.VUE_APP_TITLE === 'production' ? 
                'sentry.properties' : 'sentry.test.properties', // 相当于.sentryclirc配置文件
                cleanArtifacts: true // 上传前清除原工件
            })
        ]
    }
    
  • sentry.test.properties文件

    # 组织名称
    defaults.org=font-end
    # sentry服务器的地址
    defaults.url=https://sentry.dev.test.com
    # 上传sourceMaps要用到的token
    auth.token=8f9ca900719b4eedea68ed82726ddcee06d2c8a105c26e8b5087069ebc7b1e
    
  • sentry.properties文件

    # 组织名称
    defaults.org=font-end
    # sentry服务器的地址
    defaults.url=https://sentry.test.com
    # 上传sourceMaps要用到的token
    auth.token=8f9ca900719b4eed8ea8ed82726ddce006d2c8a105c4268b508069ebc7b1e
    

    以上配置都可在.sentryclirc文件中配置,sentry会自动检测并使用.sentryclirc文件中的配置信息 其中必填属性:

  • org:组织名字

    image.png
  • project:生成sentry sdk的时候建立的名字,项目面板查看

  • url:sentry的后台地址(如果是私有部署的,则是自己的地址,例sentry.test.com)

  • auth.token:token为API令牌,不是安全令牌;查找:左上角用户 > 用户设置 > 授权令牌;第一次需要点击右上角创建

    image.png
  • include:指定路径让sentry-cli来检测有没有.map与.js文件,如果有就会上传到sentry

非必填属性:

  • urlPrefix:上传sourceMaps文件的前缀,若不传,则默认是根目录即:/ 注意: 填写的路径要和线上的url资源的相对路径一致 比如: 我的线上资源是经过nginx代理了一层,路径是:www.test.com/home/_nuxt/… 那么我此处填写的是:'~/home/_nuxt/'

  • ignore:忽略文件夹或文件不要被检测。 一般都会将node_moudules与webpack.config.js忽略掉。

  • cleanArtifacts:每次先清除已经存在的文件,再上传

  • configFile:用来替代.sentryclirc文件

tips:出现一下任何一点,都可能会出现map文件上传成功,但是报错定位依然失败的情况。

  1. 插件方法SentryWebpackPlugin中设置的release要和Sentry.init中的保持一致;也可以两个都不设置,sentry会生成哈希值,默认帮我们保持一致
  2. urlPrefix填写的路径要一定和线上的url资源的相对路径一致

还有一点:只需在生产环境(线上环境)上传sourceMap 开发环境上传sourceMap文件过于频繁,sentry会报错


ok,忙活了那么久,又到了验证的时候!

  1. 同样,写一个bug;

  2. 执行打包,上传sourceMap,验证是否上传成功:找到自己项目>点击设置>source Map,如下图

    image.png

    然后去问题模块,找到错误信息,点进详情; 可以看到,已经显示了具体位置; sourcemap上传到sentry后,sentry会通过反解sourcemap,通过行列信息映射到源文件上;

    image.png

Sentry面板介绍

image.png image.png image.png

面包屑:还原出错误发生时,用户的关键操作路径,包括点击事件,发送请求,console log 等。 更精准的还原错误触发场景。通过全局监听console,xhr,UI等事件,SetTimeout 等方式实现

image.png

分别是错误页面,UA,用户,浏览器,设备等信息;

根据业务自定义错误详情面板

sentry 源码内有以下方法可调用:

image.png

写几个例子:

  1. 主动上报错误 有时候sentry认为这不是一个错误,但开发者认为是,此时可以主动上报一个错误
    this.$sentry.captureException(new Error('错误'));
    

2.captureMessage自定义上报信息 以我项目为例,我把接口错误区分出http错误(400或者500等)和接口业务报错

```js
// http核心上报方法
export const reportCore = (opts) => {
    if (!isOpenSentry) return
    Sentry.withScope(function (scope) {
        scope.setLevel('error')
        Sentry.captureMessage(`${opts.message}—${opts.url}`, {
            contexts: {
                message: opts
            }
        })
    })
}

// 处理http错误信息
export const reportHttpInfoHandle = (error) => {
    const res = error.response || error
    return {
        title: '上报信息【HTTP】',
        url: res.config.url,
        data: res.config.data || res.config.params || '',
        method: res.config.method,
        status: res.status,
        statusText: res.statusText,
        responseData: JSON.stringify(res.data),
        message: res.message || res.data.error_msg || res.data,
        time: releaseTime(true)
    }
}

// 网络报错信息上报
export const reportHttp = (error) => reportCore(reportHttpInfoHandle(error))

// 接口业务错误信息上报
export const reportHttpBusiness = (error) => {
    const opts = {
        ...reportHttpInfoHandle(error),
        title: '上报信息【API业务错误】'
    }
    reportCore(opts)
}

// 获取当前时间
function releaseTime(flag = false) {
    const now = new Date()
    const fmt = (v) => (v < 10 ? `0${v}` : v)
    const date = `${now.getFullYear()}-${fmt(now.getMonth() + 1)}-${fmt(now.getDate())}`
    if (!flag) return date
    const time = `${fmt(now.getHours())}:${fmt(now.getMinutes())}:${fmt(now.getSeconds())}`
    return `${date} ${time}`
}
```

上报后的效果

image.png

3.setLevel 为上报事件设置级别;可用的值有: fatal/critical/error/warning/log/info/debug/

每一个上报事件都有级别,默认是info,颜色是蓝色;如下图

image.png

为了让它看上去更重要,更醒目,可以通过setLevel更改,提醒色就会变成更醒目的橘黄色,如下图

image.png
// http核心上报方法
export const reportCore = (opts) => {
    if (!isOpenSentry) return
        Sentry.withScope(function (scope) {
            scope.setLevel('error')
            Sentry.captureMessage(`${opts.message}${opts.url}`, {
                contexts: {
                message: opts
            }
        })
    })
}
  1. 为错误信息增加’面包屑‘ breadCrumbs里还原了错误发生时用户的关键操作路径,包括点击事件,xhr等,还有 Expection等,这里可以丰富breadCrumbs
    Sentry.addBreadcrumb({
        message: '自定义信息',
        // ...
    });
    
  2. 设置用户信息
    Sentry.configureScope((scope) => {
        scope.setUser({
            user_account: '110',
            user_name: '章三',
            user_mobile: '110'
        })
        Sentry.captureException(err)
    })
    

效果:

image.png

上面的写法会把用户信息放置在 User 栏里,如果也想让tag里有,则可:

Sentry.configureScope((scope) => {
    scope.setTag('user_account', '110')
    scope.setTag('user_name', '章三')
    scope.setTag('user_mobile', '110')
    Sentry.captureException(err)
})

效果:

image.png