关于javascript:基于Sentry搭建前端异常监控系统

42次阅读

共计 7696 个字符,预计需要花费 20 分钟才能阅读完成。

背景

尽管在咱们的我的项目上线前会有很多的测试流程,然而测试流程必定无奈保障 100% 笼罩所有操作场景,在用户的应用过程中仍会有一些问题裸露进去。
但当线上用户呈现问题,咱们须要收到用户的一个反馈,能力去定位解决,这样会导致咱们的问题解决不够及时。
并且有些疑难杂症,咱们无奈复现定位,这时候咱们须要得悉用户的环境、操作等信息,以便于对问题进行排查。
基于以上三点思考,我认为在大部分我的项目中都须要接入一个异样监控零碎,来实现收集异样、收集日志信息、及时正告、展现统计信息等性能。

为什么抉择 Sentry?

  • 收费
  • Sentry 可间接应用也可自行搭建
  • 兼容性强,根本不受语言限度,搭建一套零碎可用于多个我的项目。

Sentry 简介

Sentry’s application monitoring platform helps every developer
diagnose, fix, and optimize the performance of their code.

Sentry 的应用程序监督平台可帮忙每个开发人员诊断,修复和优化其代码的性能。

Sentry 部署及应用

Sentry 可间接应用也可自行搭建,上面将解说 Sentry 的搭建过程。想要间接体验的能够跳过间接戳官网进行体验。

官网提供装置形式是应用 Docker 和 Docker Compose 以及基于 bash 的装置和降级脚本。

环境要求

  • Docker 19.03.6+
  • Compose 1.24.1+
  • 4 CPU Cores
  • 8 GB RAM
  • 20 GB Free Disk Space
  • Python 3

这里就不对环境的配置进行具体阐明,想本人搭建的同学能够参考下以下文章。

  • yum 形式装置降级 docker
  • 新装的 CentOS 7 装置 python3

部署步骤

  1. 从 github 上获取 Sentry 最新代码。
git clone https://github.com/getsentry/onpremise.git
  1. 进入 onpremise,运行 install.sh 脚本。
cd onpremise
./install.sh
  1. 运行 docker-compose up -d 以启动 Sentry。

依照默认配置构建后,Sentry 默认绑定 9000 端口,拜访 http://127.0.0.1:9000 即可进入登录页面。

  1. 关上页面填写信息后即可进入 Sentry 零碎

  1. 主动发送正告邮件配置,能够从上图配置,也能够从配置文件配置,上面为通过 config.yml 配置教程。
    关上 onpremise/sentry 下的 config.yml 文件,批改 Mail Server 配置内容。
  • mail.backend:邮件发送形式;
  • mail.host: 邮件发送域名,应用的哪个邮箱能够去该邮箱文档中找到 smtp 发送域名;
  • mail.port: 邮件发送的端口号;
  • mail.username:用于 smtp 邮箱的账号;
  • mail.password:用于 smtp 邮箱的明码;
  • mail.use-tls:是否应用 tls 平安协定,这里填写 true 或 false,和 use-ssl 配置互斥;
  • mail.use-ssl:是否应用 ssl 平安协定,这里填写 true 或 false,和 use-tls 配置互斥;
  • mail.from:收到邮件时的发送人名称;
  1. 通过配置文件批改邮件服务后,须要运行 docker-compose up -d  更新 Sentry,如果更新失败则须要敞开 docker-compose 后从新运行。
docker-compose down
docker-compose build
docker-compose up -d

重启后可通过 头像 -> admin -> mail 进入 mail 配置页,点击发送测试邮件来检测是否配置胜利。

Sentry 设置通过 HTTPS 拜访

有没有发现下面 Sentry 的启动地址还有 DSN 地址都是 http,当初要给 Sentry 配置 ssl 让咱们能通过 https 应用。

首先要批改 onpremise/sentry/config.yml system.url-prefix 配置,将其设置为咱们拜访的 Sentry 域名。url-prefix 组成了我的项目的 DSN 地址,肯定要保障格局正确。

system.url-prefix: 'https://sentry.xxxxx.com:60000'

而后是 onpremise/sentry/sentry.conf.py 文件下的 SSL/TLS 配置,将原来正文的局部全副关上。

批改完后同样要将 docker-compose 关掉重建。

docker-compose down
docker-compose build
docker-compose up -d

下面的配置只是让 Sentry 容许通过 SSL 代理,上面咱们须要在服务器内搭建一个 nginx 用来转发 https 协定内容,搭建的过程不多说,百度或者求教运维大大。上面是我的 nginx 配置,配好 nginx 并重启后就算功败垂成。咱们的 Sentry 终于能够通过 https 拜访了!

