当前位置: 首页 > news >正文

前端监控相关

1.前端监控
简易版的前端监控系统 – window.performance、window.onError??
1、Promise的错误如何监控?–promise不是所有都是接口请求
2、接口的报错如何监控?–全局监控sdk,不改动公共的请求方法、不改动业务代码;一般接口使用axios请求
3、资源的报错如何监控?
4、还有什么埋点方法?–clstag
在这里插入图片描述


【思路】

1. Promise 的错误如何监控

方法一:使用 unhandledrejection 事件

此事件会在 Promise 被拒绝且没有 .catch() 处理时触发。在全局监听该事件,可捕获未处理的 Promise 错误。

window.addEventListener('unhandledrejection', (event) => {
    const { reason, promise } = event;
    // 模拟上报错误信息到服务器
    console.log('未处理的 Promise 错误上报:', reason);
    event.preventDefault();
});
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>实际项目中的 Promise 错误监控</title>
</head>

<body>
    <h1>实际项目中的 Promise 错误监控</h1>
    <script>
        window.addEventListener('unhandledrejection', function (event) {
            const { reason, promise } = event;
            // 这里可以将错误信息上报到监控系统
            console.error('未处理的 Promise 错误:', reason);
            event.preventDefault();
        });

        // 模拟一个接口请求
        function fetchData() {
            return new Promise((resolve, reject) => {
                // 模拟请求失败
                setTimeout(() => {
                    reject(new Error('接口请求失败'));
                }, 1000);
            });
        }

        // 调用接口请求
        fetchData();
    </script>
</body>

</html>
方法二:封装 Promise 执行函数

封装一个函数来执行 Promise 并统一处理错误。

function safeExecutePromise(promiseExecutor) {
    return new Promise((resolve, reject) => {
        try {
            const promise = new Promise(promiseExecutor);
            promise
              .then((result) => {
                    resolve(result);
                })
              .catch((error) => {
                    // 模拟上报错误信息到服务器
                    console.log('Promise 错误上报:', error);
                    reject(error);
                });
        } catch (error) {
            // 捕获同步代码中的错误
            console.log('Promise 同步代码错误上报:', error);
            reject(error);
        }
    });
}

// 使用示例
const myPromiseExecutor = (resolve, reject) => {
    setTimeout(() => {
        // 模拟执行出错
        throw new Error('Promise 执行出错');
    }, 1000);
};

safeExecutePromise(myPromiseExecutor).catch((error) => {
    console.log('最终捕获的错误:', error);
});    

2. 接口的报错如何监控(使用 axios 请求)

方法一:利用 axios 实例的拦截器

通过创建 axios 实例并添加响应拦截器,可全局监控接口请求错误。

import axios from 'axios';

const axiosInstance = axios.create();

axiosInstance.interceptors.response.use(
    (response) => response,
    (error) => {
        const { config, response } = error;
        const { method, url } = config;
        const status = response? response.status : null;
        // 模拟上报错误信息到服务器
        console.log('接口请求错误上报:', { method, url, status, error });
        return Promise.reject(error);
    }
);

axiosInstance.get('https://nonexistent-url.com')
  .catch(() => {});
方法二:重写 axios 函数

可以重写 axios 函数,在其中添加错误处理和上报逻辑。

import axios from 'axios';

const originalAxios = axios;
axios = function (...args) {
    return originalAxios(...args)
      .then((response) => response)
      .catch((error) => {
            const { config, response } = error;
            const { method, url } = config;
            const status = response? response.status : null;
            // 模拟上报错误信息到服务器
            console.log('接口请求错误上报:', { method, url, status, error });
            throw error;
        });
};

axios.get('https://nonexistent-url.com')
  .catch(() => {});

3. 资源的报错如何监控

方法一:监听 error 事件

监听 windowerror 事件,针对资源加载错误进行处理。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>资源错误监控</title>
    <script>
        window.addEventListener('error', (event) => {
            const { target } = event;
            if (target.tagName === 'IMG' || target.tagName === 'SCRIPT' || target.tagName === 'LINK') {
                const resourceType = target.tagName === 'IMG'? '图片' : target.tagName === 'SCRIPT'? '脚本' : '样式表';
                const src = target.src || target.href;
                // 模拟上报错误信息到服务器
                console.log(`${resourceType} 加载错误上报:`, src);
            }
        }, true);
    </script>
</head>
<body>
    <img src="nonexistent-image.jpg" alt="示例图片">
    <script src="nonexistent-script.js"></script>
    <link rel="stylesheet" href="nonexistent-stylesheet.css">
</body>
</html>

4. 埋点方法结合代码示例

