统计用户点击按钮 — 交互式触发埋点
假设我们希望记录某些按钮的使用次数的数据,可以在 document
上监听 click
事件,目的利用事件冒泡以便于不需要侵入不同按钮的 click
事件,比如:
const TargetElementFilter = ['export_btn'] const findTarget = (filters) => { return filters.find((filter) => TargetElementFilter.find((v) => filter === v))); } document.addEventListener('click', (e) => { const { id, className, outerHTML } = e.target const isTarget = findTarget([id, className]) if (isTarget) { SDK.actionReport({ data: { id, className, outerHTML }, // 其他必要传递的信息 }) } }) 复制代码
上报页面性能
和页面性能相关的内容,属于 SDK
自动触发埋点,不应该让使用者在手动接入,在上面的实现中,我们在 pageshow
事件中通 reportWebVitals
和 performanceReport
进行数据上报,并且这里选择了 Google
推出的 web-vitals
来获取和页面性能指标相关的具体数据,对应代码为:
// 通过 web-vitals 页面性能指标 const reportWebVitals = (onPerfEntry) => { if (onPerfEntry && onPerfEntry instanceof Function) { import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { getCLS(onPerfEntry) // 布局偏移量 getFID(onPerfEntry) // 首次输入延迟时间 getFCP(onPerfEntry) // 首次内容渲染时间 getLCP(onPerfEntry) // 首次最大内容渲染时间 getTTFB(onPerfEntry) // 首个字节到达时间 }) } } 复制代码
获取得到的数据大致如下:
上报错误警告
全局错误
全局错误,即未被捕获的错误,可以通过 window.onerror
事件来捕获,然后进行错误数据上报,大致如下:
window.addEventListener('error', (reason) => { const { filename, message, error } = reason; window.SDK.errorReport({ data: { filename, message, error } }); }) 复制代码
局部错误
局部错误,即通过 try...catch、promise.then、promise.catch
等捕获的错误,大致使用如下:
try { throw new Error('error for test') } catch(error) { window.SDK.errorReport({ data: { error, }, }) } Promise.reject(new Error('Promise reject for test')) .then( () => {}, (reason) => { window.SDK.errorReport({ data: { error: reason } }); }, ) Promise.reject(new Error('Promise reject for test')) .catch( (reason) => { window.SDK.errorReport({ data: { error: reason } }); }, ) 复制代码
接口请求错误
接口请求错误,即在二次封装请求 API
中进行请求和接收响应时的错误,为了方便这里以 axios
来举例子,我们可以在它的 请求拦截 和 响应拦截 的第二个回调参数中去上报对应的错误数据信息,大致如下:
// 创建axios实例 const service = axios.create({ baseURL, // api 的 base_url timeout: 60000, // 请求超时时间 responseType: reqConf.responseType, }); // 请求拦截 service.interceptors.request.use( (config) => { ... return config; }, (error) => { window.SDK.errorReport({ apiUrl: config.url, data: { error, }, }) }, ); // 响应拦截 service.interceptors.response.use( (config: any) => { ... return config; }, (error: any) => { window.SDK.errorReport({ apiUrl: config.url, data: { error, }, }) return error.response.data; }, ); 复制代码
组件级错误
组件级错误,即使用 Vue / React
框架组件时发生的错误,完全可以使用它们在官方文档中提到的错误捕获方式来捕获并上报错误。
Vue
中的errorHandler
就是用于为应用内抛出的未捕获错误指定一个全局处理函:
// App.vue onMounted(()=>{ throw new Error('error in onMounted') }); // main.ts const app = createApp(App) app.config.errorHandler = (error, instance, info) => { window.SDK.errorReport({ data: { instance, info, error } }); } 复制代码
React
中的ErrorBoundary
错误边界相关的getDerivedStateFromError
和componentDidCatch
钩子
// 定义错误边界组件 class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // 更新 state 使下一次渲染能够显示降级后的 UI return { hasError: true }; } componentDidCatch(error, info) { // 可以将错误日志上报给服务器 window.SDK.errorReport({ data: { info, error } }); } render() { if (this.state.hasError) { // 自定义降级后的 UI 并渲染 、 return <h1>Something went wrong.</h1>; } return this.props.children; } } // 使用错误边界组件 <ErrorBoundary> <MyWidget /> </ErrorBoundary> 复制代码
最后
【统一回复私信】
想交个朋友的可以添加 微信号:Mr10212021 ,也欢迎关注同名公众号《熊的猫》,文章会同步更新!
现在我们了解了 前端数据埋点 SDK 的二三事,通过上面的例子可能让你觉得看起来比较简单,但是真的要做好数据埋点也必然没有那么容易,比如好需要考虑你的 SDK 数据发送的时间、发送的次数、需不需要将某些数据信息整合在一起只发送一次、怎么避免网络拥塞等等问题。