UNPKG

@ked3/ktrace

Version:

跨平台埋点分析SDK

169 lines (140 loc) 4.32 kB
import Tracker from "../core/Tracker"; import { TrackerConfig, EventKey } from "../core/types"; /** * HTML原生项目适配器类 */ class HtmlAdapter extends Tracker { /** * 构造函数 */ constructor(config: TrackerConfig) { super(config); } /** * 初始化适配器 */ public init(): void { if (typeof window === "undefined") { console.warn("[KTrace] HtmlAdapter 只能在浏览器环境中使用"); return; } const conf = this.getConfig(); console.log('conf',conf); // 自动添加点击追踪 if (this.getConfig().enable_auto_track) { this.setupAutoTracking(); } // 设置错误监听 this.setupErrorHandling(); if (this.getConfig().debug) { console.log("[KTrace] HTML适配器初始化成功"); } } /** * 设置自动追踪 */ private setupAutoTracking(): void { // 追踪页面访问 window.addEventListener("load", () => { this.trackPageView(); }); // 追踪页面离开 window.addEventListener("beforeunload", () => { this.trackEvent(EventKey.PAGE_LEAVE, { duration: Date.now() - (window as any).__pageLoadTime || 0, }); }); // 记录页面加载时间 (window as any).__pageLoadTime = Date.now(); // 设置路由追踪 this.setupRouteTracking(); } /** * 追踪页面浏览 */ public trackPageView(path?: string): void { const currentPath = path || window.location.pathname; try { this.trackEvent(EventKey.PAGE_VIEW, { path: currentPath, referrer: document.referrer, user_agent: navigator.userAgent, timestamp: Date.now() }); } catch (error) { if (this.getConfig().debug) { console.warn(`[KTrace] 页面浏览追踪失败:`, error); } } } /** * 设置路由追踪(支持SPA应用) */ private setupRouteTracking(): void { // 监听 popstate 事件(浏览器前进后退) window.addEventListener('popstate', () => { setTimeout(() => this.trackPageView(), 100); }); // 监听 pushState 和 replaceState const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = (...args) => { originalPushState.apply(history, args); setTimeout(() => this.trackPageView(), 100); }; history.replaceState = (...args) => { originalReplaceState.apply(history, args); setTimeout(() => this.trackPageView(), 100); }; } /** * 设置错误处理 */ private setupErrorHandling(): void { // 监听资源加载错误(图片、脚本、样式表等) window.addEventListener( "error", (event) => { // 检查是否是资源加载错误 if (event.target && event.target !== window) { const target = event.target as HTMLElement; const resourceUrl = (target as any).src || (target as any).href; const resourceType = target.tagName?.toLowerCase(); this.trackError(new Error("Resource load error"), EventKey.RESOURCE_ERROR, { target, resourceUrl, resourceType }); if (this.getConfig().debug) { console.warn( `[KTrace] 资源加载失败: ${resourceType} - ${resourceUrl}` ); } } else { // JavaScript运行时错误 this.trackError(new Error(event.message), EventKey.JAVASCRIPT_ERROR, { filename: event.filename, lineno: event.lineno, colno: event.colno, context: 'global' }); if (this.getConfig().debug) { console.warn(`[KTrace] JavaScript错误: ${event.message}`); } } }, true ); // 使用捕获阶段来确保能捕获到资源错误 // 监听未处理的Promise错误 window.addEventListener("unhandledrejection", (event) => { this.trackError(new Error(event.reason), EventKey.CUSTOM_ERROR, { error_type: 'unhandled_promise_rejection', context: 'global' }); if (this.getConfig().debug) { console.warn(`[KTrace] 未处理的Promise错误:`, event.reason); } }); } } export default HtmlAdapter;