前端异常监控:如何捕获并上报JS错误与白屏?

前端异常监控:如何捕获并上报JS错误与白屏?

引言

在现代前端开发中,用户体验是衡量产品成功与否的关键指标。然而,前端应用运行在复杂多变的环境中,浏览器差异、网络问题、设备性能等因素都可能导致各种异常情况的发生。如何及时发现并解决这些问题,成为前端工程师面临的重要挑战。

本文将深入探讨前端异常监控的核心技术,包括JS错误捕获、白屏监控以及错误上报机制,帮助开发者构建更加稳定可靠的前端应用。

一、JS错误捕获技术

1.1 try-catch 语句

最基础的错误捕获方式是使用 try-catch 语句,它可以捕获代码块中同步执行的错误:

/** * 捕获同步代码错误 * @param {Function} fn - 要执行的函数 * @param {Function} fallback - 错误处理函数 * @returns {any} 函数执行结果 */functionsafeExecute(fn, fallback){try{returnfn();}catch(error){ console.error('执行出错:', error);return fallback ?fallback(error):null;}}// 使用示例safeExecute(()=>{const result =10/0;// 会导致错误return result;},(error)=>{ console.log('捕获到错误,执行备用方案');return0;});

局限性try-catch 只能捕获同步错误,无法捕获异步错误和Promise中的错误。

1.2 window.onerror 事件

window.onerror 可以捕获全局范围内的JS错误,包括异步错误:

/** * 全局错误捕获 */functionsetupGlobalErrorHandler(){ window.onerror=function(message, source, lineno, colno, error){ console.error('全局错误:',{ message, source, lineno, colno, error });// 这里可以添加错误上报逻辑returntrue;// 阻止默认处理};}// 启用全局错误捕获setupGlobalErrorHandler();

注意事项

  • 对于跨域脚本,需要在脚本标签中添加 crossorigin 属性
  • 某些浏览器可能不会提供完整的错误信息

1.3 Promise 错误捕获

Promise 中的错误需要使用 catch 方法或 unhandledrejection 事件来捕获:

/** * Promise 错误捕获 */functionsetupPromiseErrorHandler(){ window.addEventListener('unhandledrejection',function(event){ console.error('未处理的Promise错误:',{reason: event.reason,promise: event.promise });// 这里可以添加错误上报逻辑 event.preventDefault();// 阻止默认处理});}// 启用Promise错误捕获setupPromiseErrorHandler();

1.4 Vue 应用中的错误捕获

在 Vue 应用中,可以使用 errorHandler 来捕获组件渲染和观察期间的错误:

import Vue from'vue';/** * Vue 错误捕获 */ Vue.config.errorHandler=function(err, vm, info){ console.error('Vue 错误:',{error: err,component: vm ? vm.$options.name ||'Anonymous Component':'Unknown', info // 错误发生的位置信息});// 这里可以添加错误上报逻辑};

对于 Vue 3,可以使用 app.config.errorHandler

import{ createApp }from'vue';const app =createApp(App); app.config.errorHandler=(err, instance, info)=>{ console.error('Vue 3 错误:',{error: err, instance, info });// 这里可以添加错误上报逻辑}; app.mount('#app');

二、白屏监控技术

白屏是前端应用中另一个严重影响用户体验的问题。白屏监控主要有以下几种方案:

2.1 基于DOM元素的监控

通过检查关键DOM元素是否存在来判断是否发生白屏:

/** * 白屏监控 - 基于DOM元素 * @param {string} selector - 关键DOM元素选择器 * @param {number} timeout - 超时时间(ms) * @param {Function} callback - 白屏回调 */functionmonitorWhiteScreen(selector, timeout =3000, callback){const checkTime = Date.now();functioncheckElement(){const element = document.querySelector(selector);if(element){ console.log('页面正常加载');}else{if(Date.now()- checkTime > timeout){ console.error('检测到白屏');if(callback){callback();}}else{requestAnimationFrame(checkElement);}}}requestAnimationFrame(checkElement);}// 使用示例monitorWhiteScreen('#app',5000,()=>{// 白屏处理逻辑 console.log('上报白屏事件');});

2.2 基于视觉的监控

通过检查页面的可见内容来判断是否发生白屏:

/** * 白屏监控 - 基于视觉 * @param {number} threshold - 阈值(0-1) * @param {number} timeout - 超时时间(ms) * @param {Function} callback - 白屏回调 */functionmonitorVisualWhiteScreen(threshold =0.8, timeout =3000, callback){const checkTime = Date.now();functioncheckVisual(){if(Date.now()- checkTime > timeout){const body = document.body;const rect = body.getBoundingClientRect();const area = rect.width * rect.height;if(area ===0){ console.error('检测到白屏:body面积为0');if(callback)callback();return;}// 这里可以添加更复杂的视觉检测逻辑// 例如使用Canvas截图分析像素 console.log('页面视觉检查通过');}else{requestAnimationFrame(checkVisual);}}requestAnimationFrame(checkVisual);}

2.3 基于性能指标的监控

利用Performance API监控页面加载性能,间接判断白屏情况:

/** * 白屏监控 - 基于性能指标 * @param {number} timeout - 超时时间(ms) * @param {Function} callback - 白屏回调 */functionmonitorPerformanceWhiteScreen(timeout =5000, callback){const checkTime = Date.now();functioncheckPerformance(){if(Date.now()- checkTime > timeout){const navigation = performance.getEntriesByType('navigation')[0];if(navigation){ console.log('页面性能指标:',{domContentLoadedEventEnd: navigation.domContentLoadedEventEnd,loadEventEnd: navigation.loadEventEnd });// 如果关键时间点为0,可能发生了白屏if(navigation.domContentLoadedEventEnd ===0){ console.error('检测到白屏:DOM未加载完成');if(callback)callback();}}}else{requestAnimationFrame(checkPerformance);}}requestAnimationFrame(checkPerformance);}

三、错误上报机制

捕获错误只是第一步,更重要的是将错误信息上报到服务器,以便开发团队及时发现和解决问题。

3.1 错误上报数据结构

一个完整的错误上报数据结构应该包含以下信息:

/** * 构建错误上报数据 * @param {Error} error - 错误对象 * @param {string} type - 错误类型 * @returns {Object} 错误上报数据 */functionbuildErrorReport(error, type ='js'){return{// 错误基本信息 type,message: error.message ||'未知错误',stack: error.stack ||'',// 上下文信息url: window.location.href,userAgent: navigator.userAgent,timestamp: Date.now(),// 设备信息device:{screenWidth: window.screen.width,screenHeight: window.screen.height,language: navigator.language },// 网络信息network: navigator.connection ?{type: navigator.connection.type,effectiveType: navigator.connection.effectiveType,rtt: navigator.connection.rtt }:null,// 用户信息(可选,需注意隐私)userId:getUserId()// 假设有一个获取用户ID的函数};}

3.2 错误上报策略

为了平衡实时性和性能,需要设计合理的错误上报策略:

/** * 错误上报管理器 */classErrorReporter{constructor(){this.queue =[];this.batchSize =10;// 批量上报大小this.debounceTime =1000;// 防抖时间(ms)this.debounceTimer =null;this.apiUrl ='/api/error-report';// 上报接口}/** * 上报错误 * @param {Object} errorData - 错误数据 */report(errorData){this.queue.push(errorData);this.scheduleReport();}/** * 调度上报 */scheduleReport(){if(this.queue.length >=this.batchSize){this.flush();return;}if(this.debounceTimer){clearTimeout(this.debounceTimer);}this.debounceTimer =setTimeout(()=>{this.flush();},this.debounceTime);}/** * 执行上报 */asyncflush(){if(this.queue.length ===0)return;const errors =[...this.queue];this.queue =[];try{const response =awaitfetch(this.apiUrl,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({ errors })});if(!response.ok){ console.error('错误上报失败:', response.status);// 失败后可以重试或存储到本地this.queue.unshift(...errors);}else{ console.log('错误上报成功');}}catch(error){ console.error('上报网络错误:', error);// 网络错误时存储到本地this.queue.unshift(...errors);}}}// 创建错误上报实例const errorReporter =newErrorReporter();

3.3 本地存储与重试机制

为了应对网络不稳定的情况,可以添加本地存储和重试机制:

/** * 增强版错误上报管理器 */classEnhancedErrorReporterextendsErrorReporter{constructor(){super();this.storageKey ='error-reports';this.loadFromStorage();}/** * 从本地存储加载错误 */loadFromStorage(){try{const stored = localStorage.getItem(this.storageKey);if(stored){const errors =JSON.parse(stored);this.queue.push(...errors); localStorage.removeItem(this.storageKey); console.log('从本地存储恢复错误报告:', errors.length);}}catch(error){ console.error('加载本地错误报告失败:', error);}}/** * 保存错误到本地存储 */saveToStorage(){try{if(this.queue.length >0){ localStorage.setItem(this.storageKey,JSON.stringify(this.queue)); console.log('错误报告已保存到本地存储');}}catch(error){ console.error('保存错误报告到本地存储失败:', error);}}/** * 执行上报 */asyncflush(){if(this.queue.length ===0)return;const errors =[...this.queue];try{// 调用父类的flush方法awaitsuper.flush();}finally{// 如果还有未上报的错误,保存到本地if(this.queue.length >0){this.saveToStorage();}}}}

四、综合监控方案

将上述技术整合起来,构建一个完整的前端异常监控系统:

4.1 监控系统架构

/** * 前端监控系统 */classFrontendMonitor{constructor(options ={}){this.options ={errorReportUrl:'/api/error-report',whiteScreenSelector:'#app',whiteScreenTimeout:5000,...options };this.errorReporter =newEnhancedErrorReporter();this.errorReporter.apiUrl =this.options.errorReportUrl;this.setupErrorHandlers();this.setupWhiteScreenMonitor();}/** * 设置错误处理器 */setupErrorHandlers(){// 全局错误处理 window.onerror=(message, source, lineno, colno, error)=>{const errorData =buildErrorReport(error ||newError(message),'js'); errorData.detail ={ source, lineno, colno };this.errorReporter.report(errorData);returntrue;};// Promise错误处理 window.addEventListener('unhandledrejection',(event)=>{const errorData =buildErrorReport(event.reason,'promise');this.errorReporter.report(errorData); event.preventDefault();});// 资源加载错误 window.addEventListener('error',(event)=>{if(event.target instanceofElement){const errorData ={type:'resource',message:`资源加载失败: ${event.target.src || event.target.href}`,url: window.location.href,userAgent: navigator.userAgent,timestamp: Date.now(),detail:{tagName: event.target.tagName,src: event.target.src,href: event.target.href }};this.errorReporter.report(errorData);}},true);}/** * 设置白屏监控 */setupWhiteScreenMonitor(){monitorWhiteScreen(this.options.whiteScreenSelector,this.options.whiteScreenTimeout,()=>{const errorData ={type:'white-screen',message:'页面白屏',url: window.location.href,userAgent: navigator.userAgent,timestamp: Date.now(),detail:{selector:this.options.whiteScreenSelector,timeout:this.options.whiteScreenTimeout }};this.errorReporter.report(errorData);});}/** * 手动上报错误 * @param {Error|string} error - 错误对象或错误信息 * @param {Object} context - 上下文信息 */reportError(error, context ={}){const errorObj =typeof error ==='string'?newError(error): error;const errorData =buildErrorReport(errorObj,'custom'); errorData.context = context;this.errorReporter.report(errorData);}/** * 上报性能指标 * @param {Object} metrics - 性能指标 */reportPerformance(metrics){const performanceData ={type:'performance',url: window.location.href,userAgent: navigator.userAgent,timestamp: Date.now(), metrics };this.errorReporter.report(performanceData);}}

4.2 使用示例

// 初始化监控系统const monitor =newFrontendMonitor({errorReportUrl:'https://monitor.example.com/api/report',whiteScreenSelector:'.main-content',whiteScreenTimeout:8000});// 手动上报错误functionriskyOperation(){try{// 可能出错的操作}catch(error){ monitor.reportError(error,{operation:'riskyOperation',params:{/* 相关参数 */}});}}// 上报性能指标functionreportPagePerformance(){const navigation = performance.getEntriesByType('navigation')[0];if(navigation){ monitor.reportPerformance({domContentLoaded: navigation.domContentLoadedEventEnd - navigation.startTime,loadTime: navigation.loadEventEnd - navigation.startTime,firstPaint: performance.getEntriesByName('first-paint')[0]?.startTime ||0,firstContentfulPaint: performance.getEntriesByName('first-contentful-paint')[0]?.startTime ||0});}}// 页面加载完成后上报性能 window.addEventListener('load', reportPagePerformance);

五、实践建议与最佳实践

5.1 错误监控最佳实践

  1. 分级监控:根据错误的严重程度进行分级,优先处理影响用户体验的严重错误
  2. 上下文丰富:上报错误时附带足够的上下文信息,如用户操作路径、设备信息等
  3. 采样率控制:对于高频错误,设置合理的采样率,避免上报数据过多
  4. 版本管理:在错误上报中包含应用版本信息,便于定位问题
  5. 测试环境:在测试环境中验证监控系统的有效性

5.2 白屏监控最佳实践

  1. 多维度监控:结合DOM元素检查、视觉检查和性能指标进行综合判断
  2. 阈值调优:根据不同页面的加载特性,调整合理的白屏检测阈值
  3. 排除干扰:对于首屏确实为空的页面,需要设置排除规则
  4. 用户反馈:提供用户主动反馈白屏的渠道

5.3 性能优化建议

  1. 代码分割:减少首屏加载时间,降低白屏概率
  2. 资源预加载:对于关键资源,使用预加载技术
  3. 错误边界:在React/Vue等框架中使用错误边界,防止单个组件错误导致整个应用崩溃
  4. 离线缓存:使用Service Worker缓存静态资源,提高页面加载可靠性

六、实际应用案例

6.1 案例一:电商网站异常监控

背景:某电商网站在大促期间频繁出现白屏和JS错误,严重影响用户购物体验。

解决方案

  1. 部署前端监控系统,实时捕获错误和白屏事件
  2. 针对高频错误进行优先级排序,快速修复
  3. 优化首屏加载逻辑,减少白屏时间
  4. 建立错误预警机制,当错误率超过阈值时及时告警

效果

  • 错误捕获率提升至98%以上
  • 白屏率从5%下降至0.5%
  • 问题定位时间从小时级缩短至分钟级

6.2 案例二:单页应用性能监控

背景:某单页应用在复杂操作时经常出现卡顿和错误,用户满意度低。

解决方案

  1. 集成前端监控系统,捕获运行时错误
  2. 监控关键操作的性能指标,如页面切换时间、API响应时间
  3. 分析错误分布,发现并修复内存泄漏问题
  4. 优化路由懒加载策略,减少初始加载时间

效果

  • 用户操作错误率下降60%
  • 页面切换速度提升40%
  • 用户满意度提升25%

七、未来发展趋势

7.1 智能化监控

随着AI技术的发展,前端监控系统将向智能化方向演进:

  1. 错误聚类:自动对错误进行聚类分析,识别相似错误模式
  2. 根因分析:利用机器学习算法自动分析错误根因
  3. 预测性监控:基于历史数据预测可能出现的问题
  4. 自适应阈值:根据应用状态自动调整监控阈值

7.2 全链路监控

前端监控将与后端监控、用户行为分析等系统深度融合,构建全链路监控体系:

  1. 用户旅程追踪:从用户点击到页面渲染的完整链路监控
  2. 端到端性能监控:前端性能与后端API性能的关联分析
  3. 跨设备监控:统一监控不同设备、不同浏览器的表现
  4. 实时可视化:提供直观的监控数据可视化界面

7.3 隐私保护

在监控系统发展的同时,用户隐私保护也将成为重要考量:

  1. 数据脱敏:对敏感信息进行自动脱敏处理
  2. 合规性:符合GDPR、CCPA等隐私法规要求
  3. 用户可控:提供用户选择退出监控的机制
  4. 数据最小化:只收集必要的监控数据

八、总结

前端异常监控是构建稳定可靠前端应用的重要保障,它不仅可以帮助开发者及时发现和解决问题,还可以为产品优化提供数据支撑。本文介绍的JS错误捕获、白屏监控和错误上报技术,为构建完整的前端监控系统提供了技术基础。

在实际应用中,需要根据项目的具体情况,选择合适的监控策略和技术方案。同时,要注重监控系统本身的性能和可靠性,避免监控代码成为新的性能瓶颈。

随着前端技术的不断发展,前端监控系统也在不断演进。未来,智能化、全链路和隐私保护将成为前端监控的重要发展方向。作为前端开发者,我们需要持续关注这些变化,不断优化监控策略,为用户提供更加稳定、流畅的前端体验。

结语

前端异常监控是一项需要持续投入和优化的工作,它不仅是技术问题,更是产品质量和用户体验的重要组成部分。通过本文介绍的技术和实践,希望能够帮助开发者构建更加完善的前端监控系统,让前端应用更加稳定可靠,为用户创造更好的使用体验。

记住,一个好的监控系统不仅能够捕获错误,更能够帮助我们理解用户的真实使用场景,为产品的持续优化提供数据驱动的决策依据。让我们一起努力,构建更加健康的前端生态系统。

Read more

【Model】【llm38】Llama API - 示例

【Model】【llm38】Llama API - 示例

案例目标 Llama API是一个托管的Llama 2 API服务,支持函数调用功能。本案例展示了如何通过LlamaIndex集成Llama API,实现基本的文本补全、对话交互、函数调用和结构化数据提取功能。Llama API为开发者提供了一个便捷的方式来使用Llama 2模型,无需本地部署,可以直接通过API调用模型服务,大大简化了使用流程。同时,该API支持函数调用功能,使得模型能够与外部工具和服务进行交互,扩展了应用场景。 环境配置 1. 安装依赖 安装必要的依赖包: %pip install llama-index-program-openai %pip install llama-index-llms-llama-api !pip install llama-index 2. 获取API密钥 要运行此示例,您需要从Llama API官网获取API密钥。 3. 导入库并设置API密钥 导入必要的库并设置API密钥: from llama_index.llms.llama_api import LlamaAPI

Cogito-v1-preview-llama-3B保姆级教程:Ollama模型卸载、重载与缓存清理

Cogito-v1-preview-llama-3B保姆级教程:Ollama模型卸载、重载与缓存清理 本文详细讲解Cogito v1预览版模型的完整使用流程,重点介绍如何正确卸载、重载模型以及清理缓存,帮助您更好地管理Ollama环境中的AI模型。 1. Cogito v1预览版模型介绍 Cogito v1预览版是Deep Cogito推出的混合推理模型系列,这个3B参数的模型在大多数标准基准测试中都表现出色,超越了同等规模下最优的开源模型。无论是来自LLaMA、DeepSeek还是Qwen等模型的同类产品,Cogito v1都展现出了更强的性能。 Cogito模型是经过指令调优的生成式模型,采用文本输入和文本输出的方式。最重要的是,所有模型都以开放许可发布,允许商业使用,这为开发者提供了极大的便利。 模型核心特点: * 混合推理能力:既可以直接回答问题,也可以在回答前进行自我反思 * 使用迭代蒸馏和放大(IDA)训练策略,通过自我改进实现智能提升 * 针对编码、STEM、指令执行和通用帮助性进行了专门优化 * 支持超过30种语言,上下文长度达到128k * 在

企业级图像AIGC技术观察:Seedream 4.0 模型能力与应用场景分析

企业级图像AIGC技术观察:Seedream 4.0 模型能力与应用场景分析

引言:突破视觉创作的传统限制 在视觉内容的创作领域,长久以来存在着一系列由技术、时间及预算构成的严格限制。这些限制直接影响着创意从概念到最终呈现的全过程。一个富有创造力的设计师,可能会因为无法承担高昂的实地拍摄费用,而不得不放弃一个原本极具潜力的广告方案。一个构思了宏大世界观的故事作者,可能因为不具备操作复杂三维建模软件的专业技能,而使其笔下的角色无法获得具象化的视觉呈现。一家新兴的初创公司,也可能因为传统设计流程的冗长和低效,在快速变化的市场竞争中错失发展机会。 社会和行业在某种程度上已经习惯了这种因工具和流程限制而产生的“创意妥协”。创作者们在面对自己宏大的构想时,常常因为工具的局限性而感到无力。一种普遍的观念是,顶级的、具有专业水准的视觉呈现,是少数拥有充足资源和专业团队的机构或个人的专属领域。 然而,由豆包·图像创作模型Seedream 4.0所引领的技术发展,正在从根本上改变这一现状。它所提供的并非是对现有工具集的微小改进或功能补充,而是一种全新的、高效的创作工作模式。通过这一模式,过去需要专业团队投入数周时间才能完成的复杂视觉项目,现在可以在极短的时间内,在操作者的

Qwen-Image-Edit-2511让AI绘画更有逻辑,空间关系更准

Qwen-Image-Edit-2511让AI绘画更有逻辑,空间关系更准 你有没有试过这样编辑一张图:想把照片里沙发左边的绿植换成一盏落地灯,结果AI不仅把灯放歪了,还让灯罩朝向窗外、影子却打在天花板上?或者给产品图换背景时,明明提示“纯白无影”,生成的阴影却像被风吹斜了三十度? 更让人挠头的是——你反复强调“人物站在门框正中央”,可AI总把人往右偏两厘米;你说“茶几在沙发前方一米处”,它却生成出茶几腿悬空半截的诡异构图。 这不是你提示词写得不够细,而是大多数图像编辑模型根本没真正理解‘左/右/前/后/上/下’这些空间关系。它们靠统计关联猜位置,而不是用几何逻辑推理布局。 直到我试了 Qwen-Image-Edit-2511 ——这个刚发布的增强版图像编辑镜像,第一次让我觉得:AI开始“看懂”画面里的三维世界了。 它不是又一个参数堆出来的“更大更快”,而是一次对空间语义的重新校准。下面这趟实测,我会带你亲眼看看:什么叫“让AI绘画真正讲逻辑”。 1. 它到底强在哪?不是修图,是重建空间认知 Qwen-Image-Edit-2511 是 Qwen-Image-Edit-2