(1)自定义属性埋点 – 如京东官网“clstag” 埋点**

“clstag” 并不是一个具有普遍固定含义的术语,它在不同的上下文场景中可能有不同的指代,以下是一些可能的情况:
在前端开发的埋点业务里,“clstag” 常被用作自定义的标签或标识,用于精准记录和追踪用户的特定行为。例如,当你想要监控页面上不同按钮的点击情况时,可以给每个按钮赋予一个独特的 “clstag” 值。在后续进行数据上报和分析时,就能依据这个 “clstag” 来区分到底是哪个按钮被点击了。以下是一个简单的示例代码:

// 页面加载完成时
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>在 DOMContentLoaded 时添加 click 事件</title>
</head>

<body>
    <ul id="navitems-group1">
        <li clstag="h|keycount|head|navi_01" class="fore1">
            <a class="navitems-lk" target="_blank" rel="noopener noreferrer" href="#" aria-label="新品"
                style="color: rgb(26, 26, 26);">新品</a>
            <div class="spacer"></div>
        </li>
    </ul>
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            const elementsWithClstag = document.querySelectorAll('[clstag]');
            elementsWithClstag.forEach(function (element) {
                element.addEventListener('click', function () {
                    const clstag = this.getAttribute('clstag');
                    // 模拟上报数据
                    console.log('上报数据:', {
                        eventType: 'click',
                        clstag: clstag,
                        timestamp: new Date().getTime()
                    });
                });
            });
        });
    </script>
</body>

</html>

在这里插入图片描述

  • 特定业务系统或框架
    某些特定的业务系统或者框架可能会把 “clstag” 当作一个内部使用的标识符或者参数。比如,在某个电商系统里,“clstag” 也许会和商品的分类、促销活动关联起来,用来记录用户在浏览商品过程中的各种操作。
(2)代码埋点
  • 实现原理:开发人员在代码中手动插入埋点代码,在用户与页面交互的关键位置(如按钮点击、页面加载完成等)添加数据上报逻辑。
  • 优点
    • 可以精确控制埋点的位置和上报的数据,能满足复杂业务场景下的个性化埋点需求。
    • 对上报的数据格式和内容有完全的控制权。
  • 缺点
    • 开发成本较高,需要开发人员手动编写和维护大量的埋点代码。
    • 代码侵入性强,后期修改埋点逻辑可能会影响原有代码,增加维护难度。
  • 代码示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>代码埋点示例</title>
</head>
<body>
    <button id="myButton">点击我</button>
    <script>
        const button = document.getElementById('myButton');
        button.addEventListener('click', function() {
            // 模拟上报数据
            const data = {
                eventType: 'buttonClick',
                buttonText: this.textContent,
                timestamp: new Date().getTime()
            };
            // 实际应用中可使用 AJAX 等方式将数据发送到服务器
            console.log('上报数据:', data); 
        });
    </script>
</body>
</html>
(3)可视化埋点
  • 实现原理:借助专门的可视化埋点工具,业务人员可以在页面上直接圈选需要埋点的元素,工具会自动生成埋点代码并插入到页面中。
  • 优点
    • 降低了开发成本,业务人员可以自行配置埋点,无需开发人员参与。
    • 提高了埋点的效率,能够快速响应业务需求的变化。
  • 缺点
    • 功能相对固定,对于一些复杂的埋点需求可能无法满足。
    • 依赖于特定的可视化埋点工具,可能存在工具兼容性和稳定性问题。
  • 实现方式:通常需要使用第三方的埋点平台,如神策分析、诸葛 IO 等,这些平台提供可视化的埋点配置界面,业务人员在界面上进行操作后,平台会生成相应的埋点代码并提供集成方式。
/**
* 疑问:用户是否能在页面圈选?
回答:一般普通用户在正常使用页面时不能圈选,因为可视化埋点是为专业人员服务,
普通用户圈选可能影响页面稳定性和数据准确性。特殊情况下,部分产品可能开放圈选
用于个性化反馈或自定义体验,但会有相应限制和保护机制。

疑问:防止用户圈选的措施?
回答:从访问控制上,通过账号权限、IP 地址限制和特定入口设置(URL 参数、快捷键组合)
防止普通用户进入可视化模式;界面交互上,隐藏可视化操作层并对交互事件进行拦截;代码安全上,
对相关代码混淆加密,严格验证用户输入。

疑问:模拟插入埋点代码的部署?
回答:代码示例的模拟插入是在页面运行时动态创建 <script> 标签插入代码,页面刷新后消失。实
际部署需遵循上线流程,包括代码保存同步、审查、测试环境和预发布环境验证,最后部署到生产环境。
*/
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>可视化埋点配置模拟</title>
    <style>
        /* 模拟可视化操作层 */
        #visual-layer {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
            z-index: 9999;
        }

        /* 模拟元素高亮样式 */
        .highlight {
            outline: 2px solid red;
        }

        /* 模拟配置窗口样式 */
        #config-window {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: white;
            padding: 20px;
            border: 1px solid black;
            z-index: 10000;
            display: none;
        }
    </style>
