68

JavaScript集成Sentry

 6 years ago
source link: http://www.bugs.cc/2018/08/24/JavaScript集成Sentry/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Sentry是一套用于捕获产品错误的开源项目,其下支持很多语言、框架。

这里就只阐述在前端JavaScript方向的处理操作

在我们公司之前的应用场景里,很多项目都是使用 kibana 来做信息统计。但是我们无法清楚的知道应用的运行状态是怎么样的。当某个客户在使用我们开发产品时,如果报错、崩溃。用户只能向客服寻求帮助,再交接给我们的开发人员进行复现、修复。其中因为不清楚具体的数据,开发人员是在复现时会非常的耗时。

Sentry 的用途就是解决这一痛点问题,让开发人员快速准确的定位到问题的根源所在,以达到快速修复,让开发人员更注重于开发新的功能上面。减少时间资源上的浪费。

JavaScript

接入

因为 Sentry 使用的是一种 Hook 错误函数的技术,来达到捕获错误的目的,所以我们基本可以无损耗的接入到现有的项目中去。

下面是 ReactSentry 进行结合的一些基本步骤。

React:

#SentryBoundary.js
import { Component } from "react";
import Raven from "raven-js";

export default class SentryBoundaryextends Component{
  constructor(props) {
    super(props);
    this.state = { error: null };
  }

  componentDidCatch(error, errorInfo) {
    this.setState({ error });
    // 发送错误信息
    Raven.captureException(error, { extra: errorInfo });
  }

  render() {
    if (this.state.error) {
      // 此处可以写成组件,当组件崩溃后,可以替换崩溃的组件
      console.log("React Error");
    }
    return this.props.children;
  }
}
#index.js
Raven.config("DSN", {
  release: release,
}).install();

ReactDOM.render(
  <div>
    <SentryBoundary>
      <App />
    </SentryBoundary>
</div>,
  document.getElementById("root")
);

上传source-map

如果上面的代码已经配置好后,那么现在的应用是可以捕获到错误的,但是存在了一个问题,我们目前的项目大多都使用 webpack 进行打包,而打包后的代码是混淆加密的代码,无法让我们准确的知道抛出错误的位置在哪里。所以我们需要上传 source-map 和混淆后的文件一起上传到 Sentry 服务器上。方便我们快速查找到问题所在的位置。

这个上传的配置及命令是比较繁琐的。也是项目结合 Sentry 的一个难点。

上传 source-map 目前有两种方式:

  • 使用 Sentry 提供的 Webpack 插件进行配置,但是其灵活性不高。
  • 使用 sentry-cli 的,其灵活性比较高,可以针对不同项目进行单独的配置。

其配置较为繁琐,这里就不在阐述。具体的React与Sentry结合的例子。可见我在github上的项目: react-sentry-demo 。对每个配置都有详细的说明。其中的上传 source-map ,我使用的是第二种方法,并写了一个脚本,实现了: 打包、环境检测、认证检测、上传source-map、删除本地source-map的操作 ,完成自动化,可以把脚本直接迁移到现有的项目中去,改动也不会太大。

其核心上传命令如下:

sentry-cli releases files v1.8 upload-sourcemaps {js文件和js.map所在目录。如果没有找到,sentry会遍历其子目录} --url-prefix '~/{过滤规则}'`;

浅入原理

在JavaScript中是有 window.onerror 这个方法的,而 Sentry 在前端的核心捕获原理,就是通过重写此方法,来对所有的错误进行捕获。其实现的代码大致如下:

let _winError = window.onerror;
window.onerror = function (message, url, lineNo, colNo, errorObj){
    console.log(`
