用ARMS前端监控诊断JS错误

对于前端应用来说,JS错误的发生直接影响前端应用的质量,因此对于JS错误的定位及诊断显得尤为重要。ARMS前端监控提供的JS错误诊断功能可以辅助排查JS错误,能够做到精准定位、快速诊断。

前提条件

前端开发人员已使用构建工具生成Source Map。您可以在设置 > 应用设置页面的高级设置页签上传Source Map文件。

背景信息

实际情况中,JS错误诊断经常会遇到以下困难。

  • 复现困难。

    假设您的一位用户是A,当A访问某网页时,该页面会加载在A本地的浏览器上。由于页面的加载耗时受地域、网络情况、浏览器或者运营商等因素影响,排查问题时无法复现A在访问页面时的具体情况。

  • 缺少监控信息,无法深入排查。

    大部分前端监控会通过PerformanceTiming对象来获取完整的页面加载耗时信息,这将缺失页面静态资源的加载情况,导致无法深入定位性能瓶颈。

ARMS前端监控可利用Source Map还原代码真正的错误位置,还可以利用用户行为回溯功能还原JS错误现场。这样使得开发者能够迅速定位出错的源代码位置以及相应的代码块。

什么是Source Map?

Source Map是一个存储源代码与编译代码对应位置映射的信息文件,便于开发人员定位上述代码错误。实际上,它就是一个JSON键值对,利用VLQ编码与特定的规则存储位置信息。简而言之,可以理解为Source Map在处理前的代码和处理后的代码之间搭建了一座桥梁。

如何用构建工具生成Source Map?

  • Webpack

    在配置文件webpack.config.js中设置devtool属性即可生成Source Map文件。

    const path = require('path');
    
    module.exports = {
        entry: './src/index.js',
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist')
        },
        devtool: "source-map" // devtool13种不同取值,对应不同类型的Source Map。建议设为source-map。
    };
                
  • Gulp

    var gulp = require('gulp');
    var sourcemaps = require('gulp-sourcemaps');
    
    gulp.task('javascript', function() {
        gulp.src('src/**/*.js')
            .pipe(sourcemaps.init())
            .pipe(sourcemaps.write('../sourcemaps'))
            .pipe(gulp.dest('dist'));
    });
            
  • Grunt

    如果只使用grunt-contrib-uglify压缩打包:

    grunt.initConfig({
        uglify: {
            options: {
                sourceMap: true
            }
        }
    });
            

    如果使用grunt-usemin压缩打包,由于grunt-usemin会依次调用grunt-contrib-concatgrunt-contrib-uglify对源码进行打包和压缩:

    grunt.initConfig({
        concat: {
            options: {
                sourceMap: true
            }
        },
        uglify: {
            options: {
                sourceMap: true,
                sourceMapIn: function(uglifySource) {
                    return uglifySource + '.map';
                },
            }
        }
    });
            

    如果使用grunt-jsmin-sourcemap

    module.exports = function(grunt) {
        grunt.loadNpmTasks('grunt-jsmin-sourcemap');
        grunt.initConfig({
            'jsmin-sourcemap': {
                all: {
                    src: ['scripts/script.js'],
                    dest: 'scripts/script.jsmin-grunt.js',
                    destMap: 'scripts/script.jsmin-grunt.js.map'
                }
            }
        });
        grunt.registerTask('default', 'jsmin-sourcemap');
    };
  • AngularJS

    ng build --prod --source-map --vendor-source-map
  • UglifyJS2

    UglifyJS2是命令行工具,执行方法如下所示。单击查看更多source-map选项

    $ uglifyjs app.js -o app.min.js --source-map app.min.js.map
        
  • SystemJS

    SystemJSSystemJS构建工具

    builder.bundle('app.js', 'app-outfile.js', {
        minify: true,
        sourceMaps: true
    });

步骤一:安装探针

如需全方位监控前端应用,那么您首先需要为您的前端应用安装ARMS探针。请根据实际需求选择一种方式来安装探针,具体操作,请参见前端监控接入概述