</head>

<body>
    <button id="myButton">点击我</button>
    <div id="visual-layer"></div>
    <div id="config-window">
        <h2>埋点配置</h2>
        <label for="event-type">事件类型:</label>
        <select id="event-type">
            <option value="click">点击</option>
            <option value="mouseover">鼠标悬停</option>
            <option value="scroll">滚动</option>
        </select>
        <br>
        <label for="param-name">参数名称:</label>
        <input type="text" id="param-name">
        <br>
        <label for="param-value">参数值:</label>
        <input type="text" id="param-value">
        <br>
        <button id="save-config">保存配置</button>
    </div>
    <script>
        // 模拟 SDK 初始化
        const visualLayer = document.getElementById('visual-layer');
        const elements = document.querySelectorAll('*');
        const configWindow = document.getElementById('config-window');
        const saveConfigButton = document.getElementById('save-config');

        // 模拟开启可视化模式
        elements.forEach(element => {
            element.addEventListener('mouseover', function () {
                this.classList.add('highlight');
            });
            element.addEventListener('mouseout', function () {
                this.classList.remove('highlight');
            });
            element.addEventListener('click', function () {
                configWindow.style.display = 'block';
                saveConfigButton.addEventListener('click', function () {
                    const eventType = document.getElementById('event-type').value;
                    const paramName = document.getElementById('param-name').value;
                    const paramValue = document.getElementById('param-value').value;
                    // 模拟生成埋点代码
                    const trackingCode = `
                        this.addEventListener('${eventType}', function() {
                            const data = {
                                eventName: '${eventType}',
                                ${paramName}: '${paramValue}'
                            };
                            console.log('上报数据:', data);
                        });
                    `;
                    // 模拟插入埋点代码
                    const script = document.createElement('script');
                    script.textContent = trackingCode;
                    document.head.appendChild(script);
                    configWindow.style.display = 'none';
                });
            });
        });
    </script>
</body>

</html>
(3)无痕埋点
  • 实现原理:通过对页面的 DOM 结构和用户行为进行分析,自动识别和收集用户的行为数据,无需手动在代码中插入埋点代码。
  • 优点
    • 开发成本低,对代码无侵入性,不会影响原有代码的结构和功能。
    • 能够全面收集用户行为数据,覆盖范围广。
  • 缺点
    • 数据的精准度和灵活性相对较差,可能会收集到一些无用的数据。
    • 对于一些特殊的业务需求,可能无法满足个性化的埋点要求。
  • 代码示例(简单模拟)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>无痕埋点示例</title>
</head>
<body>
    <button>按钮</button>
    <a href="#">链接</a>
    <script>
        document.addEventListener('click', function(event) {
            const target = event.target;
            // 模拟上报数据
            const data = {
                eventType: 'click',
                elementType: target.tagName,
                elementText: target.textContent,
                timestamp: new Date().getTime()
            };
            console.log('上报数据:', data);
        });
    </script>
</body>
</html>
(4)全埋点
  • 实现原理:自动收集应用内所有的用户行为数据,包括页面浏览、元素点击、表单提交等。通常借助第三方 SDK 来实现。
  • 优点
    • 能够全面、无遗漏地收集用户行为数据,为数据分析提供丰富的素材。
    • 集成相对简单,只需引入 SDK 并进行基本配置即可。
  • 缺点
    • 会产生大量的数据,需要处理和分析的成本较高。
    • 可能会对性能产生一定影响,尤其是在数据量较大的情况下。
  • 实现方式:使用第三方的全埋点 SDK,如 Google Analytics、Mixpanel 等,按照 SDK 的文档进行集成和配置,SDK 会自动收集和上报各种用户行为数据。

「全埋点和无痕埋点的区别」
虽然无痕埋点和全埋点在收集数据方面有重叠,但全埋点在数据收集的全面性上通常更具优势,以下从多个维度详细说明二者的差异:

