前端异常埋点问题

本文介绍了前端异常埋点的必要性和常见问题,详细讨论了如何通过try...catch、window.onerror、Vue错误处理和Promise全局捕获等方式进行异常捕获。同时,探讨了sourcemap在定位压缩代码错误中的作用,以及通过webpack插件实现sourcemap自动上传。错误上报通过img标签和ajax实现,并展示了后端服务如何接收和解析错误日志,以及使用ELK或MongoDB进行日志存储和可视化。最后提出了错误类型的区分、日志管理和上报频率限制等优化方向。

开发者有时会面临上线的生产环境包出现了异常bug,在长期生产bug并修复bug的循环中总结出以下几个痛点:

  1. 无法快速定位到发生错误的代码位置,因为脚手架构建时会用webapck自动帮我们压缩代码,而上线版本又通常不会保留 source map(开源贡献者除外)

  2. 无法第一时间通知开发人员异常发生

  3. 不知道用户OS与浏览器版本、请求参数(如页面ID);而对于页面逻辑是否错误问题,通常除了用户OS与浏览器版本外,需要的是报错的堆栈信息及具体报错位置。

错误埋点追踪系统的出现就是为了应对上述问题的解决方案,针对前端埋点与错误处理的博客内容,按例总结一下。

什么是埋点

大数据时代数据的重要性不言而喻,而其中最重要的就是用户信息的采集。埋点,无论是项目后期的复盘,还是明确业务价值,还是产品价值的挖掘,都具备很重要的意义。

前端异常捕获

在ES3之前js代码执行的过程中,一旦出现错误,整个js代码都会停止执行,这样就显的代码非常的不健壮。从ES3开始,js也提供了类似的异常处理机制,从而让js代码变的更健壮,程序执行的过程中出现了异常,也可以让程序具有了一部分的异常恢复能力。js异常的特点是,出现不会导致JS引擎崩溃,最多只会终止当前执行的任务。

回归正题,我们该如何在程序异常发生时捕捉并进行对应的处理呢?在Javascript中,我们通常有以下两种异常捕获机制。

基本的try…catch语句

  function errFunc() {
      // eslint-disable-next-line no-undef
      error;
  }

  function catchError() {
      try {
          this.errFunc();
      } catch (error) {
          console.log(error);
      }
  }
  catchError()

能捕捉到的异常,必须是线程执行已经进入 try catch 但 try catch 未执行完的时候抛出来的,以下都是无法被捕获到的情形。

  1. 异步任务抛出的异常(执行时try catch已经从执行完了)

  2. promise(异常内部捕获到了,并未往上抛异常,使用catch处理)

  3. 语法错误(代码运行前,在编译时就检查出来了的错误)

  • 优点:能够较好地进行异常捕获,不至于使得页面由于一处错误挂掉

  • 缺点:显得过于臃肿,大多代码使用try ... catch包裹,影响代码可读性。

思考:请用一句话描述 try catch 能捕获到哪些 JS 异常

全局异常监听window.onerror

window.onerror 最大的好处就是同步任务、异步任务都可捕获,可以得到具体的异常信息、异常文件的URL、异常的行号与列号及异常的堆栈信息,再捕获异常后,统一上报至我们的日志服务器,而且可以全局监听,代码看起来也简洁很多。

  • 缺点:

  1. 此方法有一定的浏览器兼容性

  2. 跨域脚本无法准确捕获异常,跨域之后window.onerror捕获不到正确的异常信息,而是统一返回一个Script error,可通过在<script>使用crossorigin属性来规避这个问题

 

window.addEventListener('error'function() {
  console.log(error);
  // ...
  // 异常上报
});
throw new Error('这是一个错误');

Promise内部异常

前文已经提到,onerror 以及 try-catch 也无法捕获Promise实例抛出的异常,只能最后在 catch 函数上处理,但是代码写多了就容易糊涂,忘记写 catch。

如果你的应用用到很多的 Promise 实例的话,特别是在一些基于 promise 的异步库比如 axios 等一定要小心,因为你不知道什么时候这些异步请求会抛出异常而你并没有处理它,所以最好添加一个 Promise 全局异常捕获事件 unhandledrejection

window.addEventListener("unhandledrejection", e => {
 console.log('unhandledrejection',e)
});

vue工程异常

window.onerror并不能捕获.vue文件发生的获取,Vue 2.2.0以上的版本中增加了一个errorHandle,使用Vue.config.errorHandler这样的Vue全局配置,可以在Vue指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和Vue 实例。

//main.js
import { createApp } from "vue";
import App from "./App.vue";

let app = createApp(App);
app.config.errorHandler = function(e) {
  console.log(e);
  //错误上报...
};
app.mount("#app");

Vue项目JS脚本错误捕获

综上,可以将几种方式有效结合起来,这里是在vue-cli框架中做的处理,其余类似:

import { createApp } from "vue";
import App from "./App.vue";

let app = createApp(App);

window.addEventListener(
  "error",
  (e) => {
    console.log(e);
    //TODO:上报逻辑
    return true;
  },
  
小程序前端的数据埋点是一种技术手段,用于收集用户的行为数据、操作习惯等信息,帮助企业优化产品设计及运营策略。以下是关于小程序前端如何实现数据埋点的一些关键步骤: ### 1. 确定需求与目标 - 首先明确需要采集哪些数据(如点击事件、页面访问次数、停留时间等),并制定相应的指标体系。 ### 2. 设计日志结构 - 根据业务场景规划统一的日志格式,包括但不限于`event_id`, `timestamp`, `user_id`, 和其他自定义字段等内容。 ### 3. 实现基础功能 - **手动埋点**:直接在特定位置插入代码记录指定动作的发生情况; ```javascript function logEvent(eventType, eventData) { wx.request({ url: 'your_server_url', // 后端接收地址 method: "POST", data: { eventType, ...eventData }, success(res) {}, fail(err) {} }); } Page({ onLoad() { logEvent('page_load', { pageName: this.route }); // 页面加载时触发 }, handleButtonClick(e) { const targetId = e.target.id; logEvent('button_click', { buttonId: targetId }); // 按钮点击事件 } }) ``` - **自动化工具**:利用现有的第三方库或框架自动捕获常见交互行为,并减少手工编码量; ### 4. 数据传输与存储 - 使用HTTPS协议将本地生成的日志发送到服务器保存起来供后续分析处理使用;同时考虑异常断网重传机制提高成功率。 ### 5. 用户隐私保护 - 对涉及敏感个人信息的部分需脱敏后再上传至云端避免泄露风险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值