server {
    # 配置监听端口
    listen       60000 ssl http2 default_server;
    listen       [::]:60000 ssl http2 default_server;

    # 域名
    server_name  sentry.xxxxx.cn;

    # nginx 默认根目录
    root         /usr/share/nginx/html;

    # 加载其余配置文件,这里是 nginx 默认配置,能够不须要
    include /etc/nginx/default.d/*.conf;

    # ssl 设置
    ssl on;
    # ssl 证书地址
    ssl_certificate     /etc/nginx/sslcert/server.crt;
    # ssl 密钥地址
    ssl_certificate_key /etc/nginx/sslcert/server.key;
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;


    client_max_body_size 200M;
    client_body_buffer_size 1024k;

    # 这一段是最重要的,将域名代理到本机 http://localhost:9000 服务上,对应的就是 docker 内的 sentry 服务
    location / {proxy_pass http://localhost:9000;}

    gzip  on;
    gzip_http_version 1.1;
    gzip_vary on;
    gzip_comp_level 9;
    gzip_proxied any;
    gzip_types text/plain  text/css application/json  application/x-javascript text/xml application/xml application/xml+rss text/javascript application/x-shockwave-flash image/png image/x-icon image/gif image/jpeg;
    gzip_buffers 16 8k;

    error_page 404 /404.html;
        location = /404.html { }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {}}

Sentry 接入实例

通过下面的过程 Sentry 零碎就搭建好了,拜访配置的地址即可进入 Sentry 零碎。没有搭建的敌人们,也能够间接通过官网体验上面接入我的项目的过程。

创立我的项目

进入零碎后点右上角的 New Project  创立我的项目。

这里以 React 我的项目为例,建设一个 React 我的项目,依照页面提醒即可在我的项目中注册 Sentry,对系我的项目执行中呈现的异样进行捕获。

配置

Sentry 配置应在应用程序的生命周期中尽早进行。实现此操作后,Sentry 的 JavaScript SDK 会捕捉所有未解决的异样和事务。init 参数详解:

Sentry.init({
  // Sentry 我的项目的 dsn,可从我的项目设置中获取
  dsn: "https://xxxxxx@161.xxx.xxx.xxx:9000/2",
  // 初始参数配置内容
  integrations: [new Integrations.BrowserTracing()],
  // 触发异样后发送给 Sentry 的概率
  tracesSampleRate: 1.0,
  // 管制应捕捉的面包屑 (行为栈) 的总量
  maxBreadcrumbs: 20,
  // 规定上下文数据结构的深度,默认为 3
  normalizeDepth: 100,
  // 版本信息
  release: "common@1.0.0",
  // 环境信息
  environment: process.env.NODE_ENV,
  // 钩子函数,在每次发送 event 前触发
  beforeSend(event) {
    // 网页利用刷新后设置的变量会隐没,所以我抉择在 beforeSend 触发时插入用户信息
    event.user = {userNick: "xiaohu",};
    return event;
  },
});

设置变量

在 Sentry 中,能够应用 set + tagsextracontextsuserlevelfingerprint 模式,设置变量。上面将简略介绍几种形式,详情应用办法可见文档。

通过 setUser 设置全局变量用户信息示例(不倡议应用)

捕获异样还须要采集用户信息,在用户登录后须要通过 setUser 设置一下用户信息全局变量,如下所示。留神,通过这种形式设置的全局变量在页面刷新后会隐没。设置用户信息代码:

Sentry.setUser({
    tenant: {
        code: 12345,
        name: '测试公司',
        _id: 12345
    },
    orgAccount: {
        _id: 54321,
        orgName: '是机构啦'
    },
    user: {
        _id: '8910JQ',
        loginName: '测试人员小 Q'
    } 
})

设置全局变量后触发的 issue 中,可看到上传的用户数据。

通过 beforeSnd 插入用户信息

通过 Sentry 机制设置的全局变量在页面刷新后会隐没,这边我倡议通过 beforeSend  函数,批改 event 中的数据来插入须要的全局变量。

Sentry.init({
    ...,
       // 钩子函数,在每次发送 event 前触发
    beforeSend(event) {
        // 在这里可依据业务状况发送用户信息
        event.user = {userNick: 'xiaohu'};
        return event;
    }
});

设置全局变量

// 以下是 Sentry 定义的全局变量,能够间接应用 Sentry api 设置
Sentry.setUser(object);
Sentry.tags(object);
Sentry.extra(object);
Sentry.level(object);
Sentry.fingerprint(object);

// 通过 setContext,设置 key 值,可自定义随事件传递的变量名
Sentry.setContext(key, context);

设置局部变量

captureException 是我罕用的一种设置局部变量并上传报错的形式,Sentry.captureException(err[, obj]) 第一个参数为抛出的异样,第二个参数可附加错误信息。
第二个参数为对象,key 值可为 tagsextracontextsuserlevelfingerprint 这 6 种。

Sentry.captureException(error, {
  contexts: {
    message: {
      a: 1,
      b: {b: 1},
    },
  },
});

设置局部变量网络报错信息示例

依据目前前端框架所用的 axios,对网络申请出错的部分数据进行收集,代码示例:

Sentry.captureException(error, {
  contexts: {
    message: {
      url: error.response.config.baseURL + error.response.config.url,
      data: error.response.config.data,
      method: error.response.config.method,
      status: error.response.status,
      statusText: error.response.statusText,
      responseData: JSON.stringify(error.response.data),
    },
  },
});

革除全局变量

在用户退出登录后须要革除该用户的用户信息,有以下两种形式。

  1. 通过设置为空,能够革除设置过的数据。
Sentry.setUser();
  1. 通过 scope.clear()  革除全局变量。
Sentry.configureScope((scope) => scope.clear()); // 革除所有全局变量
Sentry.configureScope((scope) => scope.setUser(null)); // 革除 user 变量

上传日志信息

有时咱们不仅仅要收集异样信息,还须要在页面中打 log 来收集页面运行数据,这时能够用 Sentry.captureMessage(err[, obj]) api,进行传输日志。应用办法与 captureException 统一,倡议将 level 设置为 Info,便于与异样辨别开来,防止触发咱们设置的异样警报。

Sentry.captureMessage("Something went fundamentally wrong", {
  contexts: {
    text: {hahah: 22,},
  },
  level: Sentry.Severity.Info,
});

上传 sourceMap

Sentry 可将前端我的项目打包后的 SourceMap 上传,不便咱们查看异样所在的代码地位。
Sentry 集成 sourcemap

卸载 sentry

须要卸载可参考以下链接。
如何卸载 Sentry?

触发一个异样看看

onClick={() => {let a = {};
    console.log(a.b.c);
}}

在这里我制作了一个异样代码,点击后大家可想而知会呈现一个 js error,如下图。

在 network 中咱们能够看到一条申请,Sentry 就是通过这样的形式上传谬误的。

而后转到 Sentry 零碎页面上,能够看到 Issues 面板中多了一条信息:

点击进入后能够看到对于这条异样的详细信息。

能够看到,详情里收集了大量的异样相干数据,如设施、浏览器版本、ip 地址、error 数据、用户操作栈等数据。但光有这些数据是不够的,原始的上传信息有时也不足以剖析问题,很多时候咱们须要依据业务场景定制所采集的数据。上面咱们将从捕获场景和采集内容这两方面进行剖析。

异样信息捕获场景及采集内容

捕获场景

针对前端常见业务场景,总结了以下几个场景须要收集业务报错信息。

  1. 接口谬误
  2. 网络谬误
  3. js error 报错
  4. 次要业务流程异样状态
  5. iframe/webview 外部谬误

以上异样如果触发了 js error 或者 Promise.reject 并且没有被抛出,会被 Sentry 主动捕捉到,如果没有主动触发可手动 new Error 或 Promise.reject(error) 抛出异样,即可被 Sentry 收集。或者应用 captureMessage Api 收集运行日志。

采集内容

只管 Sentry SDK 会捕捉所有未解决的异样和事务汇报至零碎上,并且会记录产生异样的页面及设施信息。然而有这些信息是远远不够的,还须要额定的业务信息,用于更好的区别定位问题。上面是我对上报异样所须要收集的内容进行总结。

异样信息:抛出异样的 error 信息,Sentry 会主动捕获。

用户信息:用户的信息(登录名、id、level 等),所属机构信息,所属公司信息。

行为信息:用户的操作过程,例如登陆后进入 xx 页面,点击 xx 按钮,Sentry 会主动捕获。

版本信息:运行我的项目的版本信息(测试、生产、灰度),以及版本号。

设施信息:我的项目应用的平台,web 我的项目包含运行设施信息及浏览器版本信息。小程序我的项目包含运行手机的手机型号、零碎版本及微信版本。

工夫戳:记录异样产生工夫,Sentry 会主动捕获。

异样等级:依据 Sentry 文档分为以下几个等级。

  • Critical
  • Debug
  • Error
  • Fatal
  • Info
  • Log
  • Warning

平台信息:记录异样产生的我的项目。

有以上内容的补全,再加上原有的异样数据,对于一个报错是不是就更清晰明了了呢。

小程序接入 Sentry

Sentry 无官网 api 用于提供给小程序,好在有第三方依据提供的库,可应用原有 api 实现小程序端的异样监控。

装置

  • npm install sentry-mina –save
  • yarn add sentry-mina
  • 将 browser/sentry-mina.js 拷贝到我的项目中

应用

import * as Sentry from "sentry-mina/browser/sentry-mina.js";
// import * as Sentry from "sentry-mina";
// config Sentry
Sentry.init({dsn: "",});
// Set user information, as well as tags and further extras
Sentry.configureScope((scope) => {scope.setUser({ id: "4711"});
  scope.setTag("user_mode", "admin");
  scope.setExtra("battery", 0.7);
  // scope.clear();});
// Add a breadcrumb for future events
Sentry.addBreadcrumb({
  message: "My Breadcrumb",
  // ...
});
// Capture exceptions, messages or manual events
Sentry.captureMessage("Hello, world!");
Sentry.captureException(new Error("Good bye"));
Sentry.captureEvent({
  message: "Manual",
  stacktrace: [// ...],
});

其余内容见文档 Sentry 小程序 SDK。

问题总结

上面是我在接入 Sentry 及后续应用时遇到的问题。

consolelog 不显示 sourmap 地址

这个问题产生的起因是,Sentry 会批改原生 console 办法收集 console,所以这边不会显示 sourcemap 地址,能够在开发环境下勾销注册 Sentry。


本文首发于我的博客 mogii’blog 欢送大家光顾~

正文完
 0