错误信息:${message}
错误文件地址:${url}
错误行号:${lineNo}
错误列号:${colNo}
错误的详细信息${errorObj}`);
}

然后 Sentry 的工作就是获取非错误的数据,如: user-agent浏览器信息系统信息自定义信息 等信息,然后交给 Sentry 的生命周期函数,最后在把数据发送到 Sentry 服务端,进行错误信息展示。

兼容性

这里所说的兼容性,其实也就是 window.onerror 的兼容性

运行环境兼容性

环境 message url lineNo colNo errorObj Firefox ✓ ✓ ✓ ✓ ✓ Chrom ✓ ✓ ✓ ✓ ✓ Edge ✓ ✓ ✓ ✓ ✓ IE 11 ✓ ✓ ✓ ✓ ✓ IE 10 ✓ ✓ ✓ ✓ IE 9 ✓ ✓ ✓ ✓ IE 8 ✓ ✓ ✓ Safari 10 and up ✓ ✓ ✓ ✓ ✓ Safari 9 ✓ ✓ ✓ ✓ Opera 15+ ✓ ✓ ✓ ✓ ✓ Android Browser 4.4 ✓ ✓ ✓ ✓ Android Browser 4 - 4.3 ✓ ✓ 微信webview(安卓) ✓ ✓ ✓ ✓ 微信webview(IOS) ✓ ✓ ✓ ✓ ✓ WKWebview ✓ ✓ ✓ ✓ ✓ UIWebview ✓ ✓ ✓ ✓ ✓

标签兼容性

标签 window.onerror是否能捕获 img 可以 script 需要再script标签添加 crossorigin 属性,并在服务端允许跨域。如果不使用这个属性,错误信息只会显示 Script error. css 不能 iframe 不能

可以发现其浏览器都支持此方法。只是有些运行环境不支持 colNoerrorObj ,但是这块, Sentry 已经帮你处理好了,所以不用担心。只是会在展示错误的时候,信息不太完整而已。

所能捕获的信息

错误信息

从上面的浅入原理可以看到,其核心捕获是 window.onerror 。那么只要它可以捕获到的错误,都会发送到 Sentry 上。

window.onerror 能捕获到的错误,除了 Promise ,基本上能在控制台出现的错误,都会捕获到。也就是运行时的错误,包括语法错误。

关于捕获 Promise 错误的方案,可以使用:

window.addEventListener('unhandledrejection', event => {})

来进行捕获,但是此事件的兼容性不太好,目前只有 webkit内核 支持这个事件。

如下代码,是此方法所能捕获到的:

const p = new Promise((reslove, reject) => reject('Error'))
p.then(data=> {
  console.log(data)
})
// Promise触发了reject回调函数,但是却没有相应到catch来应对。从而导致报错。

面包屑信息

  • Ajax请求
  • URL地址的变化
  • UI点击和按下的DOM事件
  • 控制台的console信息
  • 之前的错误
  • 自定义的面包屑信息

展示信息

myeqyuq.png!web

Electron集成

这里的集成,也不是说捕获Electron应用的错误,而是崩溃。因为Electron只是一个容器,里面的内容还是JavaScript应用。

接入

刚刚也说到这里的集成也只是去捕获Electron崩溃的信息。而当Electron崩溃时,会触发Electron的函数: crashReporter.start ,那么我们在这个函数里去配置一下自己的 sentry 信息:

import { crashReporter } from 'electron'

crashReporter.start({
  productName: 'aoc-desktop',
  companyName: 'alo7',
  submitURL:
    'https://sentry.com/api/15376/minidump/?sentry_key=3e05fa101f035008e953ff56909b8eb',	// sentry提供的minidump接口
  extra: {
    // 额外信息
  }
})

配置好后,可以使用 process.crash() 来模拟崩溃,以便查看Sentry是否能收到崩溃信息。

上传Symbol(符号表)

在上面的应用说的是上传 source-map ,但是这里上传的是Symbol。可以把 Symbol 理解为另一种 source-map

Symbol的格式(后缀)有很多,Mac下是 dSYM ,windows是 pdb 。而在Sentry里,暂时是不支持上传 pdb 的。需要使用 dump_syms.exe 来把 pdb 格式转化成 sym 格式。再上传到Sentry里。这样就可以在Sentry崩溃的时候,看到起崩溃的上下文了。如下图:

iyeaU3Y.png!web

这样就可以准确的定位到是哪里出现了问题。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK