├── test ├── index.js └── unit │ ├── ajax.spec.js │ ├── error.spec.js │ ├── config.spec.js │ └── index.spec.js ├── MonitorFE.gif ├── .gitignore ├── dist ├── js │ ├── monitor.0.0.1.js.gz │ ├── monitor.0.0.3.js.gz │ ├── monitor.0.0.1-beta.js.gz │ ├── monitor.0.0.2-beta.js.gz │ ├── monitor.0.0.2-beta.js │ ├── monitor.0.0.1.js │ └── monitor.0.0.1-beta.js ├── package.json ├── index.html └── README.md ├── .gitattributes ├── coverage ├── lcov-report │ ├── sort-arrow-sprite.png │ ├── prettify.css │ ├── block-navigation.js │ ├── error.js.html │ ├── stateChange.js.html │ ├── config.js.html │ ├── index.js.html │ ├── sorter.js │ ├── base.css │ ├── index.html │ ├── ajax.js.html │ └── prettify.js ├── lcov.info ├── clover.xml └── coverage-final.json ├── .github └── ISSUE_TEMPLATE │ ├── custom.md │ ├── feature_request.md │ └── bug_report.md ├── .babelrc ├── index.js ├── version.json ├── src ├── index.js ├── config.js ├── monitor.js ├── eventCenter.js ├── vue │ └── index.js ├── ajax.js ├── error.js ├── wrap.js └── initMonitor.js ├── write.js ├── server ├── database │ └── init.js ├── server.js └── index.js ├── .eslintrc.js ├── git-hooks └── verify-commit-msg.js ├── config ├── webpack.pro.config.js └── webpack.dev.config.js ├── LICENSE ├── package.json ├── index.html ├── README.md ├── docs ├── README_ZH.md └── README_EN.md ├── CODE_OF_CONDUCT.md ├── createError.js └── CHANGELOG.md /test/index.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/unit/ajax.spec.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/unit/error.spec.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/unit/config.spec.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MonitorFE.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MriLiuJY/monitorFE/HEAD/MonitorFE.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log* 3 | .DS_Store 4 | .idea 5 | .sass-cache 6 | temp-*.html 7 | .vs -------------------------------------------------------------------------------- /dist/js/monitor.0.0.1.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MriLiuJY/monitorFE/HEAD/dist/js/monitor.0.0.1.js.gz -------------------------------------------------------------------------------- /dist/js/monitor.0.0.3.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MriLiuJY/monitorFE/HEAD/dist/js/monitor.0.0.3.js.gz -------------------------------------------------------------------------------- /dist/js/monitor.0.0.1-beta.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MriLiuJY/monitorFE/HEAD/dist/js/monitor.0.0.1-beta.js.gz -------------------------------------------------------------------------------- /dist/js/monitor.0.0.2-beta.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MriLiuJY/monitorFE/HEAD/dist/js/monitor.0.0.2-beta.js.gz -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=JavaScript 2 | *.css linguist-language=JavaScript 3 | *.html linguist-language=JavaScript 4 | -------------------------------------------------------------------------------- /coverage/lcov-report/sort-arrow-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MriLiuJY/monitorFE/HEAD/coverage/lcov-report/sort-arrow-sprite.png -------------------------------------------------------------------------------- /test/unit/index.spec.js: -------------------------------------------------------------------------------- 1 | const initMonitor = require('../../src/index'); 2 | 3 | test('test initMonitor', () => { 4 | expect(initMonitor(1)).toBe(2); 5 | }); -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "current", 8 | }, 9 | }, 10 | ], 11 | ], 12 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main js at project 3 | * @author 4 | * @version 0.0.1-beta 5 | */ 6 | 7 | import Index from "./src/index"; 8 | 9 | function Shell(window) { 10 | if (!window.initMonitor) { 11 | window.initMonitor = Index; 12 | } 13 | } 14 | 15 | Shell(window); 16 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fe-monitor-sdk", 3 | "version": "0.0.3", 4 | "description": "monitor front-end pro", 5 | "main": "dist/monitor.0.0.3", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "javascript", 11 | "monitor" 12 | ], 13 | "author": "jykid", 14 | "license": "MIT" 15 | } 16 | -------------------------------------------------------------------------------- /dist/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fe-monitor-sdk", 3 | "version": "0.0.3", 4 | "description": "monitor front-end pro", 5 | "main": "dist/monitor.0.0.3", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "javascript", 11 | "monitor" 12 | ], 13 | "author": "jykid", 14 | "license": "MIT" 15 | } 16 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main js at project 3 | * @author JYkid 4 | * @version 0.0.1-beta 5 | */ 6 | 7 | /* eslint-disable */ 8 | import InitMonitor from "./initMonitor"; 9 | import Monitor from "./monitor"; 10 | 11 | function Index(userConfig, callback) { 12 | const init = new InitMonitor(userConfig); 13 | 14 | callback(new Monitor(init)); 15 | // 初始化 16 | return init; 17 | } 18 | 19 | module.exports = Index; 20 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file config detail file 3 | * @author JYkid 4 | * @version 0.0.1-beta 5 | */ 6 | 7 | function Config(conf) { 8 | const self = this; 9 | self._extend(self, conf); 10 | } 11 | 12 | Config.prototype = { 13 | https: true, 14 | post: true, 15 | url: "/monitor", 16 | record: false, 17 | _extend: (self, conf) => { 18 | Object.keys(conf).map((x) => { 19 | self[x] = conf[x]; 20 | return; 21 | }); 22 | return self; 23 | }, 24 | }; 25 | 26 | module.exports = Config; 27 | -------------------------------------------------------------------------------- /coverage/lcov-report/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} 2 | -------------------------------------------------------------------------------- /write.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 该文件的目的是为了在执行npm run build 之后自动生成README.md 和package.json 4 | * 5 | * 6 | */ 7 | 8 | const fs = require("fs"); 9 | const path = require("path"); 10 | 11 | const package = fs.readFileSync('./version.json'); 12 | const readme = fs.readFileSync('./README.md'); 13 | 14 | var packagePath = path.join(__dirname, './dist/package.json'); 15 | var readmePath = path.join(__dirname, './dist/README.md'); 16 | 17 | fs.writeFile(packagePath, package, function(err) { 18 | if (err) { 19 | return console.log(err); 20 | } 21 | }); 22 | 23 | fs.writeFile(readmePath, readme, function(err) { 24 | if (err) { 25 | return console.log(err); 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /server/database/init.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file user account connect DB init js 3 | * @author JYkid 4 | * @version 0.0.1 5 | */ 6 | 7 | const mongoose = require("mongoose"); 8 | const db = "mongodb://localhost/test"; 9 | 10 | mongoose.Promise = global.Promise; 11 | 12 | exports.connect = () => { 13 | if (process.env.NODE_ENV !== 'production') { 14 | mongoose.set('debug', true); 15 | } 16 | 17 | mongoose.connect(db); 18 | 19 | mongoose.connection.on("disonnected", () => { 20 | mongoose.connect(db); 21 | }); 22 | 23 | mongoose.connection.on("err", err => { 24 | mongoose.connect(db); 25 | }); 26 | 27 | mongoose.connection.on("open", () => { 28 | console.log("Mongoodb connect done!"); 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es6": true 6 | }, 7 | "extends": "airbnb-base", 8 | "rules": { 9 | "eol-last": 2, 10 | "indent": [2], 11 | "linebreak-style": [ 12 | "error", 13 | ], 14 | "quotes": [ 15 | "error", 16 | "double" 17 | ], 18 | "semi": [ 19 | "error", 20 | "always" 21 | ], 22 | "no-underscore-dangle": 0, 23 | "no-unused-expressions": 0, 24 | "no-useless-return": 0, 25 | "no-param-reassign": 0, 26 | "consistent-return": 0, 27 | "no-bitwise": 0, 28 | "prefer-destructuring": 0, 29 | "func-names": 0, 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/monitor.js: -------------------------------------------------------------------------------- 1 | 2 | /* eslint-disable */ 3 | 4 | function Monitor(InitMonitor) { 5 | const self = this; 6 | self._InitMonitor = InitMonitor; 7 | return self; 8 | } 9 | 10 | Monitor.prototype = { 11 | _destory() { 12 | const self = this; 13 | const array = self._InitMonitor._getEvent(); 14 | for (let i = 0; i < array.length; i++) { 15 | // event type add different stage 16 | if (array[i].type === 'error') { 17 | window.removeEventListener(array[i].type, array[i].func, true); 18 | } else { 19 | window.removeEventListener(array[i].type, array[i].func); 20 | } 21 | } 22 | }, 23 | _getRecord() { 24 | const self = this; 25 | const array = self._InitMonitor._getRrwebEvent(); 26 | return array 27 | }, 28 | } 29 | 30 | module.exports = Monitor; -------------------------------------------------------------------------------- /git-hooks/verify-commit-msg.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | 3 | const msgPath = process.env.GIT_PARAMS; 4 | const msg = require('fs').readFileSync(msgPath, 'utf-8').trim(); 5 | 6 | const commitRE = /^(revert: )?(feat|fix|merge|package|docs|style|refactor|perf|test|workflow|ci|chore|types|build)(\(.+\))?: .{1,50}/; 7 | 8 | if (!commitRE.test(msg)) { 9 | console.error( 10 | ` ${chalk.bgRed.white(' ERROR ')} ${chalk.red('invalid commit message format.')}\n\n${ 11 | chalk.red(' Proper commit message format is required for automated changelog generation. Examples:\n\n') 12 | } ${chalk.green('feat(compiler): add \'comments\' option')}\n` 13 | + ` ${chalk.green('fix(v-model): handle events on blur (close #28)')}\n\n${ 14 | chalk.red(` You can also use ${chalk.cyan('npm run commit')} to interactively generate a commit message.\n`)}`, 15 | ); 16 | process.exit(1); 17 | } 18 | -------------------------------------------------------------------------------- /config/webpack.pro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author 4 | * @version 0.1.0 5 | */ 6 | const path = require("path"); 7 | const webpack = require("webpack"); 8 | const metadata = require("../version.json"); 9 | // const UglifyJSPlugin = require("uglifyjs-webpack-plugin"); 10 | const CompressionWebpackPlugin = require('compression-webpack-plugin'); 11 | 12 | module.exports = (env) => { 13 | return { 14 | mode: "production", 15 | entry: "./index.js", 16 | output: { 17 | publicPath: "/dist/js/", 18 | filename: `monitor.${metadata.version}.js`, 19 | path: path.resolve(__dirname, "../dist/js/"), 20 | }, 21 | plugins: [ 22 | new webpack.HashedModuleIdsPlugin(), 23 | new CompressionWebpackPlugin(), 24 | ], 25 | module: { 26 | rules: [ 27 | { 28 | test: /\.js$/, 29 | exclude: /node_modules/, 30 | use: "babel-loader", 31 | }, 32 | ], 33 | }, 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /src/eventCenter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file event center && record center 3 | * @since 0.0.2 4 | * @author JYkid 5 | * @version 0.0.2 6 | */ 7 | 8 | function EventCenter() { 9 | const self = this; 10 | const data = []; 11 | const record = []; 12 | self.data = data; 13 | self.record = record; 14 | return self; 15 | } 16 | 17 | EventCenter.prototype = { 18 | _get() { 19 | const self = this; 20 | return self.data; 21 | }, 22 | _getRecord() { 23 | const self = this; 24 | return self.record; 25 | }, 26 | _set(event) { 27 | const self = this; 28 | self.data.push(event); 29 | }, 30 | /** 31 | * push record event data in Array 32 | * @param { Object } event 33 | */ 34 | _setRecord(event) { 35 | const self = this; 36 | self.record.push(event); 37 | }, 38 | /** 39 | * clear event center data 40 | */ 41 | _clearRecord() { 42 | const self = this; 43 | self.record.splice(0, self.record.length); 44 | }, 45 | }; 46 | 47 | module.exports = EventCenter; 48 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /server/server.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const express = require("express"); 3 | const bodyParser = require("body-parser"); 4 | const app = express(); 5 | 6 | app.use(bodyParser.json()); 7 | app.use(bodyParser.urlencoded({extended: false})); 8 | app.use(express.static("./")); 9 | app.use(express.static("dist")); 10 | 11 | app.use("/index", (req, res) => { 12 | const filename = "./dist/index.html"; 13 | fs.readFile(filename, (err, result) => { 14 | res.set("content-type", "text/html"); 15 | res.send(result); 16 | res.end(); 17 | }); 18 | }); 19 | 20 | // create 500 in server 21 | app.use("/servererr", (req, res) => { 22 | reqq; 23 | res.send({ 24 | status: "success", 25 | }); 26 | }); 27 | 28 | // timeout no res 29 | app.use("/timeout", (req, res) => {}); 30 | 31 | 32 | // timeout no res 33 | app.use("/monitor", (req, res) => { 34 | res.send({}); 35 | }); 36 | 37 | 38 | const point = 9999; 39 | console.log("打包测试地址: " + "http://localhost:" +point + "/index"); 40 | app.listen(point); 41 | 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 MriLiuJY 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/vue/index.js: -------------------------------------------------------------------------------- 1 | function formatComponentName(vm) { 2 | try { 3 | if (vm.$root === vm) return "root"; 4 | 5 | var name = vm._isVue 6 | ? (vm.$options && vm.$options.name) || 7 | (vm.$options && vm.$options._componentTag) 8 | : vm.name; 9 | return ( 10 | (name ? "component <" + name + ">" : "anonymous component") + 11 | (vm._isVue && vm.$options && vm.$options.__file 12 | ? " at " + (vm.$options && vm.$options.__file) 13 | : "") 14 | ); 15 | } catch (error) { 16 | // 无需出错处理 17 | } 18 | } 19 | 20 | export default function(monitor, Vue) { 21 | Vue.config.errorHandler = function(err, vm, info) { 22 | try { 23 | if (vm) { 24 | var componentName = formatComponentName(vm); 25 | var propsData = vm.$options && vm.$options.propsData; 26 | monitor.getJsError(err, { 27 | metaData: { 28 | componentName: componentName, 29 | propsData: propsData, 30 | info: info 31 | } 32 | }); 33 | } else { 34 | monitor.notifyError(err); 35 | } 36 | } catch (error) { 37 | // 无需出错处理 38 | } 39 | }; 40 | } -------------------------------------------------------------------------------- /src/ajax.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ajax request file 3 | * @author JYkid 4 | * @version 0.0.1-beta 5 | */ 6 | 7 | 8 | /* eslint-disable */ 9 | const ajax = (function() { 10 | return { 11 | canAjax: function() { 12 | return (window.XMLHttpRequest && window.JSON); 13 | }, 14 | post: function(url, data, timeout) { 15 | var xhr = new XMLHttpRequest(); 16 | xhr.open("post", url, true); 17 | xhr.setRequestHeader("content-type", "application/json;charset=utf-8"); 18 | xhr.setRequestHeader("Accept", "application/json"); 19 | xhr.withCredentials = true; 20 | xhr.timeout = timeout || 30000; 21 | xhr.onload = function () { 22 | var result = window.JSON.parse(xhr.responseText); 23 | if (result.status === 1) { 24 | changeStatus() 25 | } 26 | }; 27 | xhr.onreadystatechange = function () { 28 | if (xhr.readyState === 4) { 29 | if (xhr.status === 200) { 30 | var result = window.JSON.parse(xhr.responseText); 31 | if (result.status === 1) { 32 | changeStatus() 33 | } 34 | } else { 35 | throw new Error("网络请求错误,请稍后再试~"); 36 | } 37 | } 38 | }; 39 | xhr.send(window.JSON.stringify(data)); 40 | }, 41 | getWraper: function(err, Wrap, resource) { 42 | let wrap = new Wrap(); 43 | let data = wrap._geWrap(); 44 | 45 | }, 46 | } 47 | })(); 48 | 49 | module.exports = { 50 | ajax, 51 | } 52 | -------------------------------------------------------------------------------- /coverage/lcov.info: -------------------------------------------------------------------------------- 1 | TN: 2 | SF:/Users/jyliu/mycode/FE-Monitor/src/ajax.js 3 | FN:7,(anonymous_0) 4 | FN:9,(anonymous_1) 5 | FN:12,(anonymous_2) 6 | FN:19,(anonymous_3) 7 | FN:25,(anonymous_4) 8 | FNF:5 9 | FNH:0 10 | FNDA:0,(anonymous_0) 11 | FNDA:0,(anonymous_1) 12 | FNDA:0,(anonymous_2) 13 | FNDA:0,(anonymous_3) 14 | FNDA:0,(anonymous_4) 15 | DA:7,0 16 | DA:8,0 17 | DA:10,0 18 | DA:13,0 19 | DA:14,0 20 | DA:15,0 21 | DA:16,0 22 | DA:17,0 23 | DA:18,0 24 | DA:19,0 25 | DA:20,0 26 | DA:21,0 27 | DA:22,0 28 | DA:25,0 29 | DA:26,0 30 | DA:27,0 31 | DA:28,0 32 | DA:29,0 33 | DA:30,0 34 | DA:33,0 35 | DA:37,0 36 | DA:42,0 37 | LF:22 38 | LH:0 39 | BRDA:10,0,0,0 40 | BRDA:10,0,1,0 41 | BRDA:18,1,0,0 42 | BRDA:18,1,1,0 43 | BRDA:21,2,0,0 44 | BRDA:21,2,1,0 45 | BRDA:26,3,0,0 46 | BRDA:26,3,1,0 47 | BRDA:27,4,0,0 48 | BRDA:27,4,1,0 49 | BRDA:29,5,0,0 50 | BRDA:29,5,1,0 51 | BRF:12 52 | BRH:0 53 | end_of_record 54 | TN: 55 | SF:/Users/jyliu/mycode/FE-Monitor/src/config.js 56 | FN:7,Config 57 | FNF:1 58 | FNH:0 59 | FNDA:0,Config 60 | LF:0 61 | LH:0 62 | BRF:0 63 | BRH:0 64 | end_of_record 65 | TN: 66 | SF:/Users/jyliu/mycode/FE-Monitor/src/error.js 67 | FNF:0 68 | FNH:0 69 | LF:0 70 | LH:0 71 | BRF:0 72 | BRH:0 73 | end_of_record 74 | TN: 75 | SF:/Users/jyliu/mycode/FE-Monitor/src/index.js 76 | FN:9,initMonitor 77 | FNF:1 78 | FNH:1 79 | FNDA:1,initMonitor 80 | DA:10,1 81 | DA:11,1 82 | DA:14,1 83 | DA:16,1 84 | LF:4 85 | LH:4 86 | BRF:0 87 | BRH:0 88 | end_of_record 89 | TN: 90 | SF:/Users/jyliu/mycode/FE-Monitor/src/stateChange.js 91 | FNF:0 92 | FNH:0 93 | LF:0 94 | LH:0 95 | BRF:0 96 | BRH:0 97 | end_of_record 98 | -------------------------------------------------------------------------------- /config/webpack.dev.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const webpack = require("webpack"); 3 | const UglifyJSPlugin = require("uglifyjs-webpack-plugin"); 4 | const CompressionWebpackPlugin = require('compression-webpack-plugin'); 5 | 6 | module.exports = { 7 | mode: "development", 8 | entry: "./index.js", 9 | output: { 10 | publicPath: "/dist/js/", 11 | filename: "monitor.js", 12 | path: path.resolve(__dirname, "../dist"), 13 | }, 14 | devServer: { 15 | contentBase: "./dist/", 16 | port: 8080, 17 | hot: true, 18 | host: "localhost", 19 | }, 20 | module: { 21 | rules: [{ 22 | enforce: "pre", 23 | test: /\.js$/, 24 | exclude: /node_modules/, 25 | loader: "eslint-loader", 26 | }, 27 | { 28 | test: /\.js$/, 29 | exclude: /node_modules/, 30 | use: "babel-loader", 31 | }, 32 | { 33 | test:/\.scss$/, 34 | use:["style-loader","css-loader"], 35 | } 36 | ], 37 | }, 38 | plugins: [ 39 | new webpack.HotModuleReplacementPlugin(), 40 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. 41 | new webpack.NoEmitOnErrorsPlugin(), 42 | new UglifyJSPlugin({ 43 | sourceMap: true, 44 | uglifyOptions: { 45 | ie8: true, 46 | ecma: 5, 47 | output: { 48 | comments: (astNode, comment) => comment && comment.value && /@jscrambler/.test(comment.value), 49 | beautify: false, 50 | }, 51 | compress: { 52 | properties: false, 53 | drop_console: true, 54 | }, 55 | }, 56 | }), 57 | ], 58 | }; 59 | -------------------------------------------------------------------------------- /src/error.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file error event center 3 | * @author JYkidrecord 4 | * @version 0.0.1-beta 5 | */ 6 | 7 | /* eslint-disable */ 8 | import { ajax } from "./ajax"; 9 | import Wrap from "./wrap"; 10 | 11 | const wrap = new Wrap(); 12 | const getErrorData = function(err, initMonitor) { 13 | let data = wrap._getErrorMessage(err); 14 | data.record = []; 15 | 16 | let config = initMonitor._config; 17 | if (config.record) { 18 | data.record = initMonitor._getRrwebEvent(); 19 | } 20 | return data; 21 | }; 22 | 23 | // 服务端返回错误 24 | export const getServerError = function() {}; 25 | 26 | // ajaxError 27 | export const ajaxError = function(err, initMonitor) { 28 | // 处理err 上报 29 | if (err.type === "ajaxLoad" && err.detail.status >= 400) { 30 | let data = getErrorData(err, initMonitor); 31 | let config = initMonitor._config; 32 | ajax.post(config.protocol + config.url, data, function() { 33 | initMonitor._clearEvent(); 34 | }, 35 | function(error) { 36 | console.log(error); 37 | }); 38 | } 39 | } 40 | 41 | // js 抛出的错误 42 | export const getJsError = function(err, initMonitor) { 43 | let data = getErrorData(err, initMonitor); 44 | let config = initMonitor._config; 45 | ajax.post(config.protocol + config.url, data, 46 | function() { 47 | initMonitor._clearEvent(); 48 | }, 49 | function(error) { 50 | console.log(error); 51 | }); 52 | } 53 | 54 | // 资源加载错误 55 | export const geetResourceError = function (err, initMonitor) { 56 | let data = getErrorData(err, initMonitor); 57 | let config = initMonitor._config; 58 | ajax.post(config.protocol + config.url, data, 59 | function() { 60 | initMonitor._clearEvent(); 61 | }, 62 | function(error) { 63 | console.log(error); 64 | }); 65 | } 66 | -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file user account main js in project 3 | * @author JYkid 4 | * @version 0.0.1 5 | */ 6 | 7 | const fs = require("fs"); 8 | const express = require("express"); 9 | const webpack = require("webpack"); 10 | const devMiddleware = require("webpack-dev-middleware"); 11 | const hotMiddleware = require("webpack-hot-middleware"); 12 | const config = require("../config/webpack.dev.config"); 13 | const bodyParser = require("body-parser"); 14 | const session = require('express-session'); 15 | // const { connect } = require('./database/init'); 16 | 17 | const app = express(); 18 | app.use(express.static("./")); 19 | const complier = webpack(config); 20 | 21 | // (async() => { 22 | // await connect(); 23 | // })(); 24 | 25 | app.all('*', (req, res, next) => { 26 | res.header('Access-Control-Allow-Origin', '*'); 27 | res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild'); 28 | res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS'); 29 | if (req.method == 'OPTIONS') { 30 | res.send(200); 31 | } else { 32 | next(); 33 | } 34 | }); 35 | 36 | 37 | // webpack middleware 38 | app.use(devMiddleware(complier, { 39 | publicPath: config.output.publicPath, 40 | quiet: true, 41 | })); 42 | 43 | app.use(hotMiddleware(complier)); 44 | 45 | app.use(bodyParser.json()); 46 | app.use(bodyParser.urlencoded({extended: false})); 47 | app.use(express.static("gt-dist")); 48 | app.use(express.static("build")); 49 | 50 | app.use(session({ 51 | secret: 'my-secret', 52 | resave: false, 53 | saveUninitialized: true 54 | })); 55 | 56 | app.use((req, res, next) => { 57 | res.header("Access-Control-Allow-Origin", "*"); 58 | res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); 59 | next(); 60 | }); 61 | 62 | // page URL 63 | app.use("/index", (req, res) => { 64 | const filename = "./index.html"; 65 | fs.readFile(filename, (err, result) => { 66 | res.set("content-type", "text/html"); 67 | res.send(result); 68 | res.end(); 69 | }); 70 | }); 71 | 72 | // create 500 in server 73 | app.use("/servererr", (req, res) => { 74 | reqq; 75 | res.send({ 76 | status: "success", 77 | }); 78 | }); 79 | 80 | // timeout no res 81 | app.use("/timeout", (req, res) => {}); 82 | 83 | // timeout no res 84 | app.use("/monitor", (req, res) => { 85 | res.send({}); 86 | }); 87 | 88 | const point = 9998; 89 | console.log("Your server listen at " + "http://localhost:" +point + "/index"); 90 | app.listen(point); 91 | 92 | -------------------------------------------------------------------------------- /coverage/lcov-report/block-navigation.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var jumpToCode = (function init() { 3 | // Classes of code we would like to highlight in the file view 4 | var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; 5 | 6 | // Elements to highlight in the file listing view 7 | var fileListingElements = ['td.pct.low']; 8 | 9 | // We don't want to select elements that are direct descendants of another match 10 | var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` 11 | 12 | // Selecter that finds elements on the page to which we can jump 13 | var selector = 14 | fileListingElements.join(', ') + 15 | ', ' + 16 | notSelector + 17 | missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` 18 | 19 | // The NodeList of matching elements 20 | var missingCoverageElements = document.querySelectorAll(selector); 21 | 22 | var currentIndex; 23 | 24 | function toggleClass(index) { 25 | missingCoverageElements 26 | .item(currentIndex) 27 | .classList.remove('highlighted'); 28 | missingCoverageElements.item(index).classList.add('highlighted'); 29 | } 30 | 31 | function makeCurrent(index) { 32 | toggleClass(index); 33 | currentIndex = index; 34 | missingCoverageElements.item(index).scrollIntoView({ 35 | behavior: 'smooth', 36 | block: 'center', 37 | inline: 'center' 38 | }); 39 | } 40 | 41 | function goToPrevious() { 42 | var nextIndex = 0; 43 | if (typeof currentIndex !== 'number' || currentIndex === 0) { 44 | nextIndex = missingCoverageElements.length - 1; 45 | } else if (missingCoverageElements.length > 1) { 46 | nextIndex = currentIndex - 1; 47 | } 48 | 49 | makeCurrent(nextIndex); 50 | } 51 | 52 | function goToNext() { 53 | var nextIndex = 0; 54 | 55 | if ( 56 | typeof currentIndex === 'number' && 57 | currentIndex < missingCoverageElements.length - 1 58 | ) { 59 | nextIndex = currentIndex + 1; 60 | } 61 | 62 | makeCurrent(nextIndex); 63 | } 64 | 65 | return function jump(event) { 66 | switch (event.which) { 67 | case 78: // n 68 | case 74: // j 69 | goToNext(); 70 | break; 71 | case 66: // b 72 | case 75: // k 73 | case 80: // p 74 | goToPrevious(); 75 | break; 76 | } 77 | }; 78 | })(); 79 | window.addEventListener('keydown', jumpToCode); 80 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Monitor 打包测试 8 | 20 | 21 | 22 |

Monitor 打包测试

23 | 24 | 25 |

ajax请求错误

26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 | 34 |

js执行错误

35 | 36 |
37 | 38 | 39 |

Promise 错误

40 | 41 |
42 | 43 | 44 | 47 | 48 | 49 |

资源没有加载

50 | 51 | 52 | 53 | 54 |
55 | 56 | 57 |

第三方资源错误

58 | 59 |
60 | 61 | 62 |

销毁实例

63 | 64 |
65 | 66 | 67 | 93 | 94 | -------------------------------------------------------------------------------- /coverage/clover.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fe-monitor", 3 | "version": "0.0.1-beta", 4 | "description": "Front End buried point", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jest", 8 | "lint": "eslint --fix", 9 | "start": "node server/index", 10 | "dev": "node server/index", 11 | "build": "rm -rf ./dist/js && webpack --config config/webpack.pro.config.js && node write.js && conventional-changelog -p angular -i ./CHANGELOG.md -s", 12 | "dist-js": "rm -rf ./dist/js && webpack --config config/webpack.pro.config.js && node write.js && conventional-changelog -p angular -i ./CHANGELOG.md -s", 13 | "dev-js": "rm -rf ./dist/js && webpack --config config/webpack.pro.config.js --env.pro=dev && node write.js && conventional-changelog -p angular -i ./CHANGELOG.md -s", 14 | "server": "node server/server" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/MriLiuJY/FE-Monitor.git" 19 | }, 20 | "author": "", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/MriLiuJY/FE-Monitor/issues" 24 | }, 25 | "homepage": "https://github.com/MriLiuJY/FE-Monitor#readme", 26 | "dependencies": { 27 | "@babel/core": "^7.4.5", 28 | "@babel/preset-env": "^7.4.5", 29 | "babel-core": "7.0.0-bridge.0", 30 | "babel-eslint": "^10.0.1", 31 | "babel-jest": "^23.6.0", 32 | "babel-loader": "^7.1.5", 33 | "body-parser": "^1.19.0", 34 | "chalk": "^2.4.2", 35 | "es3ify-loader": "^0.2.0", 36 | "eslint-config-airbnb-base": "^13.1.0", 37 | "eslint-loader": "^2.1.2", 38 | "eslint-plugin-import": "^2.17.3", 39 | "fe-monitor-sdk": "0.0.1", 40 | "jest": "^24.8.0", 41 | "mongoose": "^5.6.2", 42 | "rrweb": "^0.7.18", 43 | "uglifyjs-webpack-plugin": "^2.1.3", 44 | "webpack": "^4.34.0", 45 | "webpack-dev-middleware": "^3.7.0", 46 | "webpack-hot-middleware": "^2.25.0" 47 | }, 48 | "devDependencies": { 49 | "compression-webpack-plugin": "^3.0.0", 50 | "eslint": "^5.16.0", 51 | "express": "^4.17.1", 52 | "express-session": "^1.16.2", 53 | "husky": "^3.0.3", 54 | "lint-staged": "^9.2.1", 55 | "webpack-cli": "^3.3.4" 56 | }, 57 | "config": { 58 | "commitizen": { 59 | "path": "./node_modules/cz-conventional-changelog" 60 | } 61 | }, 62 | "jest": { 63 | "moduleFileExtensions": [ 64 | "js", 65 | "json" 66 | ], 67 | "transform": { 68 | "^.+\\.js?$": "babel-jest" 69 | }, 70 | "moduleNameMapper": { 71 | "^@/(.*)$": "/src/$1" 72 | }, 73 | "testMatch": [ 74 | "**/test/unit/*.spec.(js|jsx|ts|tsx)|**/__test__/*.(js|jsx|ts|tsx)" 75 | ], 76 | "testURL": "http://localhost/", 77 | "collectCoverage": true, 78 | "collectCoverageFrom": [ 79 | "**/src/**/*.js", 80 | "!**/node_modules/**" 81 | ] 82 | }, 83 | "gitHooks": { 84 | "pre-commit": "lint-staged", 85 | "commit-msg": "node git-hooks/verify-commit-msg.js" 86 | }, 87 | "lint-staged": { 88 | "*.js": [ 89 | "eslint --fix", 90 | "git add" 91 | ] 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Monitor testPage 8 | 20 | 21 | 22 |

Monitor testPage

23 | 24 | 25 |

ajax请求错误

26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 | 34 |

js执行错误

35 | 36 |
37 | 38 | 39 |

Promise 错误

40 | 41 |
42 | 43 | 44 | 47 | 48 | 49 |

资源没有加载

50 | 51 | 52 | 53 | 54 |
55 | 56 | 57 |

第三方资源错误

58 | 59 |
60 | 61 | 62 |

销毁实例

63 | 64 |
65 | 66 | 67 | 68 |

rrweb 重播

69 | 70 |
71 | 72 | 73 | 74 | 75 | 93 | 94 | 95 | 96 | 111 | 112 | -------------------------------------------------------------------------------- /coverage/lcov-report/error.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Code coverage report for error.js 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 |
17 |
18 |

19 | All files error.js 20 |

21 |
22 |
23 | 0% 24 | Statements 25 | 0/0 26 |
27 |
28 | 0% 29 | Branches 30 | 0/0 31 |
32 |
33 | 0% 34 | Functions 35 | 0/0 36 |
37 |
38 | 0% 39 | Lines 40 | 0/0 41 |
42 |
43 |

44 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 45 |

46 |
47 |
48 |

49 | 
65 | 
1 50 | 2 51 | 3 52 | 4 53 | 5 54 | 6  55 |   56 |   57 |   58 |   59 |  
/**
60 |  * @file error event center
61 |  * @author JYkid
62 |  * @version 0.0.1-beta
63 |  */
64 |  
66 |
67 |
68 | 72 | 73 | 74 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /dist/README.md: -------------------------------------------------------------------------------- 1 | # MonitorFE 2 | 3 | 前端埋点监控SDK,一款开箱即用的前端报错监控的埋点SDK。仅需开发埋点接口即可监控收集整个前端项目在运行的时候产生的js内部报错,资源加载异常,接口返回报错,样式丢失的问题。 4 | 5 | 项目在 SDK 内监听全局 error 错误信息,ajax 错误信息,以及监听资源加载,在页面出现报错的情况下直接向埋点接口上报错误信息,监控前端项目的稳定性。 6 | 7 | ## 设计目的 8 | 9 | 1.方便更多的前端开发快速接入前端埋点。 10 | 11 | 2.为更多中小型的项目增加前端的报错监控。 12 | 13 | 3.作为一款开源产品帮助更多的项目提升稳定性。 14 | 15 | ![MonitorFE](https://github.com/MriLiuJY/monitorFE/blob/master/MonitorFE.gif "MonitorFE") 16 | 17 | ## 使用 18 | 19 | ### 配置项 20 | 21 | 用于传入 `initMonitor` 的配置项。 22 | 23 | |属性|参数|默认值|可选值|说明| 24 | |:----- |:-------|:-----|:-----|----- | 25 | | method | String | POST | POST,GET | 埋点上报请求方法 | 26 | | url | String | - | - | 埋点上报url地址 | 27 | | id | String | - | - | 标识当前用户 | 28 | | record | Boolean | false | - | 是否录制用户操作用于回放 | 29 | 30 | 可以直接 [下载](https://github.com/MriLiuJY/FE-Monitor/releases) SDK 引入自己项目中即可使用。(dist/js)目录下的打包文件。 31 | 32 | ### 引入方式 33 | 34 | **npm 下载** 35 | 36 | ``` 37 | npm install fe-monitor-sdk 38 | ``` 39 | 40 | 或者你可以使用淘宝 NPM 镜像安装: 41 | 42 | ``` 43 | npm install fe-monitor-sdk --registry=https://registry.npm.taobao.org 44 | ``` 45 | 46 | *使用* 47 | 48 | ```js 49 | var initMonitor = require("fe-monitor-sdk"); 50 | 51 | var config = {} 52 | // your config 53 | }; 54 | initMonitor(config, function(monitor) { 55 | // your code... 56 | // 销毁实例 57 | monitor._destory(); 58 | }); 59 | ``` 60 | 61 | 另外,浏览器并不支持 `CommonJS` 规范,因此需要使用 `Browserify` 或者 `Webpack` 等工具进行打包。 62 | 63 | 64 | **js 文件引入** 65 | 66 | 同源的情况下可以直接引入自己的项目中,注意请使用最新的 SDK 以获取更好的效果。 67 | 68 | ```js 69 | 70 | 71 | 81 | ``` 82 | 83 | 如果 JS 放在 CDN 上需要单独引入的情况下需要一些额外的 code 。 84 | 85 | ```js 86 | 104 | ``` 105 | 106 | 项目在v0.0.3 版本之后加入 [rrweb](https://github.com/rrweb-io/rrweb) 录制回放功能,可以通过配置传入 `initMonitor` 的 config 中的 `record` 的值来选择是否开启录制,如果传值为 true 的情况下每次错误都会上报收集到的数据用于回放错误复现。 107 | 108 | ## 项目架构 109 | 110 | 首先v0.1.0版本设计目的是为了做完整的异常监控,使得前端具备资源加载异常,js运行报错,样式丢失,接口返回异常的捕获能力。 111 | 112 | 目录结构: 113 | ``` 114 | ├── config // webpack 配置文件 115 | ├── dist // 打包输出文件目录 116 | ├── public // 公共文件目录 117 | ├── server // server 118 | ├── src // 项目文件目录 119 | ├── test 120 | ``` 121 | 122 | * JS-SDK具备获取平台信息的能力 123 | * 获取报错详情与报错的时间 124 | * 当前的url(完整带参数) 125 | * 用户可以自定义上传的参数 126 | 127 | 128 | ## 开发 129 | 130 | 自动生成changelog 需要在本地下载: 131 | 132 | `npm install -g conventional-changelog-cli` 133 | 134 | 135 | ## License 136 | 137 | [MIT](https://opensource.org/licenses/MIT) 138 | 139 | Copyright (c) 2019 MriLiuJY 140 | -------------------------------------------------------------------------------- /coverage/lcov-report/stateChange.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Code coverage report for stateChange.js 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 |
17 |
18 |

19 | All files stateChange.js 20 |

21 |
22 |
23 | 0% 24 | Statements 25 | 0/0 26 |
27 |
28 | 0% 29 | Branches 30 | 0/0 31 |
32 |
33 | 0% 34 | Functions 35 | 0/0 36 |
37 |
38 | 0% 39 | Lines 40 | 0/0 41 |
42 |
43 |

44 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 45 |

46 |
47 |
48 |

49 | 
65 | 
1 50 | 2 51 | 3 52 | 4 53 | 5 54 | 6  55 |   56 |   57 |   58 |   59 |  
/**
60 |  * @file event center
61 |  * @author JYkid
62 |  * @version 0.0.1-beta
63 |  */
64 |  
66 |
67 |
68 | 72 | 73 | 74 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MonitorFE 2 | 3 | 前端埋点监控SDK,一款开箱即用的前端报错监控的埋点SDK。仅需开发埋点接口即可监控收集整个前端项目在运行的时候产生的js内部报错,资源加载异常,接口返回报错,样式丢失的问题。 4 | 5 | 项目在 SDK 内监听全局 error 错误信息,ajax 错误信息,以及监听资源加载,在页面出现报错的情况下直接向埋点接口上报错误信息,监控前端项目的稳定性。 6 | 7 | [English document](https://github.com/MriLiuJY/monitorFE/blob/master/docs/README_EN.md) 8 | 9 | ## 设计目的 10 | 11 | 1.方便更多的前端开发快速接入前端埋点。 12 | 13 | 2.为更多中小型的项目增加前端的报错监控。 14 | 15 | 3.作为一款开源产品帮助更多的项目提升稳定性。 16 | 17 | ![MonitorFE](https://github.com/MriLiuJY/monitorFE/blob/master/MonitorFE.gif "MonitorFE") 18 | 19 | ## 使用 20 | 21 | ### 配置项 22 | 23 | 用于传入 `initMonitor` 的配置项。 24 | 25 | |属性|参数|默认值|可选值|说明| 26 | |:----- |:-------|:-----|:-----|----- | 27 | | method | String | POST | POST,GET | 埋点上报请求方法 | 28 | | url | String | - | - | 埋点上报url地址 | 29 | | id | String | - | - | 标识当前用户 | 30 | | record | Boolean | false | - | 是否录制用户操作用于回放 | 31 | 32 | 可以直接 [下载](https://github.com/MriLiuJY/FE-Monitor/releases) SDK 引入自己项目中即可使用。(dist/js)目录下的打包文件。 33 | 34 | ### 引入方式 35 | 36 | **npm 下载** 37 | 38 | ``` 39 | npm install fe-monitor-sdk 40 | ``` 41 | 42 | 或者你可以使用淘宝 NPM 镜像安装: 43 | 44 | ``` 45 | npm install fe-monitor-sdk --registry=https://registry.npm.taobao.org 46 | ``` 47 | 48 | *使用* 49 | 50 | ```js 51 | var initMonitor = require("fe-monitor-sdk"); 52 | 53 | var config = {} 54 | // your config 55 | }; 56 | initMonitor(config, function(monitor) { 57 | // your code... 58 | // 销毁实例 59 | monitor._destory(); 60 | }); 61 | ``` 62 | 63 | 另外,浏览器并不支持 `CommonJS` 规范,因此需要使用 `Browserify` 或者 `Webpack` 等工具进行打包。 64 | 65 | 66 | **js 文件引入** 67 | 68 | 同源的情况下可以直接引入自己的项目中,注意请使用最新的 SDK 以获取更好的效果。 69 | 70 | ```js 71 | 72 | 73 | 83 | ``` 84 | 85 | 如果 JS 放在 CDN 上需要单独引入的情况下需要一些额外的 code 。 86 | 87 | ```js 88 | 106 | ``` 107 | 108 | 项目在v0.0.3 版本之后加入 [rrweb](https://github.com/rrweb-io/rrweb) 录制回放功能,可以通过配置传入 `initMonitor` 的 config 中的 `record` 的值来选择是否开启录制,如果传值为 true 的情况下每次错误都会上报收集到的数据用于回放错误复现。 109 | 110 | 请注意开启 rrweb 会有部分兼容问题请注意: 111 | 112 | > 由于使用 `MutationObserver` API,rrweb 不支持 IE11 以下的浏览器。可以从[这里](https://caniuse.com/#feat=mutationobserver)找到兼容的浏览器列表。 113 | 114 | ## 项目架构 115 | 116 | 首先v0.1.0版本设计目的是为了做完整的异常监控,使得前端具备资源加载异常,js运行报错,样式丢失,接口返回异常的捕获能力。 117 | 118 | 目录结构: 119 | ``` 120 | ├── config // webpack 配置文件 121 | ├── dist // 打包输出文件目录 122 | ├── public // 公共文件目录 123 | ├── server // server 124 | ├── src // 项目文件目录 125 | ├── test 126 | ``` 127 | 128 | * JS-SDK具备获取平台信息的能力 129 | * 获取报错详情与报错的时间 130 | * 当前的url(完整带参数) 131 | * 用户可以自定义上传的参数 132 | 133 | 134 | ## 开发 135 | 136 | 自动生成changelog 需要在本地下载: 137 | 138 | `npm install -g conventional-changelog-cli` 139 | 140 | 141 | ## License 142 | 143 | [MIT](https://opensource.org/licenses/MIT) 144 | 145 | Copyright (c) 2019 MriLiuJY 146 | -------------------------------------------------------------------------------- /docs/README_ZH.md: -------------------------------------------------------------------------------- 1 | # MonitorFE 2 | 3 | 前端埋点监控SDK,一款开箱即用的前端报错监控的埋点SDK。仅需开发埋点接口即可监控收集整个前端项目在运行的时候产生的js内部报错,资源加载异常,接口返回报错,样式丢失的问题。 4 | 5 | 项目在 SDK 内监听全局 error 错误信息,ajax 错误信息,以及监听资源加载,在页面出现报错的情况下直接向埋点接口上报错误信息,监控前端项目的稳定性。 6 | 7 | [English document](https://github.com/MriLiuJY/monitorFE/blob/master/docs/README_EN.md) 8 | 9 | ## 设计目的 10 | 11 | 1.方便更多的前端开发快速接入前端埋点。 12 | 13 | 2.为更多中小型的项目增加前端的报错监控。 14 | 15 | 3.作为一款开源产品帮助更多的项目提升稳定性。 16 | 17 | ![MonitorFE](https://github.com/MriLiuJY/monitorFE/blob/master/MonitorFE.gif "MonitorFE") 18 | 19 | ## 使用 20 | 21 | ### 配置项 22 | 23 | 用于传入 `initMonitor` 的配置项。 24 | 25 | |属性|参数|默认值|可选值|说明| 26 | |:----- |:-------|:-----|:-----|----- | 27 | | method | String | POST | POST,GET | 埋点上报请求方法 | 28 | | url | String | - | - | 埋点上报url地址 | 29 | | id | String | - | - | 标识当前用户 | 30 | | record | Boolean | false | - | 是否录制用户操作用于回放 | 31 | 32 | 可以直接 [下载](https://github.com/MriLiuJY/FE-Monitor/releases) SDK 引入自己项目中即可使用。(dist/js)目录下的打包文件。 33 | 34 | ### 引入方式 35 | 36 | **npm 下载** 37 | 38 | ``` 39 | npm install fe-monitor-sdk 40 | ``` 41 | 42 | 或者你可以使用淘宝 NPM 镜像安装: 43 | 44 | ``` 45 | npm install fe-monitor-sdk --registry=https://registry.npm.taobao.org 46 | ``` 47 | 48 | *使用* 49 | 50 | ```js 51 | var initMonitor = require("fe-monitor-sdk"); 52 | 53 | var config = {} 54 | // your config 55 | }; 56 | initMonitor(config, function(monitor) { 57 | // your code... 58 | // 销毁实例 59 | monitor._destory(); 60 | }); 61 | ``` 62 | 63 | 另外,浏览器并不支持 `CommonJS` 规范,因此需要使用 `Browserify` 或者 `Webpack` 等工具进行打包。 64 | 65 | 66 | **js 文件引入** 67 | 68 | 同源的情况下可以直接引入自己的项目中,注意请使用最新的 SDK 以获取更好的效果。 69 | 70 | ```js 71 | 72 | 73 | 83 | ``` 84 | 85 | 如果 JS 放在 CDN 上需要单独引入的情况下需要一些额外的 code 。 86 | 87 | ```js 88 | 106 | ``` 107 | 108 | 项目在v0.0.3 版本之后加入 [rrweb](https://github.com/rrweb-io/rrweb) 录制回放功能,可以通过配置传入 `initMonitor` 的 config 中的 `record` 的值来选择是否开启录制,如果传值为 true 的情况下每次错误都会上报收集到的数据用于回放错误复现。 109 | 110 | 请注意开启 rrweb 会有部分兼容问题请注意: 111 | 112 | > 由于使用 `MutationObserver` API,rrweb 不支持 IE11 以下的浏览器。可以从[这里](https://caniuse.com/#feat=mutationobserver)找到兼容的浏览器列表。 113 | 114 | ## 项目架构 115 | 116 | 首先v0.1.0版本设计目的是为了做完整的异常监控,使得前端具备资源加载异常,js运行报错,样式丢失,接口返回异常的捕获能力。 117 | 118 | 目录结构: 119 | ``` 120 | ├── config // webpack 配置文件 121 | ├── dist // 打包输出文件目录 122 | ├── public // 公共文件目录 123 | ├── server // server 124 | ├── src // 项目文件目录 125 | ├── test 126 | ``` 127 | 128 | * JS-SDK具备获取平台信息的能力 129 | * 获取报错详情与报错的时间 130 | * 当前的url(完整带参数) 131 | * 用户可以自定义上传的参数 132 | 133 | 134 | ## 开发 135 | 136 | 自动生成changelog 需要在本地下载: 137 | 138 | `npm install -g conventional-changelog-cli` 139 | 140 | 141 | ## License 142 | 143 | [MIT](https://opensource.org/licenses/MIT) 144 | 145 | Copyright (c) 2019 MriLiuJY 146 | -------------------------------------------------------------------------------- /coverage/lcov-report/config.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Code coverage report for config.js 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 |
17 |
18 |

19 | All files config.js 20 |

21 |
22 |
23 | 0% 24 | Statements 25 | 0/0 26 |
27 |
28 | 0% 29 | Branches 30 | 0/0 31 |
32 |
33 | 0% 34 | Functions 35 | 0/1 36 |
37 |
38 | 0% 39 | Lines 40 | 0/0 41 |
42 |
43 |

44 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 45 |

46 |
47 |
48 |

49 | 
74 | 
1 50 | 2 51 | 3 52 | 4 53 | 5 54 | 6 55 | 7 56 | 8 57 | 9  58 |   59 |   60 |   61 |   62 |   63 |   64 |   65 |  
/**
66 |  * @file config detail file
67 |  * @author JYkid
68 |  * @version 0.0.1-beta
69 |  */
70 |  
71 | function Config(conf) {
72 |   
73 | }
75 |
76 |
77 | 81 | 82 | 83 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at mriliujy@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /createError.js: -------------------------------------------------------------------------------- 1 | 2 | // ----- ajax请求错误 ---- 3 | 4 | // ajax请求错误 5 | var ajaxRequestError = document.getElementsByClassName("err-ajax-request")[0]; 6 | ajaxRequestError.onclick = function () { 7 | var xhr = new XMLHttpRequest(); 8 | xhr.withCredentials = true; 9 | xhr.timeout = 3000; 10 | xhr.open("get", '/ajaxerror', true); 11 | xhr.setRequestHeader("content-type", "application/json;charset=utf-8"); 12 | xhr.setRequestHeader("Accept", "application/json"); 13 | xhr.send(); 14 | } 15 | 16 | // server 500 error 17 | var servererrAjax = document.getElementsByClassName("servererr-ajax-request")[0]; 18 | servererrAjax.onclick = function () { 19 | var xhr = new XMLHttpRequest(); 20 | xhr.withCredentials = true; 21 | xhr.timeout = 3000; 22 | xhr.open("get", '/servererr', true); 23 | xhr.setRequestHeader("content-type", "application/json;charset=utf-8"); 24 | xhr.setRequestHeader("Accept", "application/json"); 25 | xhr.send(); 26 | } 27 | 28 | // ajax失败 29 | var ajaxFailed = document.getElementsByClassName("fail-ajax-request")[0]; 30 | ajaxFailed.onclick = function () { 31 | var xhr = new XMLHttpRequest(); 32 | xhr.withCredentials = true; 33 | xhr.timeout = 3000; 34 | xhr.open("get", '/servererr', true); 35 | xhr.setRequestHeader("content-type", "application/json;charset=utf-8"); 36 | xhr.setRequestHeader("Accept", "application/json"); 37 | xhr.send(); 38 | } 39 | 40 | // ajax请求超时 41 | var ajaxTimeout = document.getElementsByClassName("timeout-ajax-request")[0]; 42 | ajaxTimeout.onclick = function () { 43 | var xhr = new XMLHttpRequest(); 44 | xhr.withCredentials = true; 45 | xhr.timeout = 3000; 46 | xhr.open("get", '/timeout', true); 47 | xhr.setRequestHeader("content-type", "application/json;charset=utf-8"); 48 | xhr.setRequestHeader("Accept", "application/json"); 49 | xhr.send(); 50 | } 51 | 52 | 53 | // ----- js 执行错误 ---- 54 | 55 | // js 执行错误 56 | var jsRunningerror = document.getElementsByClassName("js-running-error")[0]; 57 | jsRunningerror.onclick = function () { 58 | jsRunningerrorssss; 59 | } 60 | 61 | // Promise 错误 62 | var promiseError = document.getElementsByClassName("promise-error")[0]; 63 | promiseError.onclick = function () { 64 | new Promise((resolve, reject) => { 65 | reject(); 66 | }) 67 | } 68 | 69 | 70 | // ----- 资源加载异常 ---- 71 | 72 | // js 73 | var jsload = document.getElementsByClassName("err-js-load")[0]; 74 | jsload.onclick = function () { 75 | var script = document.createElement("script"); 76 | script.src = `./js/undefied.js`; 77 | document.body.appendChild(script); 78 | } 79 | 80 | var cssload = document.getElementsByClassName("err-css-load")[0]; 81 | cssload.onclick = function () { 82 | var css = document.createElement("link"); 83 | css.type = `text/css`; 84 | css.rel = 'stylesheet'; 85 | css.href = `./js/undefied.css`; 86 | document.head.appendChild(css); 87 | } 88 | 89 | var imageload = document.getElementsByClassName("err-image-load")[0]; 90 | imageload.onclick = function () { 91 | var img = document.createElement("img"); 92 | img.src = `./js/undefied.png`; 93 | document.body.appendChild(img); 94 | } 95 | 96 | var iframeload = document.getElementsByClassName("err-iframe-load")[0]; 97 | iframeload.onclick = function () { 98 | var iframe = document.createElement("iframe"); 99 | iframe.src = `./js/undefied.html`; 100 | document.body.appendChild(iframe); 101 | } 102 | 103 | 104 | // ------ 第三方资源错误 ------ 105 | var resourceError = document.getElementsByClassName("other-resource-error")[0]; 106 | resourceError.onclick = function () { 107 | var test = document.getElementsByClassName("other-resource-error111")[0]; 108 | test.onclick= function() {}; 109 | } 110 | 111 | // ------ 销毁实例 ------ 112 | var destory = document.getElementsByClassName("destory")[0]; 113 | destory.onclick = function () { 114 | window.monitor._destory(); 115 | } 116 | -------------------------------------------------------------------------------- /src/wrap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file get browser && platform parameter 3 | * @author JYkid 4 | * @version 0.0.1-beta 5 | */ 6 | 7 | /* eslint-disable */ 8 | function Wrap() { 9 | const self = this; 10 | self.data = self._geWrap(); 11 | } 12 | 13 | Wrap.prototype = { 14 | // 获取 UA 基本信息 15 | _geWrap: function() { 16 | let data = {}; 17 | let navigator = window.navigator; 18 | 19 | // UA 20 | data.userAgent = navigator.userAgent; 21 | 22 | // appName 23 | data.appName= navigator.appName; 24 | 25 | // appVersion 26 | data.appVersion = navigator.appVersion; 27 | 28 | // CPU 29 | data.cpuClass = navigator.cpuClass; 30 | 31 | // platform 32 | data.platform = navigator.platform; 33 | 34 | // product 35 | data.product = navigator.product; 36 | 37 | // languages 38 | data.language = navigator.language; 39 | 40 | // url 41 | data.url = window.location.href; 42 | 43 | // time 44 | data.time = (new Date()).getTime(); 45 | 46 | return data; 47 | }, 48 | // webrtc 获取 IP 49 | _getIP: function(onNewIP) { 50 | var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; 51 | var pc = new myPeerConnection({ 52 | iceServers: [ 53 | { 54 | urls: "stun:stun01.sipphone.com" 55 | }, 56 | { 57 | urls: "stun:stun.ekiga.net" 58 | }, 59 | { 60 | urls: "stun:stun.fwdnet.net" 61 | }, 62 | { 63 | urls: "stun:stun.l.google.com:19302" 64 | }, 65 | { 66 | urls: "stun:stun.l.google.com:19302" 67 | }, 68 | { 69 | urls: "stun:stun.l.google.com:19302" 70 | } 71 | ] 72 | }), 73 | noop = function() {}, 74 | localIPs = {}, 75 | ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g; 76 | 77 | function iterateIP(ip) { 78 | if (!localIPs[ip]) { 79 | onNewIP(ip); 80 | } 81 | localIPs[ip] = true; 82 | } 83 | 84 | //create a bogus data channel 85 | pc.createDataChannel(""); 86 | 87 | // create offer and set local description 88 | pc.createOffer().then(function(sdp) { 89 | sdp.sdp.split('\n').forEach(function(line) { 90 | if (line.indexOf('candidate') < 0) return; 91 | line.match(ipRegex).forEach(iterateIP); 92 | }); 93 | 94 | pc.setLocalDescription(sdp, noop, noop); 95 | }).catch(function(reason) { 96 | // An error occurred, so handle the failure to connect 97 | }); 98 | 99 | //listen for candidate events 100 | pc.onicecandidate = function(ice) { 101 | if (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return; 102 | ice.candidate.candidate.match(ipRegex).forEach(iterateIP); 103 | }; 104 | }, 105 | // 处理错误信息 106 | _getErrorMessage: function(err, resource) { 107 | const self = this; 108 | let data = self._geWrap(); 109 | self._getIP(function(ip) { 110 | data.ip = ip; 111 | }); 112 | data.detail = {}; 113 | if (err.type === "ajaxLoad") { 114 | data.detail.responseURL = err.detail.responseURL; 115 | data.detail.status = err.detail.status; 116 | data.detail.statusText = err.detail.statusText; 117 | data.detail.type = "ajaxLoad"; 118 | } else if (err.type === "error") { 119 | data.detail.message = err.message; 120 | data.detail.line = err.lineno; 121 | data.detail.filename = err.filename; 122 | data.detail.type = "error"; 123 | } else if (resource) { 124 | data.detail.src = err.target.src; 125 | data.detail.type = "resource"; 126 | } 127 | // data.jsStack = self._getCallStack(); 128 | return data; 129 | }, 130 | _getCallStack() { 131 | var stack = "#", total = 0, fn =arguments.callee; 132 | while ( (fn = fn.caller) ) { 133 | stack = stack + "" + fn.name; 134 | total++ 135 | } 136 | return stack; 137 | }, 138 | } 139 | 140 | module.exports = Wrap; -------------------------------------------------------------------------------- /src/initMonitor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file init func 3 | * @author JYkid 4 | * @version 0.0.1-beta 5 | */ 6 | 7 | import { record } from "rrweb"; 8 | import Config from "./config"; 9 | import { getJsError, geetResourceError, ajaxError } from "./error"; 10 | import EventCenter from "./eventCenter"; 11 | 12 | /* eslint-disable */ 13 | function InitMonitor(userConfig) { 14 | let self = this; 15 | let config = new Config(userConfig); 16 | self._config = config; 17 | 18 | self._config.protocol = window.location.protocol + "//"; 19 | if (config.https) { 20 | self._config.protocol = 'https://'; 21 | } 22 | const eventCenter = new EventCenter(); 23 | self._eventCenter = eventCenter; 24 | 25 | self._initListenJS(); 26 | self._initListenAjax(); 27 | if (userConfig.record) { 28 | self._initRrweb(); 29 | } 30 | } 31 | 32 | InitMonitor.prototype = { 33 | _initListenJS() { 34 | const self = this; 35 | 36 | // 监听全局下的 Promise 错误 37 | let unhandledrejection = function(err){ 38 | getJsError(err, self); 39 | } 40 | window.addEventListener("unhandledrejection", unhandledrejection); 41 | self._setEvent({ 42 | type: "unhandledrejection", 43 | func: unhandledrejection 44 | }); 45 | 46 | // 监听全局下的error事件 47 | let errorEvent = function(err) { 48 | 49 | if (err.cancelable) { 50 | // 判断错误是否来自 monitor 51 | if (err.filename.indexOf('monitor') > -1 || process.env.NODE_ENV === 'development') { 52 | return; 53 | } else { 54 | getJsError(err, self); 55 | } 56 | } else { 57 | // 静态资源加载的error事件 58 | geetResourceError(err, self); 59 | } 60 | } 61 | window.addEventListener("error", errorEvent, true); 62 | self._setEvent({ 63 | type: "error", 64 | func: errorEvent 65 | }); 66 | }, 67 | _initListenAjax () { 68 | let self = this; 69 | function ajaxEventTrigger(event) { 70 | var ajaxEvent = new CustomEvent(event, { detail: this }); 71 | window.dispatchEvent(ajaxEvent); 72 | }; 73 | 74 | var oldXHR = window.XMLHttpRequest; 75 | 76 | function newXHR() { 77 | var realXHR = new oldXHR(); 78 | 79 | realXHR.addEventListener('load', function () { 80 | ajaxEventTrigger.call(this, 'ajaxLoad'); 81 | }, false); 82 | 83 | realXHR.addEventListener('timeout', function () { 84 | ajaxEventTrigger.call(this, 'ajaxTimeout'); 85 | }, false); 86 | 87 | realXHR.addEventListener('readystatechange', function() { 88 | ajaxEventTrigger.call(this, 'ajaxReadyStateChange'); 89 | }, false); 90 | 91 | return realXHR; 92 | }; 93 | 94 | window.XMLHttpRequest = newXHR; 95 | self._startLintenAjax(); 96 | }, 97 | _startLintenAjax() { 98 | const self = this; 99 | 100 | // ajax timeout 101 | let ajaxTimeout = function(err) { 102 | !(err.detail.responseURL.indexOf(self._config.url) > -1) && ajaxError(err, self); 103 | }; 104 | window.addEventListener("ajaxTimeout", ajaxTimeout); 105 | self._setEvent({ 106 | type: "ajaxTimeout", 107 | func: ajaxTimeout 108 | }); 109 | 110 | // ajax load error 111 | let ajaxLoad = function(err) { 112 | !(err.detail.responseURL.indexOf(self._config.url) > -1) && ajaxError(err, self); 113 | } 114 | window.addEventListener("ajaxLoad", ajaxLoad); 115 | self._setEvent({ 116 | type: "ajaxLoad", 117 | func: ajaxLoad 118 | }); 119 | }, 120 | _getEvent() { 121 | const self = this; 122 | return self._eventCenter._get(); 123 | }, 124 | _getRrwebEvent() { 125 | const self = this; 126 | return self._eventCenter._getRecord(); 127 | }, 128 | _setEvent: function(event) { 129 | const self = this; 130 | self._eventCenter._set(event); 131 | }, 132 | /** 133 | * clear rrweb event 134 | */ 135 | _clearEvent() { 136 | const self = this; 137 | self._eventCenter._clearRecord(); 138 | }, 139 | /** 140 | * init rrweb 141 | */ 142 | _initRrweb() { 143 | const self = this; 144 | /** 145 | * init record function to record event in browser 146 | * @event mouseevent 147 | * @param { Object } event 148 | */ 149 | record({ 150 | emit(event) { 151 | self._eventCenter._setRecord(event); 152 | } 153 | }); 154 | } 155 | } 156 | 157 | module.exports = InitMonitor; -------------------------------------------------------------------------------- /coverage/lcov-report/index.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Code coverage report for index.js 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 |
17 |
18 |

19 | All files index.js 20 |

21 |
22 |
23 | 100% 24 | Statements 25 | 4/4 26 |
27 |
28 | 100% 29 | Branches 30 | 0/0 31 |
32 |
33 | 100% 34 | Functions 35 | 1/1 36 |
37 |
38 | 100% 39 | Lines 40 | 4/4 41 |
42 |
43 |

44 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 45 |

46 |
47 |
48 |

 49 | 
 98 | 
1 50 | 2 51 | 3 52 | 4 53 | 5 54 | 6 55 | 7 56 | 8 57 | 9 58 | 10 59 | 11 60 | 12 61 | 13 62 | 14 63 | 15 64 | 16 65 | 17  66 |   67 |   68 |   69 |   70 |   71 |   72 |   73 |   74 | 1x 75 | 1x 76 |   77 |   78 | 1x 79 |   80 | 1x 81 |  
/**
 82 |  * @file main js at project
 83 |  * @author JYkid
 84 |  * @version 0.0.1-beta
 85 |  */
 86 |  
 87 |  
 88 | /* eslint-disable */
 89 | function initMonitor(config) {
 90 |   console.log(config);
 91 |   return config + 1;
 92 | }
 93 |  
 94 | window.initMonitor = initMonitor;
 95 |  
 96 | module.exports = initMonitor;
 97 |  
99 |
100 |
101 | 105 | 106 | 107 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /docs/README_EN.md: -------------------------------------------------------------------------------- 1 | # MonitorFE 2 | 3 | The front-end buried point monitoring SDK, an out-of-the-box front-end error monitoring buried point SDK. Only need to develop the buried interface to monitor and collect the internal error of the js generated during the running of the entire front-end project, the resource loading is abnormal, the interface returns an error, and the style is lost. 4 | 5 | The project listens for global error error information, ajax error information, and listener resource loading in the SDK. When an error occurs on the page, the error message is directly reported to the buried interface to monitor the stability of the front-end project. 6 | 7 | [中文文档](https://github.com/MriLiuJY/monitorFE/blob/master/docs/README_ZH.md) 8 | 9 | ## aim of design 10 | 11 | 1. Convenient for more front-end development and quick access to the front-end buried point. 12 | 13 | 2. Increase front-end error monitoring for more small and medium-sized projects. 14 | 15 | 3. As an open source product to help more projects improve stability. 16 | 17 | ![MonitorFE](https://github.com/MriLiuJY/monitorFE/blob/master/MonitorFE.gif "MonitorFE") 18 | 19 | ## Use 20 | 21 | ### Configuration Item 22 | 23 | A configuration item for passing in `initMonitor`. 24 | 25 | |Attributes|Parameters|Defaults|Optional Values|Description| 26 | |:----- |:-------|:-----|:-----|----- | 27 | | method | String | POST | POST,GET | Buried Point Reporting Request Method | 28 | | url | String | - | - | Buried point report url address | 29 | | id | String | - | - | Identifies the current user | 30 | | record | Boolean | false | - | Whether to record user actions for playback | 31 | 32 | You can use the [Download](https://github.com/MriLiuJY/FE-Monitor/releases) SDK to bring it into your own project. Package files in the (dist/js) directory. 33 | 34 | ### Introduction method 35 | 36 | **npm download** 37 | 38 | ``` 39 | Npm install fe-monitor-sdk 40 | ``` 41 | 42 | Or you can use the Taobao NPM image to install: 43 | 44 | ``` 45 | Npm install fe-monitor-sdk --registry=https://registry.npm.taobao.org 46 | ``` 47 | 48 | *use* 49 | 50 | ```js 51 | Var initMonitor = require("fe-monitor-sdk"); 52 | 53 | Var config = {} 54 |   // your config 55 | }; 56 | initMonitor(config, function(monitor) { 57 |   // your code... 58 |   // Destroy the instance 59 |   Monitor._destory(); 60 | }); 61 | ``` 62 | 63 | In addition, the browser does not support the `CommonJS` specification, so it needs to be packaged using tools such as `Browserify` or `Webpack`. 64 | 65 | 66 | **js file introduction** 67 | 68 | If you have the same origin, you can directly import it into your own project. Please use the latest SDK for better results. 69 | 70 | ```js 71 | 72 | 73 | 83 | ``` 84 | 85 | If the JS is placed on the CDN and needs to be introduced separately, some extra code is needed. 86 | 87 | ```js 88 | 106 | ``` 107 | 108 | The project adds [rrweb](https://github.com/rrweb-io/rrweb) to the recording playback function after v0.0.3. You can choose whether to pass the value of `record` in the config of `initMonitor`. Turn on recording. If the value is true, the error will report the collected data for playback error replay. 109 | 110 | Please note that there are some compatibility issues when opening rrweb. Please note: 111 | 112 | > Due to the `MutationObserver` API, rrweb does not support browsers below IE11. A list of compatible browsers can be found from [here](https://caniuse.com/#feat=mutationobserver). 113 | 114 | ## Project Architecture 115 | 116 | Firstly, the v0.1.0 version is designed to perform complete exception monitoring, so that the front end has resource loading exceptions, js runs error reporting, style is lost, and the interface returns an abnormal capture capability. 117 | 118 | Directory Structure: 119 | ``` 120 | ├── config // webpack configuration file 121 | ├── dist // package output file directory 122 | ├── public // public file directory 123 | ├── server // server 124 | ├── src // project file directory 125 | ├── test 126 | ``` 127 | 128 | * JS-SDK has the ability to obtain platform information 129 | * Get the details of the error and the time of the error 130 | * Current url (complete with parameters) 131 | * Users can customize the uploaded parameters 132 | 133 | 134 | ## Development 135 | 136 | Automatically generating a changelog needs to be downloaded locally: 137 | 138 | `npm install -g conventional-changelog-cli` 139 | 140 | 141 | ## License 142 | 143 | [MIT](https://opensource.org/licenses/MIT) 144 | 145 | Copyright (c) 2019 MriLiuJY -------------------------------------------------------------------------------- /coverage/coverage-final.json: -------------------------------------------------------------------------------- 1 | {"/Users/jyliu/mycode/FE-Monitor/src/ajax.js": {"path":"/Users/jyliu/mycode/FE-Monitor/src/ajax.js","statementMap":{"0":{"start":{"line":7,"column":14},"end":{"line":40,"column":4}},"1":{"start":{"line":8,"column":2},"end":{"line":39,"column":3}},"2":{"start":{"line":10,"column":6},"end":{"line":10,"column":52}},"3":{"start":{"line":13,"column":16},"end":{"line":13,"column":36}},"4":{"start":{"line":14,"column":6},"end":{"line":14,"column":39}},"5":{"start":{"line":15,"column":6},"end":{"line":15,"column":77}},"6":{"start":{"line":16,"column":6},"end":{"line":16,"column":57}},"7":{"start":{"line":17,"column":6},"end":{"line":17,"column":33}},"8":{"start":{"line":18,"column":6},"end":{"line":18,"column":37}},"9":{"start":{"line":19,"column":6},"end":{"line":24,"column":8}},"10":{"start":{"line":20,"column":21},"end":{"line":20,"column":56}},"11":{"start":{"line":21,"column":8},"end":{"line":23,"column":9}},"12":{"start":{"line":22,"column":10},"end":{"line":22,"column":24}},"13":{"start":{"line":25,"column":6},"end":{"line":36,"column":8}},"14":{"start":{"line":26,"column":8},"end":{"line":35,"column":9}},"15":{"start":{"line":27,"column":10},"end":{"line":34,"column":11}},"16":{"start":{"line":28,"column":25},"end":{"line":28,"column":60}},"17":{"start":{"line":29,"column":12},"end":{"line":31,"column":13}},"18":{"start":{"line":30,"column":14},"end":{"line":30,"column":28}},"19":{"start":{"line":33,"column":12},"end":{"line":33,"column":45}},"20":{"start":{"line":37,"column":6},"end":{"line":37,"column":44}},"21":{"start":{"line":42,"column":0},"end":{"line":44,"column":1}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":7,"column":15},"end":{"line":7,"column":16}},"loc":{"start":{"line":7,"column":26},"end":{"line":40,"column":1}},"line":7},"1":{"name":"(anonymous_1)","decl":{"start":{"line":9,"column":13},"end":{"line":9,"column":14}},"loc":{"start":{"line":9,"column":24},"end":{"line":11,"column":5}},"line":9},"2":{"name":"(anonymous_2)","decl":{"start":{"line":12,"column":10},"end":{"line":12,"column":11}},"loc":{"start":{"line":12,"column":47},"end":{"line":38,"column":5}},"line":12},"3":{"name":"(anonymous_3)","decl":{"start":{"line":19,"column":19},"end":{"line":19,"column":20}},"loc":{"start":{"line":19,"column":31},"end":{"line":24,"column":7}},"line":19},"4":{"name":"(anonymous_4)","decl":{"start":{"line":25,"column":31},"end":{"line":25,"column":32}},"loc":{"start":{"line":25,"column":43},"end":{"line":36,"column":7}},"line":25}},"branchMap":{"0":{"loc":{"start":{"line":10,"column":14},"end":{"line":10,"column":50}},"type":"binary-expr","locations":[{"start":{"line":10,"column":14},"end":{"line":10,"column":35}},{"start":{"line":10,"column":39},"end":{"line":10,"column":50}}],"line":10},"1":{"loc":{"start":{"line":18,"column":20},"end":{"line":18,"column":36}},"type":"binary-expr","locations":[{"start":{"line":18,"column":20},"end":{"line":18,"column":27}},{"start":{"line":18,"column":31},"end":{"line":18,"column":36}}],"line":18},"2":{"loc":{"start":{"line":21,"column":8},"end":{"line":23,"column":9}},"type":"if","locations":[{"start":{"line":21,"column":8},"end":{"line":23,"column":9}},{"start":{"line":21,"column":8},"end":{"line":23,"column":9}}],"line":21},"3":{"loc":{"start":{"line":26,"column":8},"end":{"line":35,"column":9}},"type":"if","locations":[{"start":{"line":26,"column":8},"end":{"line":35,"column":9}},{"start":{"line":26,"column":8},"end":{"line":35,"column":9}}],"line":26},"4":{"loc":{"start":{"line":27,"column":10},"end":{"line":34,"column":11}},"type":"if","locations":[{"start":{"line":27,"column":10},"end":{"line":34,"column":11}},{"start":{"line":27,"column":10},"end":{"line":34,"column":11}}],"line":27},"5":{"loc":{"start":{"line":29,"column":12},"end":{"line":31,"column":13}},"type":"if","locations":[{"start":{"line":29,"column":12},"end":{"line":31,"column":13}},{"start":{"line":29,"column":12},"end":{"line":31,"column":13}}],"line":29}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0]},"hash":"1a6186719c9fc9ac01a33da497b96c1bc56d332f"} 2 | ,"/Users/jyliu/mycode/FE-Monitor/src/config.js": {"path":"/Users/jyliu/mycode/FE-Monitor/src/config.js","statementMap":{},"fnMap":{"0":{"name":"Config","decl":{"start":{"line":7,"column":9},"end":{"line":7,"column":15}},"loc":{"start":{"line":7,"column":22},"end":{"line":9,"column":1}},"line":7}},"branchMap":{},"s":{},"f":{"0":0},"b":{},"hash":"39da93aab67732a303764e4ec08f894dd8bd2321"} 3 | ,"/Users/jyliu/mycode/FE-Monitor/src/error.js": {"path":"/Users/jyliu/mycode/FE-Monitor/src/error.js","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"hash":"2e3a440bcc5d0cb761cfa5d9d80946e6b3929b42"} 4 | ,"/Users/jyliu/mycode/FE-Monitor/src/index.js": {"path":"/Users/jyliu/mycode/FE-Monitor/src/index.js","statementMap":{"0":{"start":{"line":10,"column":2},"end":{"line":10,"column":22}},"1":{"start":{"line":11,"column":2},"end":{"line":11,"column":20}},"2":{"start":{"line":14,"column":0},"end":{"line":14,"column":33}},"3":{"start":{"line":16,"column":0},"end":{"line":16,"column":29}}},"fnMap":{"0":{"name":"initMonitor","decl":{"start":{"line":9,"column":9},"end":{"line":9,"column":20}},"loc":{"start":{"line":9,"column":29},"end":{"line":12,"column":1}},"line":9}},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1},"f":{"0":1},"b":{},"_coverageSchema":"43e27e138ebf9cfc5966b082cf9a028302ed4184","hash":"e2b92b614b38987ba18ed7e3046fb1d373bb9c49"} 5 | ,"/Users/jyliu/mycode/FE-Monitor/src/stateChange.js": {"path":"/Users/jyliu/mycode/FE-Monitor/src/stateChange.js","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"hash":"24ed9a35602110a8a6f5a0494027aac05c66460d"} 6 | } 7 | -------------------------------------------------------------------------------- /coverage/lcov-report/sorter.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var addSorting = (function() { 3 | 'use strict'; 4 | var cols, 5 | currentSort = { 6 | index: 0, 7 | desc: false 8 | }; 9 | 10 | // returns the summary table element 11 | function getTable() { 12 | return document.querySelector('.coverage-summary'); 13 | } 14 | // returns the thead element of the summary table 15 | function getTableHeader() { 16 | return getTable().querySelector('thead tr'); 17 | } 18 | // returns the tbody element of the summary table 19 | function getTableBody() { 20 | return getTable().querySelector('tbody'); 21 | } 22 | // returns the th element for nth column 23 | function getNthColumn(n) { 24 | return getTableHeader().querySelectorAll('th')[n]; 25 | } 26 | 27 | // loads all columns 28 | function loadColumns() { 29 | var colNodes = getTableHeader().querySelectorAll('th'), 30 | colNode, 31 | cols = [], 32 | col, 33 | i; 34 | 35 | for (i = 0; i < colNodes.length; i += 1) { 36 | colNode = colNodes[i]; 37 | col = { 38 | key: colNode.getAttribute('data-col'), 39 | sortable: !colNode.getAttribute('data-nosort'), 40 | type: colNode.getAttribute('data-type') || 'string' 41 | }; 42 | cols.push(col); 43 | if (col.sortable) { 44 | col.defaultDescSort = col.type === 'number'; 45 | colNode.innerHTML = 46 | colNode.innerHTML + ''; 47 | } 48 | } 49 | return cols; 50 | } 51 | // attaches a data attribute to every tr element with an object 52 | // of data values keyed by column name 53 | function loadRowData(tableRow) { 54 | var tableCols = tableRow.querySelectorAll('td'), 55 | colNode, 56 | col, 57 | data = {}, 58 | i, 59 | val; 60 | for (i = 0; i < tableCols.length; i += 1) { 61 | colNode = tableCols[i]; 62 | col = cols[i]; 63 | val = colNode.getAttribute('data-value'); 64 | if (col.type === 'number') { 65 | val = Number(val); 66 | } 67 | data[col.key] = val; 68 | } 69 | return data; 70 | } 71 | // loads all row data 72 | function loadData() { 73 | var rows = getTableBody().querySelectorAll('tr'), 74 | i; 75 | 76 | for (i = 0; i < rows.length; i += 1) { 77 | rows[i].data = loadRowData(rows[i]); 78 | } 79 | } 80 | // sorts the table using the data for the ith column 81 | function sortByIndex(index, desc) { 82 | var key = cols[index].key, 83 | sorter = function(a, b) { 84 | a = a.data[key]; 85 | b = b.data[key]; 86 | return a < b ? -1 : a > b ? 1 : 0; 87 | }, 88 | finalSorter = sorter, 89 | tableBody = document.querySelector('.coverage-summary tbody'), 90 | rowNodes = tableBody.querySelectorAll('tr'), 91 | rows = [], 92 | i; 93 | 94 | if (desc) { 95 | finalSorter = function(a, b) { 96 | return -1 * sorter(a, b); 97 | }; 98 | } 99 | 100 | for (i = 0; i < rowNodes.length; i += 1) { 101 | rows.push(rowNodes[i]); 102 | tableBody.removeChild(rowNodes[i]); 103 | } 104 | 105 | rows.sort(finalSorter); 106 | 107 | for (i = 0; i < rows.length; i += 1) { 108 | tableBody.appendChild(rows[i]); 109 | } 110 | } 111 | // removes sort indicators for current column being sorted 112 | function removeSortIndicators() { 113 | var col = getNthColumn(currentSort.index), 114 | cls = col.className; 115 | 116 | cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); 117 | col.className = cls; 118 | } 119 | // adds sort indicators for current column being sorted 120 | function addSortIndicators() { 121 | getNthColumn(currentSort.index).className += currentSort.desc 122 | ? ' sorted-desc' 123 | : ' sorted'; 124 | } 125 | // adds event listeners for all sorter widgets 126 | function enableUI() { 127 | var i, 128 | el, 129 | ithSorter = function ithSorter(i) { 130 | var col = cols[i]; 131 | 132 | return function() { 133 | var desc = col.defaultDescSort; 134 | 135 | if (currentSort.index === i) { 136 | desc = !currentSort.desc; 137 | } 138 | sortByIndex(i, desc); 139 | removeSortIndicators(); 140 | currentSort.index = i; 141 | currentSort.desc = desc; 142 | addSortIndicators(); 143 | }; 144 | }; 145 | for (i = 0; i < cols.length; i += 1) { 146 | if (cols[i].sortable) { 147 | // add the click event handler on the th so users 148 | // dont have to click on those tiny arrows 149 | el = getNthColumn(i).querySelector('.sorter').parentElement; 150 | if (el.addEventListener) { 151 | el.addEventListener('click', ithSorter(i)); 152 | } else { 153 | el.attachEvent('onclick', ithSorter(i)); 154 | } 155 | } 156 | } 157 | } 158 | // adds sorting functionality to the UI 159 | return function() { 160 | if (!getTable()) { 161 | return; 162 | } 163 | cols = loadColumns(); 164 | loadData(); 165 | addSortIndicators(); 166 | enableUI(); 167 | }; 168 | })(); 169 | 170 | window.addEventListener('load', addSorting); 171 | -------------------------------------------------------------------------------- /coverage/lcov-report/base.css: -------------------------------------------------------------------------------- 1 | body, html { 2 | margin:0; padding: 0; 3 | height: 100%; 4 | } 5 | body { 6 | font-family: Helvetica Neue, Helvetica, Arial; 7 | font-size: 14px; 8 | color:#333; 9 | } 10 | .small { font-size: 12px; } 11 | *, *:after, *:before { 12 | -webkit-box-sizing:border-box; 13 | -moz-box-sizing:border-box; 14 | box-sizing:border-box; 15 | } 16 | h1 { font-size: 20px; margin: 0;} 17 | h2 { font-size: 14px; } 18 | pre { 19 | font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; 20 | margin: 0; 21 | padding: 0; 22 | -moz-tab-size: 2; 23 | -o-tab-size: 2; 24 | tab-size: 2; 25 | } 26 | a { color:#0074D9; text-decoration:none; } 27 | a:hover { text-decoration:underline; } 28 | .strong { font-weight: bold; } 29 | .space-top1 { padding: 10px 0 0 0; } 30 | .pad2y { padding: 20px 0; } 31 | .pad1y { padding: 10px 0; } 32 | .pad2x { padding: 0 20px; } 33 | .pad2 { padding: 20px; } 34 | .pad1 { padding: 10px; } 35 | .space-left2 { padding-left:55px; } 36 | .space-right2 { padding-right:20px; } 37 | .center { text-align:center; } 38 | .clearfix { display:block; } 39 | .clearfix:after { 40 | content:''; 41 | display:block; 42 | height:0; 43 | clear:both; 44 | visibility:hidden; 45 | } 46 | .fl { float: left; } 47 | @media only screen and (max-width:640px) { 48 | .col3 { width:100%; max-width:100%; } 49 | .hide-mobile { display:none!important; } 50 | } 51 | 52 | .quiet { 53 | color: #7f7f7f; 54 | color: rgba(0,0,0,0.5); 55 | } 56 | .quiet a { opacity: 0.7; } 57 | 58 | .fraction { 59 | font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; 60 | font-size: 10px; 61 | color: #555; 62 | background: #E8E8E8; 63 | padding: 4px 5px; 64 | border-radius: 3px; 65 | vertical-align: middle; 66 | } 67 | 68 | div.path a:link, div.path a:visited { color: #333; } 69 | table.coverage { 70 | border-collapse: collapse; 71 | margin: 10px 0 0 0; 72 | padding: 0; 73 | } 74 | 75 | table.coverage td { 76 | margin: 0; 77 | padding: 0; 78 | vertical-align: top; 79 | } 80 | table.coverage td.line-count { 81 | text-align: right; 82 | padding: 0 5px 0 20px; 83 | } 84 | table.coverage td.line-coverage { 85 | text-align: right; 86 | padding-right: 10px; 87 | min-width:20px; 88 | } 89 | 90 | table.coverage td span.cline-any { 91 | display: inline-block; 92 | padding: 0 5px; 93 | width: 100%; 94 | } 95 | .missing-if-branch { 96 | display: inline-block; 97 | margin-right: 5px; 98 | border-radius: 3px; 99 | position: relative; 100 | padding: 0 4px; 101 | background: #333; 102 | color: yellow; 103 | } 104 | 105 | .skip-if-branch { 106 | display: none; 107 | margin-right: 10px; 108 | position: relative; 109 | padding: 0 4px; 110 | background: #ccc; 111 | color: white; 112 | } 113 | .missing-if-branch .typ, .skip-if-branch .typ { 114 | color: inherit !important; 115 | } 116 | .coverage-summary { 117 | border-collapse: collapse; 118 | width: 100%; 119 | } 120 | .coverage-summary tr { border-bottom: 1px solid #bbb; } 121 | .keyline-all { border: 1px solid #ddd; } 122 | .coverage-summary td, .coverage-summary th { padding: 10px; } 123 | .coverage-summary tbody { border: 1px solid #bbb; } 124 | .coverage-summary td { border-right: 1px solid #bbb; } 125 | .coverage-summary td:last-child { border-right: none; } 126 | .coverage-summary th { 127 | text-align: left; 128 | font-weight: normal; 129 | white-space: nowrap; 130 | } 131 | .coverage-summary th.file { border-right: none !important; } 132 | .coverage-summary th.pct { } 133 | .coverage-summary th.pic, 134 | .coverage-summary th.abs, 135 | .coverage-summary td.pct, 136 | .coverage-summary td.abs { text-align: right; } 137 | .coverage-summary td.file { white-space: nowrap; } 138 | .coverage-summary td.pic { min-width: 120px !important; } 139 | .coverage-summary tfoot td { } 140 | 141 | .coverage-summary .sorter { 142 | height: 10px; 143 | width: 7px; 144 | display: inline-block; 145 | margin-left: 0.5em; 146 | background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; 147 | } 148 | .coverage-summary .sorted .sorter { 149 | background-position: 0 -20px; 150 | } 151 | .coverage-summary .sorted-desc .sorter { 152 | background-position: 0 -10px; 153 | } 154 | .status-line { height: 10px; } 155 | /* yellow */ 156 | .cbranch-no { background: yellow !important; color: #111; } 157 | /* dark red */ 158 | .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } 159 | .low .chart { border:1px solid #C21F39 } 160 | .highlighted, 161 | .highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ 162 | background: #C21F39 !important; 163 | } 164 | /* medium red */ 165 | .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } 166 | /* light red */ 167 | .low, .cline-no { background:#FCE1E5 } 168 | /* light green */ 169 | .high, .cline-yes { background:rgb(230,245,208) } 170 | /* medium green */ 171 | .cstat-yes { background:rgb(161,215,106) } 172 | /* dark green */ 173 | .status-line.high, .high .cover-fill { background:rgb(77,146,33) } 174 | .high .chart { border:1px solid rgb(77,146,33) } 175 | /* dark yellow (gold) */ 176 | .status-line.medium, .medium .cover-fill { background: #f9cd0b; } 177 | .medium .chart { border:1px solid #f9cd0b; } 178 | /* light yellow */ 179 | .medium { background: #fff4c2; } 180 | 181 | .cstat-skip { background: #ddd; color: #111; } 182 | .fstat-skip { background: #ddd; color: #111 !important; } 183 | .cbranch-skip { background: #ddd !important; color: #111; } 184 | 185 | span.cline-neutral { background: #eaeaea; } 186 | 187 | .coverage-summary td.empty { 188 | opacity: .5; 189 | padding-top: 4px; 190 | padding-bottom: 4px; 191 | line-height: 1; 192 | color: #888; 193 | } 194 | 195 | .cover-fill, .cover-empty { 196 | display:inline-block; 197 | height: 12px; 198 | } 199 | .chart { 200 | line-height: 0; 201 | } 202 | .cover-empty { 203 | background: white; 204 | } 205 | .cover-full { 206 | border-right: none !important; 207 | } 208 | pre.prettyprint { 209 | border: none !important; 210 | padding: 0 !important; 211 | margin: 0 !important; 212 | } 213 | .com { color: #999 !important; } 214 | .ignore-none { color: #999; font-weight: normal; } 215 | 216 | .wrapper { 217 | min-height: 100%; 218 | height: auto !important; 219 | height: 100%; 220 | margin: 0 auto -48px; 221 | } 222 | .footer, .push { 223 | height: 48px; 224 | } 225 | -------------------------------------------------------------------------------- /dist/js/monitor.0.0.2-beta.js: -------------------------------------------------------------------------------- 1 | !function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(o,r,function(e){return t[e]}.bind(null,r));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="/dist/js/",n(n.s="QfWi")}({"/tra":function(t,e,n){"use strict";function o(){return this.data=[],this}o.prototype={_get(){return this.data},_set(t){this.data.push(t)}},t.exports=o},"20nU":function(t,e,n){"use strict";function o(t){this._extend(this,t)}o.prototype={https:!0,post:!0,url:"/monitor",_extend:(t,e)=>(Object.keys(e).map(n=>{t[n]=e[n]}),t)},t.exports=o},QfWi:function(t,e,n){"use strict";var o,r=(o=n("tjUo"))&&o.__esModule?o:{default:o};!function(t){t.initMonitor||(t.initMonitor=r.default)}(window)},f6yO:function(t,e,n){"use strict";var o=a(n("20nU")),r=n("xziN"),i=a(n("/tra"));function a(t){return t&&t.__esModule?t:{default:t}}function s(t){let e=this,n=new o.default(t);e._config=n,e._config.protocol=window.location.protocol+"//",n.https&&(e._config.protocol="https://");const r=new i.default;e._eventCenter=r,e._initListenJS(),e._initListenAjax()}s.prototype={_initListenJS:function(){const t=this;let e=function(e){(0,r.getJsError)(e,t._config)};window.addEventListener("unhandledrejection",e),t._setEvent({type:"unhandledrejection",func:e});let n=function(e){if(e.cancelable){if(e.filename.indexOf("monitor")>-1)return;(0,r.getJsError)(e,t._config)}else(0,r.geetResourceError)(e,t._config)};window.addEventListener("error",n,!0),t._setEvent({type:"error",func:n})},_initListenAjax:function(){function t(t){var e=new CustomEvent(t,{detail:this});window.dispatchEvent(e)}var e=window.XMLHttpRequest;window.XMLHttpRequest=function(){var n=new e;return n.addEventListener("load",function(){t.call(this,"ajaxLoad")},!1),n.addEventListener("timeout",function(){t.call(this,"ajaxTimeout")},!1),n.addEventListener("readystatechange",function(){t.call(this,"ajaxReadyStateChange")},!1),n},this._startLintenAjax()},_startLintenAjax:function(){const t=this;let e=function(e){!(e.detail.responseURL.indexOf(t._config.url)>-1)&&(0,r.ajaxError)(e,t._config)};window.addEventListener("ajaxTimeout",e),t._setEvent({type:"ajaxTimeout",func:e});let n=function(e){!(e.detail.responseURL.indexOf(t._config.url)>-1)&&(0,r.ajaxError)(e,t._config)};window.addEventListener("ajaxLoad",n),t._setEvent({type:"ajaxLoad",func:n})},_getEvent:function(){return this._eventCenter._get()},_setEvent:function(t){this._eventCenter._set(t)}},t.exports=s},oLOV:function(t,e,n){"use strict";const o={canAjax:function(){return window.XMLHttpRequest&&window.JSON},post:function(t,e,n){var o=new XMLHttpRequest;o.open("post",t,!0),o.setRequestHeader("content-type","application/json;charset=utf-8"),o.setRequestHeader("Accept","application/json"),o.withCredentials=!0,o.timeout=n||3e4,o.onload=function(){1===window.JSON.parse(o.responseText).status&&changeStatus()},o.onreadystatechange=function(){if(4===o.readyState){if(200!==o.status)throw new Error("网络请求错误,请稍后再试~");1===window.JSON.parse(o.responseText).status&&changeStatus()}},o.send(window.JSON.stringify(e))},getWraper:function(t,e,n){(new e)._geWrap()}};t.exports={ajax:o}},"pB/M":function(t,e,n){"use strict";function o(){this.data=this._geWrap()}o.prototype={_geWrap:function(){let t={},e=window.navigator;return t.userAgent=e.userAgent,t.appName=e.appName,t.appVersion=e.appVersion,t.cpuClass=e.cpuClass,t.platform=e.platform,t.product=e.product,t.language=e.language,t.url=window.location.href,t.time=(new Date).getTime(),t},_getIP:function(t){var e=new(window.RTCPeerConnection||window.mozRTCPeerConnection||window.webkitRTCPeerConnection)({iceServers:[{urls:"stun:stun01.sipphone.com"},{urls:"stun:stun.ekiga.net"},{urls:"stun:stun.fwdnet.net"},{urls:"stun:stun.l.google.com:19302"},{urls:"stun:stun.l.google.com:19302"},{urls:"stun:stun.l.google.com:19302"}]}),n=function(){},o={},r=/([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g;function i(e){o[e]||t(e),o[e]=!0}e.createDataChannel(""),e.createOffer().then(function(t){t.sdp.split("\n").forEach(function(t){t.indexOf("candidate")<0||t.match(r).forEach(i)}),e.setLocalDescription(t,n,n)}).catch(function(t){}),e.onicecandidate=function(t){t&&t.candidate&&t.candidate.candidate&&t.candidate.candidate.match(r)&&t.candidate.candidate.match(r).forEach(i)}},_getErrorMessage:function(t,e){let n=this._geWrap();return this._getIP(function(t){n.ip=t}),n.detail={},"ajaxLoad"===t.type?(n.detail.responseURL=t.detail.responseURL,n.detail.status=t.detail.status,n.detail.statusText=t.detail.statusText,n.detail.type="ajaxLoad"):"error"===t.type?(n.detail.message=t.message,n.detail.line=t.lineno,n.detail.filename=t.filename,n.detail.type="error"):e&&(n.detail.src=t.target.src,n.detail.type="resource"),n},_getCallStack(){for(var t="#",e=arguments.callee;e=e.caller;)t=t+""+e.name,0;return t}},t.exports=o},tjUo:function(t,e,n){"use strict";var o=i(n("f6yO")),r=i(n("y11X"));function i(t){return t&&t.__esModule?t:{default:t}}t.exports=function(t,e){const n=new o.default(t);return e(new r.default(n)),n}},xziN:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.geetResourceError=e.getJsError=e.ajaxError=e.getServerError=void 0;var o,r=n("oLOV"),i=(o=n("pB/M"))&&o.__esModule?o:{default:o};e.getServerError=function(){};e.ajaxError=function(t,e){if("ajaxLoad"===t.type&&t.detail.status>=400){let n=(new i.default)._getErrorMessage(t);r.ajax.post(e.protocol+e.url,n,function(){},function(t){console.log(t)})}};e.getJsError=function(t,e){let n=(new i.default)._getErrorMessage(t);r.ajax.post(e.protocol+e.url,n,function(){},function(t){console.log(t)})};e.geetResourceError=function(t,e){let n=(new i.default)._getErrorMessage(t);r.ajax.post(e.protocol+e.url,n,function(){},function(t){console.log(t)})}},y11X:function(t,e,n){"use strict";function o(t){return this._InitMonitor=t,this}o.prototype={_destory:function(){const t=this._InitMonitor._getEvent();for(let e=0;e(Object.keys(e).map(n=>{t[n]=e[n]}),t)},t.exports=o},QfWi:function(t,e,n){"use strict";var o,r=(o=n("tjUo"))&&o.__esModule?o:{default:o};!function(t){t.initMonitor||(t.initMonitor=r.default)}(window)},f6yO:function(t,e,n){"use strict";var o=a(n("20nU")),r=n("xziN"),i=a(n("/tra"));function a(t){return t&&t.__esModule?t:{default:t}}function s(t){let e=this,n=new o.default(t);e._config=n,e._config.protocol=window.location.protocol+"//",n.https&&(e._config.protocol="https://");const r=new i.default;e._eventCenter=r,e._initListenJS(),e._initListenAjax()}s.prototype={_initListenJS:function(){const t=this;let e=function(e){return getError(e,t._config),!0};window.addEventListener("unhandledrejection",e),t._setEvent({type:"unhandledrejection",func:e});let n=function(e){if(e.cancelable){if(e.filename.indexOf("monitor")>-1)return;(0,r.getJsError)(e,t._config)}else(0,r.geetResourceError)(e,t._config)};window.addEventListener("error",n,!0),t._setEvent({type:"error",func:n})},_initListenAjax:function(){function t(t){var e=new CustomEvent(t,{detail:this});window.dispatchEvent(e)}var e=window.XMLHttpRequest;window.XMLHttpRequest=function(){var n=new e;return n.addEventListener("load",function(){t.call(this,"ajaxLoad")},!1),n.addEventListener("timeout",function(){t.call(this,"ajaxTimeout")},!1),n.addEventListener("readystatechange",function(){t.call(this,"ajaxReadyStateChange")},!1),n},this._startLintenAjax()},_startLintenAjax:function(){const t=this;let e=function(e){e.detail.responseURL.indexOf(t._config.url)>-1||(0,r.ajaxError)(e,t._config)};window.addEventListener("ajaxTimeout",e),t._setEvent({type:"ajaxTimeout",func:e});let n=function(e){e.detail.responseURL.indexOf(t._config.url)>-1||(0,r.ajaxError)(e,t._config)};window.addEventListener("ajaxLoad",n),t._setEvent({type:"ajaxLoad",func:n})},_getEvent:function(){return this._eventCenter._get()},_setEvent:function(t){this._eventCenter._set(t)}},t.exports=s},oLOV:function(t,e,n){"use strict";const o={canAjax:function(){return window.XMLHttpRequest&&window.JSON},post:function(t,e,n){var o=new XMLHttpRequest;o.open("post",t,!0),o.setRequestHeader("content-type","application/json;charset=utf-8"),o.setRequestHeader("Accept","application/json"),o.withCredentials=!0,o.timeout=n||3e4,o.onload=function(){1===window.JSON.parse(o.responseText).status&&changeStatus()},o.onreadystatechange=function(){if(4===o.readyState){if(200!==o.status)throw new Error("网络请求错误,请稍后再试~");1===window.JSON.parse(o.responseText).status&&changeStatus()}},o.send(window.JSON.stringify(e))},getWraper:function(t,e,n){(new e)._geWrap()}};t.exports={ajax:o}},"pB/M":function(t,e,n){"use strict";function o(){this.data=this._geWrap()}o.prototype={_geWrap:function(){let t={},e=window.navigator;return t.userAgent=e.userAgent,t.appName=e.appName,t.appVersion=e.appVersion,t.cpuClass=e.cpuClass,t.platform=e.platform,t.product=e.product,t.language=e.language,t.url=window.location.href,t.time=(new Date).getTime(),t},_getIP:function(t){var e=new(window.RTCPeerConnection||window.mozRTCPeerConnection||window.webkitRTCPeerConnection)({iceServers:[{urls:"stun:stun01.sipphone.com"},{urls:"stun:stun.ekiga.net"},{urls:"stun:stun.fwdnet.net"},{urls:"stun:stun.l.google.com:19302"},{urls:"stun:stun.l.google.com:19302"},{urls:"stun:stun.l.google.com:19302"}]}),n=function(){},o={},r=/([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g;function i(e){o[e]||t(e),o[e]=!0}e.createDataChannel(""),e.createOffer().then(function(t){t.sdp.split("\n").forEach(function(t){t.indexOf("candidate")<0||t.match(r).forEach(i)}),e.setLocalDescription(t,n,n)}).catch(function(t){}),e.onicecandidate=function(t){t&&t.candidate&&t.candidate.candidate&&t.candidate.candidate.match(r)&&t.candidate.candidate.match(r).forEach(i)}},_getErrorMessage:function(t,e){let n=this._geWrap();return this._getIP(function(t){n.ip=t}),n.detail={},"ajaxLoad"===t.type?(n.detail.responseURL=t.detail.responseURL,n.detail.status=t.detail.status,n.detail.statusText=t.detail.statusText,n.detail.type="ajaxLoad"):"error"===t.type?(n.detail.message=t.message,n.detail.line=t.lineno,n.detail.filename=t.filename,n.detail.type="error",n.detail.stack=t.error.stack):e&&(n.detail.src=t.target.src,n.detail.type="resource"),n},_getCallStack(){for(var t="#",e=arguments.callee;e=e.caller;)t=t+""+e.name,0;return t}},t.exports=o},tjUo:function(t,e,n){"use strict";var o=i(n("f6yO")),r=i(n("y11X"));function i(t){return t&&t.__esModule?t:{default:t}}t.exports=function(t,e){const n=new o.default(t);return e(new r.default(n)),n}},xziN:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.geetResourceError=e.getJsError=e.ajaxError=e.getServerError=void 0;var o,r=n("oLOV"),i=(o=n("pB/M"))&&o.__esModule?o:{default:o};e.getServerError=function(){};e.ajaxError=function(t,e){if("ajaxLoad"===t.type&&t.detail.status>300){let n=(new i.default)._getErrorMessage(t);r.ajax.post(e.protocol+e.url,n,function(){},function(t){console.log(t)})}};e.getJsError=function(t,e){let n=(new i.default)._getErrorMessage(t);r.ajax.post(e.protocol+e.url,n,function(){},function(t){console.log(t)})};e.geetResourceError=function(t,e){let n=r.ajax.getWraper(t,i.default,!0);r.ajax.post(e.protocol+e.url,n,function(){},function(t){console.log(t)})}},y11X:function(t,e,n){"use strict";function o(t){return this._InitMonitor=t,this}o.prototype={_destory:function(){const t=this._InitMonitor._getEvent();for(let e=0;e 2 | 3 | 4 | Code coverage report for All files 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 |
17 |
18 |

19 | All files 20 |

21 |
22 |
23 | 15.38% 24 | Statements 25 | 4/26 26 |
27 |
28 | 0% 29 | Branches 30 | 0/12 31 |
32 |
33 | 14.29% 34 | Functions 35 | 1/7 36 |
37 |
38 | 15.38% 39 | Lines 40 | 4/26 41 |
42 |
43 |

44 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 45 |

46 |
47 |
48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 |
FileStatementsBranchesFunctionsLines
ajax.js
0%0/220%0/120%0/50%0/22
config.js
0%0/00%0/00%0/10%0/0
error.js
0%0/00%0/00%0/00%0/0
index.js
100%4/4100%0/0100%1/1100%4/4
stateChange.js
0%0/00%0/00%0/00%0/0
131 |
132 |
133 | 137 | 138 | 139 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /coverage/lcov-report/ajax.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Code coverage report for ajax.js 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 |
17 |
18 |

19 | All files ajax.js 20 |

21 |
22 |
23 | 0% 24 | Statements 25 | 0/22 26 |
27 |
28 | 0% 29 | Branches 30 | 0/12 31 |
32 |
33 | 0% 34 | Functions 35 | 0/5 36 |
37 |
38 | 0% 39 | Lines 40 | 0/22 41 |
42 |
43 |

44 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 45 |

46 |
47 |
48 |

 49 | 
182 | 
1 50 | 2 51 | 3 52 | 4 53 | 5 54 | 6 55 | 7 56 | 8 57 | 9 58 | 10 59 | 11 60 | 12 61 | 13 62 | 14 63 | 15 64 | 16 65 | 17 66 | 18 67 | 19 68 | 20 69 | 21 70 | 22 71 | 23 72 | 24 73 | 25 74 | 26 75 | 27 76 | 28 77 | 29 78 | 30 79 | 31 80 | 32 81 | 33 82 | 34 83 | 35 84 | 36 85 | 37 86 | 38 87 | 39 88 | 40 89 | 41 90 | 42 91 | 43 92 | 44 93 | 45  94 |   95 |   96 |   97 |   98 |   99 |   100 |   101 |   102 |   103 |   104 |   105 |   106 |   107 |   108 |   109 |   110 |   111 |   112 |   113 |   114 |   115 |   116 |   117 |   118 |   119 |   120 |   121 |   122 |   123 |   124 |   125 |   126 |   127 |   128 |   129 |   130 |   131 |   132 |   133 |   134 |   135 |   136 |   137 |  
/**
138 |  * @file ajax request file
139 |  * @author JYkid
140 |  * @version 0.0.1-beta
141 |  */
142 |  
143 | const ajax =  (function() {
144 |   return {
145 |     canAjax: function() {
146 |       return (window.XMLHttpRequest && window.JSON);
147 |     },
148 |     post: function(config, url, data, timeout) {
149 |       var xhr = new XMLHttpRequest();
150 |       xhr.open(config.type, url, true);
151 |       xhr.setRequestHeader("content-type", "application/json;charset=utf-8");
152 |       xhr.setRequestHeader("Accept", "application/json");
153 |       xhr.withCredentials = true;
154 |       xhr.timeout = timeout || 30000;
155 |       xhr.onload = function () {
156 |         var result = window.JSON.parse(xhr.responseText);
157 |         if (result.status === 1) {
158 |           changeStatus()
159 |         }
160 |       };
161 |       xhr.onreadystatechange = function () {
162 |         if (xhr.readyState === 4) {
163 |           if (xhr.status === 200) {
164 |             var result = window.JSON.parse(xhr.responseText);
165 |             if (result.status === 1) {
166 |               changeStatus()
167 |             }
168 |           } else {
169 |             throw new Error("网络请求错误,请稍后再试~");
170 |           }
171 |         }
172 |       };
173 |       xhr.send(window.JSON.stringify(data));
174 |     } 
175 |   }
176 | })();
177 |  
178 | module.exports = {
179 |   ajax,
180 | }
181 |  
183 |
184 |
185 | 189 | 190 | 191 | 198 | 199 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /coverage/lcov-report/prettify.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /dist/js/monitor.0.0.1-beta.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 40 | /******/ } 41 | /******/ }; 42 | /******/ 43 | /******/ // define __esModule on exports 44 | /******/ __webpack_require__.r = function(exports) { 45 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 46 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 47 | /******/ } 48 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 49 | /******/ }; 50 | /******/ 51 | /******/ // create a fake namespace object 52 | /******/ // mode & 1: value is a module id, require it 53 | /******/ // mode & 2: merge all properties of value into the ns 54 | /******/ // mode & 4: return value when already ns object 55 | /******/ // mode & 8|1: behave like require 56 | /******/ __webpack_require__.t = function(value, mode) { 57 | /******/ if(mode & 1) value = __webpack_require__(value); 58 | /******/ if(mode & 8) return value; 59 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 60 | /******/ var ns = Object.create(null); 61 | /******/ __webpack_require__.r(ns); 62 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 63 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 64 | /******/ return ns; 65 | /******/ }; 66 | /******/ 67 | /******/ // getDefaultExport function for compatibility with non-harmony modules 68 | /******/ __webpack_require__.n = function(module) { 69 | /******/ var getter = module && module.__esModule ? 70 | /******/ function getDefault() { return module['default']; } : 71 | /******/ function getModuleExports() { return module; }; 72 | /******/ __webpack_require__.d(getter, 'a', getter); 73 | /******/ return getter; 74 | /******/ }; 75 | /******/ 76 | /******/ // Object.prototype.hasOwnProperty.call 77 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 78 | /******/ 79 | /******/ // __webpack_public_path__ 80 | /******/ __webpack_require__.p = "/dist/js/"; 81 | /******/ 82 | /******/ 83 | /******/ // Load entry module and return exports 84 | /******/ return __webpack_require__(__webpack_require__.s = "QfWi"); 85 | /******/ }) 86 | /************************************************************************/ 87 | /******/ ({ 88 | 89 | /***/ "20nU": 90 | /***/ (function(module, exports, __webpack_require__) { 91 | 92 | "use strict"; 93 | 94 | 95 | /** 96 | * @file config detail file 97 | * @author JYkid 98 | * @version 0.0.1-beta 99 | */ 100 | function Config(conf) { 101 | const self = this; 102 | 103 | self._extend(self, conf); 104 | } 105 | 106 | Config.prototype = { 107 | https: true, 108 | post: true, 109 | url: "/v1/monitor", 110 | _extend: (self, conf) => { 111 | Object.keys(conf).map(x => { 112 | self[x] = conf[x]; 113 | return; 114 | }); 115 | return self; 116 | } 117 | }; 118 | module.exports = Config; 119 | 120 | /***/ }), 121 | 122 | /***/ "QfWi": 123 | /***/ (function(module, exports, __webpack_require__) { 124 | 125 | "use strict"; 126 | 127 | 128 | var _index = _interopRequireDefault(__webpack_require__("tjUo")); 129 | 130 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 131 | 132 | /** 133 | * @file main js at project 134 | * @author 135 | * @version 0.0.1-beta 136 | */ 137 | function Shell(window, func) { 138 | if (!window.func) { 139 | window.initMonitor = func; 140 | } 141 | } 142 | 143 | Shell(window, _index.default); 144 | 145 | /***/ }), 146 | 147 | /***/ "f6yO": 148 | /***/ (function(module, exports, __webpack_require__) { 149 | 150 | "use strict"; 151 | 152 | 153 | var _config = _interopRequireDefault(__webpack_require__("20nU")); 154 | 155 | var _error = __webpack_require__("xziN"); 156 | 157 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 158 | 159 | /** 160 | * @file init func 161 | * @author JYkid 162 | * @version 0.0.1-beta 163 | */ 164 | 165 | /* eslint-disable */ 166 | function InitMonitor(userConfig) { 167 | let self = this; 168 | let config = new _config.default(userConfig); 169 | self._config = config; 170 | self._config.protocol = window.location.protocol + "//"; 171 | 172 | if (config.https) { 173 | self._config.protocol = 'https://'; 174 | } 175 | 176 | self._initListenJS(); 177 | 178 | self._initListenAjax(); 179 | } 180 | 181 | InitMonitor.prototype = { 182 | _initListenJS: function () { 183 | const self = this; // 监听全局下的error事件 184 | 185 | window.addEventListener("error", function (err) { 186 | if (err.filename.indexOf('monitor') > -1 || "production" === 'development') { 187 | return; 188 | } else { 189 | (0, _error.getError)(err, self._config); 190 | } 191 | }, true); // 监听全局下的 Promise 错误 192 | 193 | window.addEventListener("unhandledrejection", function (err) { 194 | (0, _error.getError)(err, self._config); 195 | return true; 196 | }); 197 | }, 198 | _initListenAjax: function () { 199 | let self = this; 200 | 201 | function ajaxEventTrigger(event) { 202 | var ajaxEvent = new CustomEvent(event, { 203 | detail: this 204 | }); 205 | window.dispatchEvent(ajaxEvent); 206 | } 207 | 208 | var oldXHR = window.XMLHttpRequest; 209 | 210 | function newXHR() { 211 | var realXHR = new oldXHR(); 212 | realXHR.addEventListener('load', function ($event) { 213 | ajaxEventTrigger.call(this, 'ajaxLoad'); 214 | }, false); 215 | realXHR.addEventListener('timeout', function () { 216 | ajaxEventTrigger.call(this, 'ajaxTimeout'); 217 | }, false); 218 | realXHR.addEventListener('readystatechange', function () { 219 | ajaxEventTrigger.call(this, 'ajaxReadyStateChange'); 220 | }, false); 221 | return realXHR; 222 | } 223 | 224 | window.XMLHttpRequest = newXHR; 225 | 226 | self._startLintenAjax(); 227 | }, 228 | 229 | _startLintenAjax() { 230 | const self = this; // ajax timeout 231 | 232 | window.addEventListener("ajaxTimeout", function (err) { 233 | if (err.detail.responseURL.indexOf(self._config.url) > -1) { 234 | return; 235 | } else { 236 | (0, _error.ajaxError)(err, self._config); 237 | } 238 | }); // ajax load error 239 | 240 | window.addEventListener("ajaxLoad", function (err) { 241 | if (err.detail.responseURL.indexOf(self._config.url) > -1) { 242 | return; 243 | } else { 244 | (0, _error.ajaxError)(err, self._config); 245 | } 246 | }); 247 | }, 248 | 249 | _send: function () {} 250 | }; 251 | module.exports = InitMonitor; 252 | 253 | /***/ }), 254 | 255 | /***/ "oLOV": 256 | /***/ (function(module, exports, __webpack_require__) { 257 | 258 | "use strict"; 259 | 260 | 261 | /** 262 | * @file ajax request file 263 | * @author JYkid 264 | * @version 0.0.1-beta 265 | */ 266 | 267 | /* eslint-disable */ 268 | const ajax = function () { 269 | return { 270 | canAjax: function () { 271 | return window.XMLHttpRequest && window.JSON; 272 | }, 273 | post: function (url, data, timeout) { 274 | var xhr = new XMLHttpRequest(); 275 | xhr.open("post", url, true); 276 | xhr.setRequestHeader("content-type", "application/json;charset=utf-8"); 277 | xhr.setRequestHeader("Accept", "application/json"); 278 | xhr.withCredentials = true; 279 | xhr.timeout = timeout || 30000; 280 | 281 | xhr.onload = function () { 282 | var result = window.JSON.parse(xhr.responseText); 283 | 284 | if (result.status === 1) { 285 | changeStatus(); 286 | } 287 | }; 288 | 289 | xhr.onreadystatechange = function () { 290 | if (xhr.readyState === 4) { 291 | if (xhr.status === 200) { 292 | var result = window.JSON.parse(xhr.responseText); 293 | 294 | if (result.status === 1) { 295 | changeStatus(); 296 | } 297 | } else { 298 | throw new Error("网络请求错误,请稍后再试~"); 299 | } 300 | } 301 | }; 302 | 303 | xhr.send(window.JSON.stringify(data)); 304 | }, 305 | getWraper: function (err, Wrap, resource) { 306 | let wrap = new Wrap(); 307 | 308 | let data = wrap._geWrap(); 309 | } 310 | }; 311 | }(); 312 | 313 | module.exports = { 314 | ajax 315 | }; 316 | 317 | /***/ }), 318 | 319 | /***/ "pB/M": 320 | /***/ (function(module, exports, __webpack_require__) { 321 | 322 | "use strict"; 323 | 324 | 325 | /** 326 | * @file get browser && platform parameter 327 | * @author JYkid 328 | * @version 0.0.1-beta 329 | */ 330 | 331 | /* eslint-disable */ 332 | function Wrap() { 333 | const self = this; 334 | self.data = self._geWrap(); 335 | } 336 | 337 | Wrap.prototype = { 338 | // 获取 UA 基本信息 339 | _geWrap: function () { 340 | let data = {}; 341 | let navigator = window.navigator; // UA 342 | 343 | data.userAgent = navigator.userAgent; // appName 344 | 345 | data.appName = navigator.appName; // appVersion 346 | 347 | data.appVersion = navigator.appVersion; // CPU 348 | 349 | data.cpuClass = navigator.cpuClass; // platform 350 | 351 | data.platform = navigator.platform; // product 352 | 353 | data.product = navigator.product; // languages 354 | 355 | data.language = navigator.language; // url 356 | 357 | data.url = window.location.href; // time 358 | 359 | data.time = new Date().getTime(); 360 | return data; 361 | }, 362 | // webrtc 获取 IP 363 | _getIP: function (onNewIP) { 364 | var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; 365 | 366 | var pc = new myPeerConnection({ 367 | iceServers: [{ 368 | urls: "stun:stun01.sipphone.com" 369 | }, { 370 | urls: "stun:stun.ekiga.net" 371 | }, { 372 | urls: "stun:stun.fwdnet.net" 373 | }, { 374 | urls: "stun:stun.l.google.com:19302" 375 | }, { 376 | urls: "stun:stun.l.google.com:19302" 377 | }, { 378 | urls: "stun:stun.l.google.com:19302" 379 | }] 380 | }), 381 | noop = function () {}, 382 | localIPs = {}, 383 | ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g; 384 | 385 | function iterateIP(ip) { 386 | if (!localIPs[ip]) { 387 | onNewIP(ip); 388 | } 389 | 390 | localIPs[ip] = true; 391 | } //create a bogus data channel 392 | 393 | 394 | pc.createDataChannel(""); // create offer and set local description 395 | 396 | pc.createOffer().then(function (sdp) { 397 | sdp.sdp.split('\n').forEach(function (line) { 398 | if (line.indexOf('candidate') < 0) return; 399 | line.match(ipRegex).forEach(iterateIP); 400 | }); 401 | pc.setLocalDescription(sdp, noop, noop); 402 | }).catch(function (reason) {// An error occurred, so handle the failure to connect 403 | }); //listen for candidate events 404 | 405 | pc.onicecandidate = function (ice) { 406 | if (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return; 407 | ice.candidate.candidate.match(ipRegex).forEach(iterateIP); 408 | }; 409 | }, 410 | // 处理错误信息 411 | _getErrorMessage: function (err, resource) { 412 | const self = this; 413 | 414 | let data = self._geWrap(); 415 | 416 | self._getIP(function (ip) { 417 | data.ip = ip; 418 | }); 419 | 420 | data.detail = {}; 421 | 422 | if (err.type === "ajaxLoad") { 423 | data.detail.responseURL = err.detail.responseURL; 424 | data.detail.status = err.detail.status; 425 | data.detail.statusText = err.detail.statusText; 426 | data.detail.type = "ajaxLoad"; 427 | } else if (err.type === "error") { 428 | data.detail.message = err.message; 429 | data.detail.line = err.lineno; 430 | data.detail.filename = err.filename; 431 | data.detail.type = "error"; 432 | data.detail.stack = err.error.stack; 433 | } else if (resource) { 434 | data.detail.src = err.target.src; 435 | data.detail.type = "resource"; 436 | } // data.jsStack = self._getCallStack(); 437 | 438 | 439 | console.log(data); 440 | console.log(err); 441 | return data; 442 | }, 443 | 444 | _getCallStack() { 445 | var stack = "#", 446 | total = 0, 447 | fn = arguments.callee; 448 | 449 | while (fn = fn.caller) { 450 | stack = stack + "" + fn.name; 451 | total++; 452 | } 453 | 454 | return stack; 455 | } 456 | 457 | }; 458 | module.exports = Wrap; 459 | 460 | /***/ }), 461 | 462 | /***/ "tjUo": 463 | /***/ (function(module, exports, __webpack_require__) { 464 | 465 | "use strict"; 466 | 467 | 468 | var _initMonitor = _interopRequireDefault(__webpack_require__("f6yO")); 469 | 470 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 471 | 472 | /** 473 | * @file main js at project 474 | * @author JYkid 475 | * @version 0.0.1-beta 476 | */ 477 | 478 | /* eslint-disable */ 479 | function monitor(userConfig) { 480 | const init = new _initMonitor.default(userConfig); 481 | return init; 482 | } 483 | 484 | monitor.prototype = { 485 | _destory: function () {} 486 | }; 487 | module.exports = monitor; 488 | 489 | /***/ }), 490 | 491 | /***/ "xziN": 492 | /***/ (function(module, exports, __webpack_require__) { 493 | 494 | "use strict"; 495 | 496 | 497 | Object.defineProperty(exports, "__esModule", { 498 | value: true 499 | }); 500 | exports.getError = exports.ajaxError = exports.getServerError = void 0; 501 | 502 | var _ajax = __webpack_require__("oLOV"); 503 | 504 | var _wrap = _interopRequireDefault(__webpack_require__("pB/M")); 505 | 506 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 507 | 508 | /** 509 | * @file error event center 510 | * @author JYkid 511 | * @version 0.0.1-beta 512 | */ 513 | 514 | /* eslint-disable */ 515 | // 服务端返回错误 516 | const getServerError = function () {}; // ajaxError 517 | 518 | 519 | exports.getServerError = getServerError; 520 | 521 | const ajaxError = function (err, config) { 522 | // 处理err 上报 523 | if (err.type === "ajaxLoad" && err.detail.status > 300) { 524 | let data = new _wrap.default()._getErrorMessage(err); 525 | 526 | _ajax.ajax.post(config.protocol + config.url, data, function () {}, function (error) { 527 | console.log(error); 528 | }); 529 | } 530 | }; // js 内部运行错误 531 | 532 | 533 | exports.ajaxError = ajaxError; 534 | 535 | const getError = function (err, config) { 536 | // 可以被取消的是js抛出的错误 537 | if (err.cancelable) { 538 | getJsError(err, config); 539 | } else { 540 | geetResourceError(err, config); 541 | } 542 | }; // js 抛出的错误 543 | 544 | 545 | exports.getError = getError; 546 | 547 | const getJsError = function (err, config) { 548 | let data = new _wrap.default()._getErrorMessage(err); 549 | 550 | _ajax.ajax.post(config.protocol + config.url, data, function () {}, function (error) { 551 | console.log(error); 552 | }); 553 | }; // 资源加载错误 554 | 555 | 556 | const geetResourceError = function (err, config) { 557 | let data = _ajax.ajax.getWraper(err, _wrap.default, true); 558 | 559 | _ajax.ajax.post(config.protocol + config.url, data, function () {}, function (error) { 560 | console.log(error); 561 | }); 562 | }; 563 | 564 | /***/ }) 565 | 566 | /******/ }); -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.0.1-beta (2019-08-07) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 7 | * change Promise error event name ([0ac684d](https://github.com/MriLiuJY/FE-Monitor/commit/0ac684d)) 8 | * delete console ([192d2f3](https://github.com/MriLiuJY/FE-Monitor/commit/192d2f3)) 9 | * fix report url width 'protocol' value ([fc4b814](https://github.com/MriLiuJY/FE-Monitor/commit/fc4b814)) 10 | * get data type detail ([7ad5686](https://github.com/MriLiuJY/FE-Monitor/commit/7ad5686)) 11 | * lintener error event judge js running or recouse error type ([847e0b8](https://github.com/MriLiuJY/FE-Monitor/commit/847e0b8)) 12 | * npm package license descript ([df435c6](https://github.com/MriLiuJY/FE-Monitor/commit/df435c6)) 13 | * remove some rely ([56b8477](https://github.com/MriLiuJY/FE-Monitor/commit/56b8477)) 14 | * removeEventListener in different stage ([34ce2b9](https://github.com/MriLiuJY/FE-Monitor/commit/34ce2b9)) 15 | * resource type error change get wrap message ([5880b98](https://github.com/MriLiuJY/FE-Monitor/commit/5880b98)) 16 | 17 | 18 | ### Features 19 | 20 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 21 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 22 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 23 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 24 | * add callback func ([a28461d](https://github.com/MriLiuJY/FE-Monitor/commit/a28461d)) 25 | * add clearRecord array func ([440a09d](https://github.com/MriLiuJY/FE-Monitor/commit/440a09d)) 26 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 27 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 28 | * add destory function to removeEventListener ([e05cf52](https://github.com/MriLiuJY/FE-Monitor/commit/e05cf52)) 29 | * add eslint config change ([a6ab680](https://github.com/MriLiuJY/FE-Monitor/commit/a6ab680)) 30 | * add eventListener get resource error ([53cfdaf](https://github.com/MriLiuJY/FE-Monitor/commit/53cfdaf)) 31 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 32 | * add git hook ([6472553](https://github.com/MriLiuJY/FE-Monitor/commit/6472553)) 33 | * add git hook change ([65d7c84](https://github.com/MriLiuJY/FE-Monitor/commit/65d7c84)) 34 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 35 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 36 | * add js running error get js error stack message ([c615fbc](https://github.com/MriLiuJY/FE-Monitor/commit/c615fbc)) 37 | * add listen promise error ([3b7191b](https://github.com/MriLiuJY/FE-Monitor/commit/3b7191b)) 38 | * add mongoose conf ([1e9336c](https://github.com/MriLiuJY/FE-Monitor/commit/1e9336c)) 39 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 40 | * add release README && package.json ([9d11a53](https://github.com/MriLiuJY/FE-Monitor/commit/9d11a53)) 41 | * add report rrweb event data with error request ([cf64d79](https://github.com/MriLiuJY/FE-Monitor/commit/cf64d79)) 42 | * add rrweb record page action ([3fc87f8](https://github.com/MriLiuJY/FE-Monitor/commit/3fc87f8)) 43 | * add some change at npm publish ([07568c9](https://github.com/MriLiuJY/FE-Monitor/commit/07568c9)) 44 | * add test destory case ([e85d8ba](https://github.com/MriLiuJY/FE-Monitor/commit/e85d8ba)) 45 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 46 | * add user conf report url ([9a4f8ef](https://github.com/MriLiuJY/FE-Monitor/commit/9a4f8ef)) 47 | * add vue monitor ([6c85f67](https://github.com/MriLiuJY/FE-Monitor/commit/6c85f67)) 48 | * change addEventlistener anonymous func ([6b6940f](https://github.com/MriLiuJY/FE-Monitor/commit/6b6940f)) 49 | * change get Wraper data ([8a3f2a3](https://github.com/MriLiuJY/FE-Monitor/commit/8a3f2a3)) 50 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 51 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 52 | * finish ajaxErrot report ([1f283c0](https://github.com/MriLiuJY/FE-Monitor/commit/1f283c0)) 53 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 54 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 55 | * remove eventlistener ([c0e4071](https://github.com/MriLiuJY/FE-Monitor/commit/c0e4071)) 56 | * remove rrweb-player in SDK ([0a9cea1](https://github.com/MriLiuJY/FE-Monitor/commit/0a9cea1)) 57 | * remove some useless function ([4089cc5](https://github.com/MriLiuJY/FE-Monitor/commit/4089cc5)) 58 | * webpack conf add gzip config ([b9c13ed](https://github.com/MriLiuJY/FE-Monitor/commit/b9c13ed)) 59 | 60 | 61 | 62 | ## 0.0.1-beta (2019-07-15) 63 | 64 | 65 | ### Bug Fixes 66 | 67 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 68 | * fix report url width 'protocol' value ([fc4b814](https://github.com/MriLiuJY/FE-Monitor/commit/fc4b814)) 69 | * get data type detail ([7ad5686](https://github.com/MriLiuJY/FE-Monitor/commit/7ad5686)) 70 | * lintener error event judge js running or recouse error type ([847e0b8](https://github.com/MriLiuJY/FE-Monitor/commit/847e0b8)) 71 | * removeEventListener in different stage ([34ce2b9](https://github.com/MriLiuJY/FE-Monitor/commit/34ce2b9)) 72 | 73 | 74 | ### Features 75 | 76 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 77 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 78 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 79 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 80 | * add callback func ([a28461d](https://github.com/MriLiuJY/FE-Monitor/commit/a28461d)) 81 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 82 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 83 | * add destory function to removeEventListener ([e05cf52](https://github.com/MriLiuJY/FE-Monitor/commit/e05cf52)) 84 | * add eventListener get resource error ([53cfdaf](https://github.com/MriLiuJY/FE-Monitor/commit/53cfdaf)) 85 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 86 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 87 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 88 | * add js running error get js error stack message ([c615fbc](https://github.com/MriLiuJY/FE-Monitor/commit/c615fbc)) 89 | * add listen promise error ([3b7191b](https://github.com/MriLiuJY/FE-Monitor/commit/3b7191b)) 90 | * add mongoose conf ([1e9336c](https://github.com/MriLiuJY/FE-Monitor/commit/1e9336c)) 91 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 92 | * add release README && package.json ([9d11a53](https://github.com/MriLiuJY/FE-Monitor/commit/9d11a53)) 93 | * add test destory case ([e85d8ba](https://github.com/MriLiuJY/FE-Monitor/commit/e85d8ba)) 94 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 95 | * add user conf report url ([9a4f8ef](https://github.com/MriLiuJY/FE-Monitor/commit/9a4f8ef)) 96 | * change addEventlistener anonymous func ([6b6940f](https://github.com/MriLiuJY/FE-Monitor/commit/6b6940f)) 97 | * change get Wraper data ([8a3f2a3](https://github.com/MriLiuJY/FE-Monitor/commit/8a3f2a3)) 98 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 99 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 100 | * finish ajaxErrot report ([1f283c0](https://github.com/MriLiuJY/FE-Monitor/commit/1f283c0)) 101 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 102 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 103 | * remove eventlistener ([c0e4071](https://github.com/MriLiuJY/FE-Monitor/commit/c0e4071)) 104 | * webpack conf add gzip config ([b9c13ed](https://github.com/MriLiuJY/FE-Monitor/commit/b9c13ed)) 105 | 106 | 107 | 108 | ## 0.0.1-beta (2019-07-12) 109 | 110 | 111 | ### Bug Fixes 112 | 113 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 114 | * fix report url width 'protocol' value ([fc4b814](https://github.com/MriLiuJY/FE-Monitor/commit/fc4b814)) 115 | * get data type detail ([7ad5686](https://github.com/MriLiuJY/FE-Monitor/commit/7ad5686)) 116 | * lintener error event judge js running or recouse error type ([847e0b8](https://github.com/MriLiuJY/FE-Monitor/commit/847e0b8)) 117 | 118 | 119 | ### Features 120 | 121 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 122 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 123 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 124 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 125 | * add callback func ([a28461d](https://github.com/MriLiuJY/FE-Monitor/commit/a28461d)) 126 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 127 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 128 | * add destory function to removeEventListener ([e05cf52](https://github.com/MriLiuJY/FE-Monitor/commit/e05cf52)) 129 | * add eventListener get resource error ([53cfdaf](https://github.com/MriLiuJY/FE-Monitor/commit/53cfdaf)) 130 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 131 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 132 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 133 | * add js running error get js error stack message ([c615fbc](https://github.com/MriLiuJY/FE-Monitor/commit/c615fbc)) 134 | * add listen promise error ([3b7191b](https://github.com/MriLiuJY/FE-Monitor/commit/3b7191b)) 135 | * add mongoose conf ([1e9336c](https://github.com/MriLiuJY/FE-Monitor/commit/1e9336c)) 136 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 137 | * add test destory case ([e85d8ba](https://github.com/MriLiuJY/FE-Monitor/commit/e85d8ba)) 138 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 139 | * add user conf report url ([9a4f8ef](https://github.com/MriLiuJY/FE-Monitor/commit/9a4f8ef)) 140 | * change addEventlistener anonymous func ([6b6940f](https://github.com/MriLiuJY/FE-Monitor/commit/6b6940f)) 141 | * change get Wraper data ([8a3f2a3](https://github.com/MriLiuJY/FE-Monitor/commit/8a3f2a3)) 142 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 143 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 144 | * finish ajaxErrot report ([1f283c0](https://github.com/MriLiuJY/FE-Monitor/commit/1f283c0)) 145 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 146 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 147 | * webpack conf add gzip config ([b9c13ed](https://github.com/MriLiuJY/FE-Monitor/commit/b9c13ed)) 148 | 149 | 150 | 151 | ## 0.0.1-beta (2019-07-09) 152 | 153 | 154 | ### Bug Fixes 155 | 156 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 157 | * fix report url width 'protocol' value ([fc4b814](https://github.com/MriLiuJY/FE-Monitor/commit/fc4b814)) 158 | * get data type detail ([7ad5686](https://github.com/MriLiuJY/FE-Monitor/commit/7ad5686)) 159 | 160 | 161 | ### Features 162 | 163 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 164 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 165 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 166 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 167 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 168 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 169 | * add eventListener get resource error ([53cfdaf](https://github.com/MriLiuJY/FE-Monitor/commit/53cfdaf)) 170 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 171 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 172 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 173 | * add listen promise error ([3b7191b](https://github.com/MriLiuJY/FE-Monitor/commit/3b7191b)) 174 | * add mongoose conf ([1e9336c](https://github.com/MriLiuJY/FE-Monitor/commit/1e9336c)) 175 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 176 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 177 | * add user conf report url ([9a4f8ef](https://github.com/MriLiuJY/FE-Monitor/commit/9a4f8ef)) 178 | * change get Wraper data ([8a3f2a3](https://github.com/MriLiuJY/FE-Monitor/commit/8a3f2a3)) 179 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 180 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 181 | * finish ajaxErrot report ([1f283c0](https://github.com/MriLiuJY/FE-Monitor/commit/1f283c0)) 182 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 183 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 184 | * webpack conf add gzip config ([b9c13ed](https://github.com/MriLiuJY/FE-Monitor/commit/b9c13ed)) 185 | 186 | 187 | 188 | ## 0.0.1-beta (2019-07-09) 189 | 190 | 191 | ### Bug Fixes 192 | 193 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 194 | * fix report url width 'protocol' value ([fc4b814](https://github.com/MriLiuJY/FE-Monitor/commit/fc4b814)) 195 | * get data type detail ([7ad5686](https://github.com/MriLiuJY/FE-Monitor/commit/7ad5686)) 196 | 197 | 198 | ### Features 199 | 200 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 201 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 202 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 203 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 204 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 205 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 206 | * add eventListener get resource error ([53cfdaf](https://github.com/MriLiuJY/FE-Monitor/commit/53cfdaf)) 207 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 208 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 209 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 210 | * add listen promise error ([3b7191b](https://github.com/MriLiuJY/FE-Monitor/commit/3b7191b)) 211 | * add mongoose conf ([1e9336c](https://github.com/MriLiuJY/FE-Monitor/commit/1e9336c)) 212 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 213 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 214 | * add user conf report url ([9a4f8ef](https://github.com/MriLiuJY/FE-Monitor/commit/9a4f8ef)) 215 | * change get Wraper data ([8a3f2a3](https://github.com/MriLiuJY/FE-Monitor/commit/8a3f2a3)) 216 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 217 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 218 | * finish ajaxErrot report ([1f283c0](https://github.com/MriLiuJY/FE-Monitor/commit/1f283c0)) 219 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 220 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 221 | * webpack conf add gzip config ([b9c13ed](https://github.com/MriLiuJY/FE-Monitor/commit/b9c13ed)) 222 | 223 | 224 | 225 | ## 0.0.1-beta (2019-07-09) 226 | 227 | 228 | ### Bug Fixes 229 | 230 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 231 | * fix report url width 'protocol' value ([fc4b814](https://github.com/MriLiuJY/FE-Monitor/commit/fc4b814)) 232 | * get data type detail ([7ad5686](https://github.com/MriLiuJY/FE-Monitor/commit/7ad5686)) 233 | 234 | 235 | ### Features 236 | 237 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 238 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 239 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 240 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 241 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 242 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 243 | * add eventListener get resource error ([53cfdaf](https://github.com/MriLiuJY/FE-Monitor/commit/53cfdaf)) 244 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 245 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 246 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 247 | * add listen promise error ([3b7191b](https://github.com/MriLiuJY/FE-Monitor/commit/3b7191b)) 248 | * add mongoose conf ([1e9336c](https://github.com/MriLiuJY/FE-Monitor/commit/1e9336c)) 249 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 250 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 251 | * add user conf report url ([9a4f8ef](https://github.com/MriLiuJY/FE-Monitor/commit/9a4f8ef)) 252 | * change get Wraper data ([8a3f2a3](https://github.com/MriLiuJY/FE-Monitor/commit/8a3f2a3)) 253 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 254 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 255 | * finish ajaxErrot report ([1f283c0](https://github.com/MriLiuJY/FE-Monitor/commit/1f283c0)) 256 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 257 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 258 | * webpack conf add gzip config ([b9c13ed](https://github.com/MriLiuJY/FE-Monitor/commit/b9c13ed)) 259 | 260 | 261 | 262 | ## 0.0.1-beta (2019-07-09) 263 | 264 | 265 | ### Bug Fixes 266 | 267 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 268 | * fix report url width 'protocol' value ([fc4b814](https://github.com/MriLiuJY/FE-Monitor/commit/fc4b814)) 269 | * get data type detail ([7ad5686](https://github.com/MriLiuJY/FE-Monitor/commit/7ad5686)) 270 | 271 | 272 | ### Features 273 | 274 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 275 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 276 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 277 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 278 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 279 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 280 | * add eventListener get resource error ([53cfdaf](https://github.com/MriLiuJY/FE-Monitor/commit/53cfdaf)) 281 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 282 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 283 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 284 | * add listen promise error ([3b7191b](https://github.com/MriLiuJY/FE-Monitor/commit/3b7191b)) 285 | * add mongoose conf ([1e9336c](https://github.com/MriLiuJY/FE-Monitor/commit/1e9336c)) 286 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 287 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 288 | * add user conf report url ([9a4f8ef](https://github.com/MriLiuJY/FE-Monitor/commit/9a4f8ef)) 289 | * change get Wraper data ([8a3f2a3](https://github.com/MriLiuJY/FE-Monitor/commit/8a3f2a3)) 290 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 291 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 292 | * finish ajaxErrot report ([1f283c0](https://github.com/MriLiuJY/FE-Monitor/commit/1f283c0)) 293 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 294 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 295 | * webpack conf add gzip config ([b9c13ed](https://github.com/MriLiuJY/FE-Monitor/commit/b9c13ed)) 296 | 297 | 298 | 299 | ## 0.0.1-beta (2019-07-09) 300 | 301 | 302 | ### Bug Fixes 303 | 304 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 305 | * fix report url width 'protocol' value ([fc4b814](https://github.com/MriLiuJY/FE-Monitor/commit/fc4b814)) 306 | * get data type detail ([7ad5686](https://github.com/MriLiuJY/FE-Monitor/commit/7ad5686)) 307 | 308 | 309 | ### Features 310 | 311 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 312 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 313 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 314 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 315 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 316 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 317 | * add eventListener get resource error ([53cfdaf](https://github.com/MriLiuJY/FE-Monitor/commit/53cfdaf)) 318 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 319 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 320 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 321 | * add listen promise error ([3b7191b](https://github.com/MriLiuJY/FE-Monitor/commit/3b7191b)) 322 | * add mongoose conf ([1e9336c](https://github.com/MriLiuJY/FE-Monitor/commit/1e9336c)) 323 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 324 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 325 | * add user conf report url ([9a4f8ef](https://github.com/MriLiuJY/FE-Monitor/commit/9a4f8ef)) 326 | * change get Wraper data ([8a3f2a3](https://github.com/MriLiuJY/FE-Monitor/commit/8a3f2a3)) 327 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 328 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 329 | * finish ajaxErrot report ([1f283c0](https://github.com/MriLiuJY/FE-Monitor/commit/1f283c0)) 330 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 331 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 332 | * webpack conf add gzip config ([b9c13ed](https://github.com/MriLiuJY/FE-Monitor/commit/b9c13ed)) 333 | 334 | 335 | 336 | ## 0.0.1-beta (2019-07-09) 337 | 338 | 339 | ### Bug Fixes 340 | 341 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 342 | * fix report url width 'protocol' value ([fc4b814](https://github.com/MriLiuJY/FE-Monitor/commit/fc4b814)) 343 | * get data type detail ([7ad5686](https://github.com/MriLiuJY/FE-Monitor/commit/7ad5686)) 344 | 345 | 346 | ### Features 347 | 348 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 349 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 350 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 351 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 352 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 353 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 354 | * add eventListener get resource error ([53cfdaf](https://github.com/MriLiuJY/FE-Monitor/commit/53cfdaf)) 355 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 356 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 357 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 358 | * add listen promise error ([3b7191b](https://github.com/MriLiuJY/FE-Monitor/commit/3b7191b)) 359 | * add mongoose conf ([1e9336c](https://github.com/MriLiuJY/FE-Monitor/commit/1e9336c)) 360 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 361 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 362 | * add user conf report url ([9a4f8ef](https://github.com/MriLiuJY/FE-Monitor/commit/9a4f8ef)) 363 | * change get Wraper data ([8a3f2a3](https://github.com/MriLiuJY/FE-Monitor/commit/8a3f2a3)) 364 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 365 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 366 | * finish ajaxErrot report ([1f283c0](https://github.com/MriLiuJY/FE-Monitor/commit/1f283c0)) 367 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 368 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 369 | * webpack conf add gzip config ([b9c13ed](https://github.com/MriLiuJY/FE-Monitor/commit/b9c13ed)) 370 | 371 | 372 | 373 | ## 0.0.1-beta (2019-07-05) 374 | 375 | 376 | ### Bug Fixes 377 | 378 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 379 | * get data type detail ([7ad5686](https://github.com/MriLiuJY/FE-Monitor/commit/7ad5686)) 380 | 381 | 382 | ### Features 383 | 384 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 385 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 386 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 387 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 388 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 389 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 390 | * add eventListener get resource error ([53cfdaf](https://github.com/MriLiuJY/FE-Monitor/commit/53cfdaf)) 391 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 392 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 393 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 394 | * add listen promise error ([3b7191b](https://github.com/MriLiuJY/FE-Monitor/commit/3b7191b)) 395 | * add mongoose conf ([1e9336c](https://github.com/MriLiuJY/FE-Monitor/commit/1e9336c)) 396 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 397 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 398 | * change get Wraper data ([8a3f2a3](https://github.com/MriLiuJY/FE-Monitor/commit/8a3f2a3)) 399 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 400 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 401 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 402 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 403 | * webpack conf add gzip config ([b9c13ed](https://github.com/MriLiuJY/FE-Monitor/commit/b9c13ed)) 404 | 405 | 406 | 407 | ## 0.0.1-beta (2019-06-30) 408 | 409 | 410 | ### Bug Fixes 411 | 412 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 413 | * get data type detail ([7ad5686](https://github.com/MriLiuJY/FE-Monitor/commit/7ad5686)) 414 | 415 | 416 | ### Features 417 | 418 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 419 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 420 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 421 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 422 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 423 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 424 | * add eventListener get resource error ([53cfdaf](https://github.com/MriLiuJY/FE-Monitor/commit/53cfdaf)) 425 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 426 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 427 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 428 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 429 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 430 | * change get Wraper data ([8a3f2a3](https://github.com/MriLiuJY/FE-Monitor/commit/8a3f2a3)) 431 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 432 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 433 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 434 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 435 | 436 | 437 | 438 | ## 0.0.1-beta (2019-06-26) 439 | 440 | 441 | ### Bug Fixes 442 | 443 | * change get wrap data func ([b61e367](https://github.com/MriLiuJY/FE-Monitor/commit/b61e367)) 444 | 445 | 446 | ### Features 447 | 448 | * add addEventListener watch error event ([d99cbf9](https://github.com/MriLiuJY/FE-Monitor/commit/d99cbf9)) 449 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 450 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 451 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 452 | * add config extend ([27f2196](https://github.com/MriLiuJY/FE-Monitor/commit/27f2196)) 453 | * add crossorigin ([9ff9df6](https://github.com/MriLiuJY/FE-Monitor/commit/9ff9df6)) 454 | * add get ajax timeout error ([080f2b9](https://github.com/MriLiuJY/FE-Monitor/commit/080f2b9)) 455 | * add index.html common create error func ([af34341](https://github.com/MriLiuJY/FE-Monitor/commit/af34341)) 456 | * add js running error catch ([c4db726](https://github.com/MriLiuJY/FE-Monitor/commit/c4db726)) 457 | * add new enent center file ([fda13f4](https://github.com/MriLiuJY/FE-Monitor/commit/fda13f4)) 458 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 459 | * common js error ([10a6f2f](https://github.com/MriLiuJY/FE-Monitor/commit/10a6f2f)) 460 | * finish addeventer ajax error and report ([ac6d7ca](https://github.com/MriLiuJY/FE-Monitor/commit/ac6d7ca)) 461 | * get base info && webRtc get real ip address ([b875b35](https://github.com/MriLiuJY/FE-Monitor/commit/b875b35)) 462 | * moitor global XMLhttpRequest error ([27d4843](https://github.com/MriLiuJY/FE-Monitor/commit/27d4843)) 463 | 464 | 465 | 466 | ## 0.0.1-beta (2019-06-20) 467 | 468 | 469 | ### Features 470 | 471 | * add babel conf ([8aef7bf](https://github.com/MriLiuJY/FE-Monitor/commit/8aef7bf)) 472 | * add base features files ([acc1bf1](https://github.com/MriLiuJY/FE-Monitor/commit/acc1bf1)) 473 | * add base webpack config ([c7b1955](https://github.com/MriLiuJY/FE-Monitor/commit/c7b1955)) 474 | * add testpage && README desc ([d427bf2](https://github.com/MriLiuJY/FE-Monitor/commit/d427bf2)) 475 | 476 | 477 | 478 | --------------------------------------------------------------------------------