范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

前端异常捕获且日志上报处理

  JavaScript 网页异常捕获一、异常大概分类
  一般我们想要捕获的异常大概分类:语法错误onerror 事件代码块与语法错误代码块不在一起,例如trycatche或者同在一个代码块,但是语法错误代码块异步执行以上情况都可以用onerror捕获语法错误setTimeout(() => { eval("function()") }, 1000); // Uncaught SyntaxError: Function statements require a function name 复制代码引用错误,类型错误,uri 错误,范围错误等等非try catch包裹情况下,可以使用 onerror 捕获同步错误、异步错误console.log(a) // Uncaught ReferenceError: a is not defined Array.test() // 调用了 Array 上不存在的 test,值为 undefined,作为函数执行,则会抛出类型错误 // Uncaught TypeError: Array.test is not a function new Array(12221312312) // Uncaught RangeError: Invalid array length decodeURI("%") // Uncaught URIError: URI malformed 复制代码try{} catch{}若 try 代码块报错,只能在 catch 中捕获。但是 try 代码块中若有异步错误代码,catch 无法捕获,会被 onerror 捕获try { setTimeout(() => { console.log("a", a) // 可以被 onerror 捕获 }, 1000) } catch(e) { console.log("e", e) } // Uncaught ReferenceError: a is not defined 复制代码Promise 抛出错误没有设置 catch 捕获let p = new Promise((resolve, reject) => { reject(1) } ) // 这里没有做 catch 处理 // Uncaught (in promise) 1 复制代码在 catch 中报错没有捕获;(async function xx() { try { throw 1 } catch(e) { console.log("a", a) // 这里出错可以使用 unhandledrejection 来捕获 } })() // Uncaught ReferenceError: a is not defined 复制代码上面两种情况可以监听 unhandledrejection 捕获错误window.addEventListener("unhandledrejection", function(e) { // e.preventDefault(); // 阻止异常向上抛出 console.log("捕获到异常 unhandledrejection :", e) }) 复制代码静态资源加载失败在资源上添加 onerror 事件// html //  // js let imgID = document.getElementById("imgID") imgID.onerror = function(e) { console.log("img load error :>> ", e); } // 注意:onerror 需要定义之后,再设置图片路径,才能捕获到加载失败 imgID.src = "http://xxx.png" 复制代码静态资源网络请求失败事件不会冒泡,需要在捕获阶段捕获chrome、FF 中可以通过冒泡方式监听 error 事件捕获资源加载失败// 注意:此处会与上面的 onerror 事件一起触发,将导致日志重复上报 // 可以只使用 addEventListener 捕获模式统一监听, 就不需要注册 window.onerror 了 window.addEventListener( "error", error => { console.log("addEventListener 捕获到异常:", error) }, true ) 复制代码网页崩溃网页加载后,埋入一个标志,表示正在加载// 初次进来,将埋入一个标志,值为 pending ,正常退出后,会设置为 true // 若网页崩溃,第二次回来页面后,读取当前标志,如果值存在且为 true 则表示正常退出 // 如果不是 true ,则表示上次可能是崩溃了,需要上报之前定时更新的时间值 if(localStorage.getItem("good_exit") && localStorage.getItem("good_exit") !== "true") { localStorage.getItem("time_before_crash") // 日志上报,将崩溃之前的时间一起上报 } window.addEventListener("load", function () { localStorage.setItem("good_exit", "pending"); // 定时更新崩溃之前的网页时间 setInterval(function () { localStorage.setItem("time_before_crash", new Date().toString()); }, 10000); }) window.addEventListener("beforeunload", function () { // 网页正常退出后,将埋入标志,设置成 true,表示正常退出 localStorage.setItem("good_exit", "true"); }) 复制代码上面是在 第二次 进入页面才知道网页崩溃,那么有什么方法可以在网页崩溃之后就可以上报呢可以使用 Service Worker 来进行监控其生命周期与页面无关(关联页面未关闭时,它也可以退出,没有关联页面时,它也可以启动)1、注册 service worker js 2、 每间隔 10 秒,就向 worker 发送消息 消息中包含: { type 字段:active 表示正常活跃,exit 表示正常退出 time 字段:表示当前时间 } 在页面要退出后,发送 type: exit,表示正常退出 3、 worker 内部注册有消息接收事件,接收页面发送过来的消息 接收到 type 为 active,表示正常活跃,更新内部 time 的值 接收到 type 为 exit,表示正常退出,更新内部 time 值为 0 worker 内部维护一个状态对象,包含时间,值为页面发送过来 每隔 15 秒检查一次,若时间与上一次没有改变,则说明页面可能崩溃(注意区分 time 为 0 的情况) 复制代码Script Error跨域脚本的错误信息,因为处于保护信息的原因,只会展示 Script Error, 通过以下方式解决1、外链脚本增加 crossorigin 属性: 2、同时脚本的 Access-Control-Allow-Origin: 设置为 * 或者 当前域名 复制代码iframe Error  复制代码vue 自身 try catch 处理了错误,导致我们无法捕获使用 Vue 提供的 errorHandler 方法捕获Vue.config.errorHandler = function(err, vm, info) { let { message, // 异常信息 name, // 异常名称 script, // 异常脚本url line, // 异常行号 column, // 异常列号 stack // 异常堆栈信息 } = err // vm 为抛出异常的 Vue 实例 // info 为 Vue 特定的错误信息,比如错误所在的生命周期钩子 console.log("vue err,vm,info :>> ", err, vm, info) } 复制代码
  所以捕获错误总结下来:// 1、try catch 中的 catch 错误捕获  可以在 webpack 打包时候,使用 AST 方式解析并在 catch 中插入日志上报代码 // 2、error 事件 window.addEventListener( "error", error => {      let data = {} // 此处与上面的 onerror 会重复事件      let { colno, lineno, message, filename, error, stack } = error //不一定所有浏览器都支持 colno 参数      let col = colno || (window.event && window.event.errorCharacter) || 0      data.url = url      data.line = line      data.col = col      if (!!stack){          //如果浏览器有堆栈信息          //直接使用          data.msg = stack.toString()      }else if (!!arguments.callee){          //尝试通过callee拿堆栈信息          let ext = []          let f = arguments.callee.caller, c = 3 //这里只拿三层堆栈信息          while (f && (--c>0)) {              ext.push(f.toString())              if (f === f.caller) {                  break //如果有环              }              f = f.caller          }          ext = ext.join(",") data.msg = ext      }      console.log("3、addEventListener error 捕获阶段>>>异常:", data)  }, true ) // 3、unhandledrejection  window.addEventListener("unhandledrejection", function(e) {      // e.preventDefault();      // 阻止异常向上抛出      console.log("4、promise 异常 unhandledrejection :", e)  }) // 4、errorHandler  Vue.config.errorHandler = function(err, vm, info) {  // vm 为抛出异常的 Vue 实例  // info 为 Vue 特定的错误信息,比如错误所在的生命周期钩子  let {      message, // 异常信息      name, // 异常名称      script, // 异常脚本url      line, // 异常行号      column, // 异常列号     stack // 异常堆栈信息  } = err  console.log("2、vue errorHandler :>> ", err, vm, info) } 复制代码二、错误日志上报
  既然异常已经捕获到了,那我们怎么处理呢,如何上报,需要上报哪些内容?日志分类
  1、一般日志分类等级log、debug、info、warn、error 复制代码
  2、分场景使用日志上报类型log: 记录流程信息  debug: 记录调试关键信息  info: 记录业务功能点,是否触发成功或者失败 warn: 页面警告信息  error: 页面错误或者业务异常信息 复制代码
  3、日志上报信息附带信息1、用户id、session、用户名  2、当前错误信息  3、可以用来重现、推断当前错误发生的信息  4、上报时间  5、日志等级等等 复制代码
  4、日志上报策略1、达量上传,设置一个缓存数量,到达即上报。因为不能一发生错误就要上报,会影响用户的网络。 2、日志埋点处各自有各自的上报等级。 需要有一个总配置地方,配置当前的上报等级 这样各处埋点可以判断当前需要上报的日志等级,等级小于设置值的话,不可上报。  3、本地缓存若暂存过多,需要删除前面的数据  4、抽样上报  5、设置缓存有效时间 等等 复制代码
  上报之后,接下来的步骤就是在服务端收集分析归类展示,基于badjs我们搭建一整套日志解析系统三、日志上报
  badjs 服务安装
  1、前期预备工作
  为了快速搭建,我们统一使用 docker 安装
  备注:windows 环境使用 docker,需要安装 Docker Desktopmysql 安装 docker 安装 mysql备注:mysql 安装好后,需要从 badjs-web (需要先把项目下载下来)项目中的 db 目录下。 使用 create.sql 初始化 web 相关的数据库mongodb 安装(不可设置密码) docker 安装 mongo
  2、项目安装
  github 克隆项目到本地git clone https://github.com/BetterJS/badjs-installer 复制代码
  子项目下载以及依赖安装// 克隆下载 badjs-acceptor、badjs-mq、badjs-storage、badjs-web 项目  yarn clone  // 安装各项目的依赖  yarn install 复制代码
  3、修改配置项修改 badjs-acceptor 项目的 project.debug.json/project.json注意:这里是日志上报的地方,客户端初始化 badjs-report 时候需要设置的 url 属性即是这里的服务地址http://{badjs-acceptor:port}/badjs// 修改 port 属性: 从 80 改为 8083; // 因为 node 默认没有 80 端口的权限,需要你使用管理员权限才可以使用 { "port": 8083 } 复制代码修改 badjs-web 项目的 project.debug.json/project.json// 修改 mysql 属性,配置我们 docker 安装好的 mysql 用户密码与端口 { "mysql" : { "url" : "mysql://root:123456@localhost:3306/badjs" } } 复制代码
  4、启动项目
  yarn start
  查看 badjs-web 的启动端口,访问 http://localhost:port 可以看到日志后台管理服务页面四、badjs各模块
  1、badjs-acceptor 接受客户端上报的日志badjs-acceptor 收到日志上报,发送到 badjs-mq package.json 中配置 dispatcher 分发属性, 表示向 badjs-mq 请求的信息:如请求端口(10001) 复制代码
  2、badjs-mq 消息队列,保证消息有序稳定被接受badjs-mq 接收 badjs-acceptor 的请求 package.json 中配置 acceptor 接收属性, 表示用来接收信息所配置的接口信息:如端口(10001)。  badjs-mq 再分发到 badjs-storage package.json 中配置 dispatcher 分发属性, 表示向 badjs-storage 请求的信息:如端口(10000) 复制代码
  3、badjs-storage 存储模块badjs-storage: 接收来自 badjs-mq 的请求,再写入到 mongodb package.json 中配置 acceptor 接收属性, 表示用来接收信息所配置的接口信息:如端口(10000) 复制代码
  4、badjs-web 日志后台管理系统badjs-web 查询日志存储,分类查看日志信息,解析日志内容 package.json 中配置 acceptor 接收属性, badjs-acceptor 可请求的端口 package.json 中配置 storage 存储属性, 查询 mongodb 数据 package.json 中配置 mysql 数据库属性, 查询 mysql 数据等等 复制代码五、上报日志插件 badjs-report
  badjs-report 重写了 window.onerror 来捕获错误
  1、安装yarn add badjs-report 复制代码
  2、初始化import badjs from "badjs-report"  badjs.init({     // 必须配置项     id: 1 // 此 id 为 badjs-web 启动后,申请的项目的 id,上报的日志根据该 id 区分业务模块     url: "http://badjs-acceptor启动后的地址", // 日志上报到的地方      // 选择配置     uin: 123, // 指定用户的 id (该插件默认读取 qq uin)     delay: 1000, // 延迟多少毫秒,合并缓冲区中的上报(默认 1000)     ignore: [/Script error/i], // 忽略某个错误,遇到该错误不进行上报     random: 1, // 抽样上报, 值可以设置 0-1 之间。1 表示 100% 上报(默认为 1)     repeat: 5, // 重复上报次数(对于同一个错误超过多少次不上报;避免单个用户同一错误上报过多的情况)     onReport: function(id, errObj) {}, // 上报日志之后的回调。id 为上报的 id,errorObj 为上报的错误对象     submit: function(url) {}, // 覆盖原来的上报方式,原来是使用 new Image() 形式上报,可以修改成自己想要上报的方式,比如使用 post 内部构造好的 url     ext: {}, // 扩展属性,后端做扩展处理属性。设置了 ext 的值,就会作为 "ext=设置的值" 合并到构造好的上报 url 中     offlineLog: false, // 是否开启离线日志(默认不开启为 false)     offlineLogExp: 5 // 离线有效时间(默认最近5天) }) 复制代码
  3、手动上报a、badjs.report("error msg") b、badjs.report({     msg: "error msg", // 需要上报的错误信息     target: "error.js", // 发生错误的 js 文件     rowNum: 1, // 发生错误的行数     colNum: 2 // 发生错误的列数 }) 复制代码
  4、延迟上报
  暂存badjs.push("error msg") badjs.push({     msg: "error msg", // 需要上报的错误信息     target: "error.js", // 发生错误的 js 文件     rowNum: 1, // 发生错误的行数     colNum: 2 // 发生错误的列数 }) 复制代码
  立即上报badjs.report({     msg: "error msg", // 需要上报的错误信息     target: "error.js", // 发生错误的 js 文件     rowNum: 1, // 发生错误的行数     colNum: 2 // 发生错误的列数 }) 复制代码
  5、上报离线日志badjs.reportOfflineLog() 复制代码六、项目应用import BJ_REPORT from "badjs-report" import Vue from "vue"  // 环境ID枚举 let ENV_ID_ENUM = {     DEV: 1,     SIT: 2,     UAT: 3,     PRO: 4 } let curEnv = "",     origin = window.location.origin if (origin.indexOf("dev.xxx.com") > -1) {     // http://dev.xxx.com     // DEV 环境     curEnv = "DEV" } else if (origin.indexOf("sit.xxx.com") > -1) {     // http://sit.xxx.com     // SIT 环境     curEnv = "SIT" } else if (origin.indexOf("uat.xxx.com") > -1) {     // http://uat.xxx.com     // UAT 环境     curEnv = "UAT" } else if (origin.indexOf("m.xxx.com") > -1) {     // http://pro.xxx.com     // PRO 环境     curEnv = "PRO" } let envID = ENV_ID_ENUM[curEnv] || ENV_ID_ENUM.DEV  // 初始化日志上报插件 BJ_REPORT.init({     id: envID, // 不指定 id 将不上报,     url: "http://{badjs-acceptor:port}/badjs" })  // 初始化项目时,可以暴露一个全局的 vm 实例,方便上传需要的信息 window.rootvm = new Vue({}) // 初始化项目  // 初始化监听异常 init(window.rootvm) function init(rootInstance) {     Vue.config.errorHandler = function(err, curInstance, info) {         // vm 为抛出异常的 Vue 实例         // info 为 Vue 特定的错误信息,比如错误所在的生命周期钩子         let {             message, // 异常信息             // name, // 异常名称             // script, // 异常脚本url             line, // 异常行号             column, // 异常列号             stack // 异常堆栈信息         } = err         log(message, stack, line, column, curInstance)         console.log("vue errorHandler :>> ", err, curInstance, info)     }     window.addEventListener(         "error",         e => {             let { colno, lineno, message, filename } = e             log(message, filename, lineno, colno, rootInstance)             console.log("addEventListener error 捕获阶段>>>异常:", e)         },         true     )     window.addEventListener("unhandledrejection", function(e) {         // e.preventDefault(); // 阻止异常向上抛出         let { reason } = e         log(JSON.stringify(reason), "", "", "", rootInstance)         console.log("Promise 异常 unhandledrejection :", e)     }) }  function log(msg, target, rowNum, colNums, vminstance) {     let msgs = `***[${msg}]***`,         state = (vminstance && vminstance.$store && vminstance.$store.state) || {}      // 用户信息     if (state.userInfo) {         let { phoneNumber, userId } = state.userInfo         msgs += `***[phone:${phoneNumber}--userId:${userId}]***`     }     // 路由信息     let { name, fullPath } = (vminstance && vminstance.$route) || {}     msgs += `***[router-name: ${name} -- router-fullpath: ${fullPath}]***`      BJ_REPORT.report({         msg: msgs,         target,         rowNum,         colNums     }) }

N86之后,诺基亚N系列再也没有键盘了诺基亚N86上市时,全屏触控时代已经来临了,当年想不到它竟成N系列传统键盘手机的绝唱。N86不好吗?它很好,只是时代变了。情怀机佬又来怀缅古董了,把日历翻回2009年,在用过机王诺3nm之争暗潮汹涌芯片制造巨头对抗升级国产半导体迎发展契机本报记者贾丽在全球芯片供应吃紧之下,芯片制造巨头们加足马力开工之余,暗中较劲,在芯片3纳米制程技术(3nm)上争夺不休。台积电与三星的3nm争夺战已然打响,前者已进入试产阶段,预计两大长线赛道重点基金分享(下)接上文两大长线赛道重点基金分享(上)今天说一下芯片行业的投资机会,这是确定的长牛赛道之一。最初,芯片行业被广大投资者认知,是基于5G技术的快速发展。当时的逻辑是,基站建设通讯设备5粤港澳大湾区科技合作跑出加速度新华社广州12月12日电题粤港澳大湾区科技合作跑出加速度新华社记者马晓澄陆浩在今年东京奥运会上,中国香港运动员李慧诗在场地自行车女子争先赛中夺得一枚铜牌,这背后,有国家超算广州中心美科技巨头将面临美政策密集的反垄断监管中国日报网12月13日电据英国媒体经济学人报道,美国总统拜登执政后,有多位秉持对美国大型科技企业持强硬态度的官员执掌相关监管机构,预计会与国会的一些持类似观点的议员一起,对美国大型今日热点茅台原箱价惊现三位数小米新型电池明年下半年量产12021年我国广告市场规模预计突破万亿大关12月12日,从第28届中国国际广告节上了解到,今年前三季度,我国头部企事业单位广告业务收入已经达到了9403亿元,比去年同期增长20。双12别乱买旧旗舰,这几款2022年度旗舰即将上线,看了参数再决定双12即将逼近,在电商大促之下,很多小伙伴开始考虑换机需求。但数码圈买新不买旧的定理永远不失效,这几款即将上线的2022年度高端旗舰,参数已经几乎曝光,十分值得入手!下面就一起看看小米12Ultra最新渲染图曝光,终于等到徕卡可乐标疑似小米12系列三款新机的手机壳,其中小米12Ultra巨大的后摄模组十分引人注意。此后国外爆料大神带来了小米12Ultra的最新渲染图。相机模组也改为了非常巨大的奥利奥圆形设计,朱江明打造全国人民都买得起的豪车七年前的造车新浪潮将300多家企业裹挟进来,如今,经过大浪淘沙,拼杀出来的,都是精兵强将,都是中国自主品牌新能源汽车的希望。目前中国新能源汽车市场主要有三股力量造车新势力,传统自主被列投资黑名单商汤科技表示仍致力于尽快上市本报记者李乔宇12月13日午间,商汤科技披露公告,称董事会宣布,全球发售及上市将会延迟,且公司预期将刊发补充招股章程,将载有经更新上市时间表中国香港发售股份的相关申请程序及其他相关三星平板S8Ultra价格全曝光搭载骁龙8处理器据PhoneArena报道,三星将于2022年推出高端旗舰平板GalaxyTabS8Ultra,售价将比iPadPro便宜。报道指出,三星GalaxyTabS8Ultra顶配版配备
互联网人自救指南!360全向拾音转文字,零距离线上办公太舒服互联网人居家办公的烦噪!伴随着疫情的反复无常,越来越多公司和企业都开始了线上移动办公模式。作为从事互联网工作的人,面对线上电话会议线上视频培训以及线上业务洽谈的增多,我发现身边不少简单清理,越清越多!警惕那些专坑老年人手机的流氓软件问互联网时代你最怕老年人做什么?答最怕他她什么都信除了保健品和投资理财,智能手机普及后的今天你还得担心流氓软件盯上老年人群体。而最有特色的就是各种清理软件了。它们通过老年人的微信群摩托罗拉edgeX40Ultra惊喜的不止外观,骁龙8gen2加持,看齐高端摩托罗拉完全称得上是行业卷王,不仅首发了搭载旗舰处理器骁龙8gen1的edgeX30,还凭借一己之力拉低了骁龙8gen1的定价,其后发布的多款机型在定价方面也是极具诚意。除了吸引人索尼A9III相关规格传闻曝光2500万像素支持30FPS无损压缩RAW连拍今年索尼摄影师最为关注的微单相机应该就是第三代A9了,最近外媒传出了A9III新的相关信息,暂时不能确定消息源是否完全可信,但大家可以参考一下。据该消息源透露,索尼旗舰微单相机A9苹果修复macOS12。3。1Monterey漏洞,但BigSurCatalina未修复据MacRumors报道,近期苹果发布了macOSMonterey12。3。1,解决了两个可能在被主动利用的关键漏洞,但正如Intego本周指出的,苹果给macOSBigSur和m小屏手机我只推荐这三款,真满血小屏旗舰完美胜任主力机小屏手机我只推荐这三款,真满血小屏旗舰完美胜任主力机。第一款三星S22搭载骁龙8Gen1处理器,正面采用了一块6。1英寸的居中挖孔屏,屏幕比例为19。59,425ppi,支持108这样实现分布式锁,才叫优雅概述提到分布式锁大家都会想到如下两种基于Redisson组件,使用redlock算法实现基于ApacheCurator,利用Zookeeper的临时顺序节点模型实现今天我们来说说第老年人使用智能手机必须要知道的4个小技巧,实用且强大老年人使用智能手机必须要知道的4个小技巧,实用且强大。大家好呀,我们生活中智能手机越来越普及了,使用手机的老年人也越来越多了,为了帮助咱们老年朋友能将智能手机玩得更溜,今天我给大家4。8跨境早报东南亚女性网购者增长54,美国青少年支出增长9平台资讯01hr受日本法律修改的影响,亚马逊日本站发出公告,由于民法修改,从今年4月1日起,日本的成年年龄从20岁降低到18岁,但饮酒年龄仍保持在20岁以上。近日,受日本法律修改的加密货币成为主流资产还有多远?加密货币已经从一种不起眼的时尚变成了一种更为主流的投资和金融形式。少数加密货币主导市场,比特币占该行业总市值的41。随着这种增长,世界各国政府对监管该行业产生了兴趣。一些政府也已采安洁科技预计2022年13月归属净利润盈利7500万元至1亿元,同比上年增长1567。11至2122。81安洁科技20220408发布业绩预告,预计2022年13月归属净利润盈利7500万元至1亿元,同比上年增长1567。11至2122。81。本次业绩变动的原因为公司不断提升在新能源汽