步骤二:查看错误总览

  1. 登录ARMS控制台,在左侧导航栏选择前端监控 > 前端列表
  2. 前端列表页面顶部选择目标地域,然后单击目标应用名称。
  3. 在左侧导航栏,单击JS错误诊断

    JS Error Diagnosis

    • 通过错误总览查看总的错误数、JS错误率、影响用户数及占比。

    • 通过曲线图判断JS的错误趋势。

    • 通过高频错误筛选出频繁出现的错误。

    • 通过页面错误率排行错误分布等信息对JS错误有一个全局的判断。

步骤三:诊断具体错误

对全局错误信息有一个初步的判断后,还需要排查具体的错误。进入ARMS前端监控中JS错误诊断的异常诊断有以下两种方式:

  • 单击高频错误页签的诊断直接进入异常诊断。

  • 在错误曲线图中下钻到某个时刻的异常洞察弹出框,再进入到异常诊断。

本文以第二种方式为例。

  1. 观察到错误曲线图中某个时刻的错误率突然变高,将鼠标悬浮于该曲线拐点上,当鼠标显示为手形指针时单击拐点,可打开该时间点的异常洞察对话框。更多信息,请参见查看异常洞察

    JS错误异常洞察

  2. 单击高频错误Top 5页签,选择其中一条错误,然后单击操作列中的诊断

    进入错误详情页面。

步骤四:查看错误详情

JS错误详情信息包括首次发现时间、首次发现版本(可选上报指标)、错误名称、错误类型、错误时间、设备、操作系统、浏览器、IP、网络制式、地区、错误URL、错误所在文件及行列信息、应用版本号等。如下图所示,可以从错误详情信息中看出是实时大屏页面的地图模块在更新时报了一个数据非法的异常,错误发生在第1行第79585列。

Error Details

步骤五:定位错误代码

通过查看JS错误详情得到的信息不足以诊断问题,因为线上代码一般是经过编译、压缩、混淆等处理,因此您看到的JS代码不具备可读性。虽然知道是第1行第79585列发生了错误,但这并不代表是源码的实际位置。此时,就需要用到Source Map进行源码映射。

  1. 堆栈信息区域,单击一条堆栈信息左侧的展开图标图标展开该行,并单击选择Source Map

  2. Source Map文件对话框中选择已有Source Map文件,或上传新的Source Map文件,并单击确定

    说明

    一次最多可以上传5个。

    Source Map文件

    ARMS前端监控将利用Source Map文件还原准确的JS错误位置,如果选择的Source Map能够匹配出源码的错误,则原始错误位置将以红色字体标注于源代码区域中。如下图所示,经过解析后就可以一目了然地看出是哪个文件里面的哪一行出现错误。除此之外,错误堆栈的每一行都可以使用Source Map做源码映射。

    图 1. Source Map源码映射Stack Information

步骤六:查看用户行为回溯

虽然通过Source Map源码映射,可以看到源码报错是创建地图组件时,传入了非法的数据导致的。但非法的数据可能性有很多,上述代码中实际已经对数据做了判空容错处理,但依然触发了数据非法异常。如果能对报错时的数据做一个快照,就能更准确地定位问题。实际上在全局异常捕获中,现场数据一般无法获取到,只能依赖用户主动上报时附带数据信息。

最好的辅助排查方式就是复现,ARMS前端监控把页面上发生的各个事件节点定义为用户行为,包括页面加载、路由跳转、页面单击、API请求、控制台输出等信息,按照时间顺序将用户行为串联起来就是用户的行为链路。通过出错时的行为回溯可以帮助开发者复现问题。

用户行为回溯所示,通过出错时用户行为回溯可以看到出错前有一个API请求,这个API请求试图去请求数据实时更新地图模块,但是返回的数据是ConsoleNeedLogin,说明此时页面已经退出登录状态了,这就是导致非法数据的根源。

图 2. 用户行为回溯User Behavior Trace