数据收集的深度与广度

  • 无痕埋点
    • 主要聚焦于一些通用的、常见的用户交互行为,像页面浏览、元素点击、表单提交等。它依据预设的规则和通用事件监听来收集数据,更倾向于收集表层的交互信息。
    • 例如,对于页面浏览,通常只记录页面的 URL、标题和用户停留时间;对于元素点击,仅记录点击元素的基本信息(如标签名、ID、类名)。
  • 全埋点
    • 追求全方位、深层次的数据收集,不仅会收集常见的用户交互行为,还会涵盖各种细微的操作和状态变化。
    • 比如在页面浏览方面,除了基本的页面信息和停留时间,还可能收集页面滚动的位置、滚动速度、页面内元素的曝光情况等;对于元素点击,会详细记录点击时的坐标、鼠标的按键类型(左键、右键、中键)等信息。

业务流程覆盖度

  • 无痕埋点
    • 对业务流程的覆盖相对有限,通常只能捕捉到一些明显的业务节点。例如在电商购物流程中,可能仅能记录用户进入商品详情页、点击加入购物车、提交订单等关键步骤。
    • 对于一些复杂的业务逻辑和中间状态,无痕埋点可能无法全面覆盖。比如在商品搜索过程中,用户的输入关键词变化、搜索结果的筛选操作等细节可能难以准确收集。
  • 全埋点
    • 致力于完整覆盖整个业务流程,从用户进入应用的初始状态,到每一个操作步骤和状态转换,都会进行详细记录。
    • 仍以电商购物为例,全埋点可以记录用户在搜索框输入关键词的每一次按键、筛选条件的选择和取消、商品的比较过程等,为分析用户的购物决策过程提供更丰富的数据支持。

自定义与扩展性

  • 无痕埋点
    • 通常基于预设的规则和模式进行数据收集,自定义程度相对较低。如果需要收集一些特殊的业务数据或满足特定的分析需求,可能需要对埋点规则进行调整,这可能会增加一定的开发成本和复杂度。
    • 例如,对于一些特定行业的业务指标,无痕埋点可能无法直接支持,需要额外的开发工作来实现。
  • 全埋点
    • 一般借助强大的第三方 SDK 实现,具有较高的可定制性和扩展性。可以根据不同的业务需求,灵活配置需要收集的数据字段和规则。
    • 比如,企业可以根据自身的业务特点,自定义收集某些特定元素的属性变化、用户在特定时间段内的操作频率等数据,以满足个性化的分析需求。

数据准确性与完整性

  • 无痕埋点
    • 由于是基于通用规则自动收集数据,可能会存在一些数据遗漏或不准确的情况。例如,在复杂的页面结构中,可能会出现事件监听失败或误判的问题,导致部分数据无法正常收集。
    • 而且,无痕埋点对于一些动态生成的元素或异步加载的内容,可能无法及时准确地进行数据收集。
  • 全埋点
    • 通过更全面的事件监听和数据采集机制,能够最大程度地保证数据的准确性和完整性。SDK 会对页面的各种状态和变化进行实时监控,及时捕捉用户的每一个操作行为。
    • 同时,全埋点通常会有更完善的数据校验和纠错机制,确保收集到的数据质量较高。

相关文章:

  • GPU中HBM2和GDDR显存比较, 数据传输带宽具体比较
  • AtCoder [ABC156E] Roaming
  • Vue.js 组件开发全解析:从基础概念到实战应用
  • leeCode 70. 爬楼梯
  • Java单例模式中的饿汉模式和懒汉模式
  • 使用ES支持树状结构查询实战
  • SQLite 查询数据库属性
  • 一道积分_3
  • Linux多线程
  • Java 大视界 -- 基于 Java 的大数据机器学习模型的可扩展性设计与实践(149)
  • 使用 Python 开发 MCP Server 及 Inspector 工具详解
  • 【2025 华中师范大学-菜鸟杯程序设计竞赛】部分题解
  • 多模态工作idea讨论
  • HTTPS协议—加密算法和中间攻击人的博弈
  • 【Dive Into Stable Diffusion v3.5】2:Stable Diffusion v3.5原理介绍
  • Baklib驱动企业数字化内容管理升级
  • WebSocket接入SSL证书
  • Java面试黄金宝典11
  • 数据库锁机制
  • 《Oracle DBA入门实战:十大高频问题详解与避坑指南》
  • 海外市场,押注中国无人驾驶龙头
  • 幼儿园教师拍打孩子额头,新疆库尔勒教育局:涉事教师已被辞退
  • 新片|《碟中谍8:最终清算》定档5月30日
  • 政企共同发力:多地密集部署外贸企业抢抓90天政策窗口期
  • 浙江省台州市政协原副主席林虹被“双开”
  • 明查| 新一代AI诊疗系统可3秒筛查13种癌症?没有证据