UNPKG

my-performance-sdk

Version:

前端性能监控SDK,支持FCP、LCP、TBT、TTI和内存泄漏监控

781 lines (772 loc) 22 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); /** * 获取内存使用信息 */ function getMemoryInfo() { if ('memory' in performance) { const memory = performance.memory; return { usedJSHeapSize: memory.usedJSHeapSize, jsHeapSizeLimit: memory.jsHeapSizeLimit, totalJSHeapSize: memory.totalJSHeapSize }; } return null; } /** * 获取页面加载时间 */ function getLoadTime() { const navigation = performance.getEntriesByType('navigation')[0]; if (navigation) { return navigation.loadEventEnd - navigation.loadEventStart; } return 0; } /** * 获取DOM内容加载时间 */ function getDOMContentLoadedTime() { const navigation = performance.getEntriesByType('navigation')[0]; if (navigation) { return navigation.domContentLoadedEventEnd - navigation.domContentLoadedEventStart; } return 0; } /** * 计算总阻塞时间 (TBT) */ function calculateTBT() { const longTasks = performance.getEntriesByType('longtask'); let totalBlockingTime = 0; longTasks.forEach(task => { const longTask = task; // 只计算超过50ms的任务 if (longTask.duration > 50) { totalBlockingTime += longTask.duration - 50; } }); return totalBlockingTime; } /** * 计算可交互时间 (TTI) */ function calculateTTI() { const navigation = performance.getEntriesByType('navigation')[0]; if (!navigation) return 0; // 简化的TTI计算:DOM内容加载完成时间 + 总阻塞时间 const domContentLoaded = navigation.domContentLoadedEventEnd; const tbt = calculateTBT(); return domContentLoaded + tbt; } /** * 获取Web Vitals指标 */ function getWebVitals() { const vitals = {}; // 获取FCP const fcpEntry = performance.getEntriesByName('first-contentful-paint')[0]; if (fcpEntry) { vitals.fcp = fcpEntry.startTime; } // 获取LCP const lcpEntries = performance.getEntriesByType('largest-contentful-paint'); if (lcpEntries.length > 0) { const lastLCP = lcpEntries[lcpEntries.length - 1]; vitals.lcp = lastLCP.startTime; } // 计算TBT vitals.tbt = calculateTBT(); // 计算TTI vitals.tti = calculateTTI(); return vitals; } /** * 获取完整的性能指标 */ function getPerformanceMetrics$1() { const metrics = {}; // 获取Web Vitals const vitals = getWebVitals(); metrics.fcp = vitals.fcp; metrics.lcp = vitals.lcp; metrics.tbt = vitals.tbt; metrics.tti = vitals.tti; // 获取内存信息 const memory = getMemoryInfo(); if (memory) { metrics.memory = memory; } // 获取页面加载时间 metrics.loadTime = getLoadTime(); metrics.domContentLoaded = getDOMContentLoadedTime(); return metrics; } /** * 内存泄漏检测器 */ class MemoryLeakDetector { constructor(onLeakDetected) { this.memoryHistory = []; this.maxHistoryLength = 50; this.detectionInterval = null; this.onLeakDetected = onLeakDetected; } /** * 开始内存泄漏检测 */ start(intervalMs = 5000) { if (this.detectionInterval) { this.stop(); } this.detectionInterval = window.setInterval(() => { this.checkMemoryLeak(); }, intervalMs); } /** * 停止内存泄漏检测 */ stop() { if (this.detectionInterval) { clearInterval(this.detectionInterval); this.detectionInterval = null; } } /** * 检查内存泄漏 */ checkMemoryLeak() { var _a; const currentMemory = this.getMemoryInfo(); if (!currentMemory) return; this.memoryHistory.push(currentMemory); // 保持历史记录长度 if (this.memoryHistory.length > this.maxHistoryLength) { this.memoryHistory.shift(); } // 计算内存增长趋势 if (this.memoryHistory.length >= 10) { const trend = this.calculateMemoryTrend(); // 如果内存持续增长且增长幅度超过阈值,认为可能存在内存泄漏 if (trend > 0.1) { // 10%的增长阈值 (_a = this.onLeakDetected) === null || _a === void 0 ? void 0 : _a.call(this, { current: currentMemory, trend: trend }); } } } /** * 计算内存增长趋势 */ calculateMemoryTrend() { if (this.memoryHistory.length < 10) return 0; const recent = this.memoryHistory.slice(-10); const older = this.memoryHistory.slice(-20, -10); if (older.length === 0) return 0; const recentAvg = recent.reduce((sum, mem) => sum + mem.usedJSHeapSize, 0) / recent.length; const olderAvg = older.reduce((sum, mem) => sum + mem.usedJSHeapSize, 0) / older.length; return (recentAvg - olderAvg) / olderAvg; } /** * 获取当前内存信息 */ getMemoryInfo() { if ('memory' in performance) { const memory = performance.memory; return { usedJSHeapSize: memory.usedJSHeapSize, jsHeapSizeLimit: memory.jsHeapSizeLimit, totalJSHeapSize: memory.totalJSHeapSize }; } return null; } /** * 获取内存历史记录 */ getMemoryHistory() { return [...this.memoryHistory]; } /** * 清理历史记录 */ clearHistory() { this.memoryHistory = []; } } /** * 数据上报器 */ class PerformanceReporter { constructor(reportUrl, reportInterval = 30000) { this.intervalId = null; this.dataQueue = []; this.reportUrl = reportUrl; this.reportInterval = reportInterval; } /** * 开始定期上报 */ start() { if (this.intervalId) { this.stop(); } this.intervalId = window.setInterval(() => { this.report(); }, this.reportInterval); } /** * 停止定期上报 */ stop() { if (this.intervalId) { clearInterval(this.intervalId); this.intervalId = null; } } /** * 添加数据到队列 */ addData(data) { this.dataQueue.push({ ...data, timestamp: Date.now(), url: window.location.href, userAgent: navigator.userAgent }); } /** * 立即上报数据 */ async report() { if (this.dataQueue.length === 0) return; const dataToReport = [...this.dataQueue]; this.dataQueue = []; if (this.reportUrl) { try { await this.sendData(dataToReport); } catch (error) { console.warn('Performance data report failed:', error); // 失败时重新加入队列 this.dataQueue.unshift(...dataToReport); } } else { // 如果没有配置上报URL,则输出到控制台 console.log('Performance Metrics:', dataToReport); } } /** * 发送数据到服务器 */ async sendData(data) { if (!this.reportUrl) return; const response = await fetch(this.reportUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ timestamp: Date.now(), data: data, sessionId: this.getSessionId() }) }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } } /** * 获取会话ID */ getSessionId() { let sessionId = sessionStorage.getItem('performance_sdk_session_id'); if (!sessionId) { sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; sessionStorage.setItem('performance_sdk_session_id', sessionId); } return sessionId; } /** * 获取队列中的数据数量 */ getQueueSize() { return this.dataQueue.length; } /** * 清空数据队列 */ clearQueue() { this.dataQueue = []; } } /** * 能耗监控器 */ class PowerMonitor { constructor(onPowerChange) { this.batteryManager = null; this.cpuUsageHistory = []; this.maxHistoryLength = 10; this.monitoringInterval = null; this.onPowerChange = onPowerChange; this.initBatteryManager(); } /** * 初始化电池管理器 */ async initBatteryManager() { if ('getBattery' in navigator) { try { this.batteryManager = await navigator.getBattery(); this.setupBatteryListeners(); } catch (error) { console.warn('Battery API not supported:', error); } } } /** * 设置电池状态监听器 */ setupBatteryListeners() { if (!this.batteryManager) return; this.batteryManager.addEventListener('levelchange', () => { this.collectPowerInfo(); }); this.batteryManager.addEventListener('chargingchange', () => { this.collectPowerInfo(); }); this.batteryManager.addEventListener('chargingtimechange', () => { this.collectPowerInfo(); }); this.batteryManager.addEventListener('dischargingtimechange', () => { this.collectPowerInfo(); }); } /** * 开始能耗监控 */ start(intervalMs = 5000) { if (this.monitoringInterval) { this.stop(); } this.monitoringInterval = window.setInterval(() => { this.collectPowerInfo(); }, intervalMs); // 立即收集一次数据 this.collectPowerInfo(); } /** * 停止能耗监控 */ stop() { if (this.monitoringInterval) { clearInterval(this.monitoringInterval); this.monitoringInterval = null; } } /** * 收集能耗信息 */ collectPowerInfo() { var _a; const powerInfo = this.getPowerConsumptionInfo(); (_a = this.onPowerChange) === null || _a === void 0 ? void 0 : _a.call(this, powerInfo); } /** * 获取能耗信息 */ getPowerConsumptionInfo() { const info = { powerLevel: 'medium', powerScore: 50 }; // 获取电池信息 if (this.batteryManager) { info.batteryLevel = this.batteryManager.level; info.charging = this.batteryManager.charging; info.timeToEmpty = this.batteryManager.dischargingTime; info.timeToFull = this.batteryManager.chargingTime; } // 估算CPU使用率 info.cpuUsage = this.estimateCPUUsage(); // 计算能耗等级和评分 const { powerLevel, powerScore } = this.calculatePowerMetrics(info); info.powerLevel = powerLevel; info.powerScore = powerScore; return info; } /** * 估算CPU使用率 */ estimateCPUUsage() { // 基于内存使用率和页面活动来估算CPU使用率 const memory = performance.memory; if (memory) { const memoryUsage = memory.usedJSHeapSize / memory.jsHeapSizeLimit; // 基于内存使用率估算CPU使用率 let cpuUsage = memoryUsage * 100; // 考虑页面活动 const now = performance.now(); const timeSinceLastActivity = now - this.lastActivityTime || 0; if (timeSinceLastActivity < 1000) { cpuUsage += 20; // 最近有活动,增加CPU使用率 } this.lastActivityTime = now; return Math.min(cpuUsage, 100); } return 0; } /** * 计算能耗指标 */ calculatePowerMetrics(info) { let score = 50; // 基础分数 // 基于电池电量调整分数 if (info.batteryLevel !== undefined) { if (info.batteryLevel < 0.2) { score += 30; // 电量低,能耗高 } else if (info.batteryLevel < 0.5) { score += 15; } else { score -= 10; // 电量充足,能耗相对较低 } } // 基于充电状态调整分数 if (info.charging) { score -= 20; // 充电时能耗相对较低 } else { score += 10; // 使用电池时能耗较高 } // 基于CPU使用率调整分数 if (info.cpuUsage !== undefined) { if (info.cpuUsage > 80) { score += 25; // CPU使用率高,能耗高 } else if (info.cpuUsage > 50) { score += 10; } else { score -= 5; // CPU使用率低,能耗低 } } // 确保分数在0-100范围内 score = Math.max(0, Math.min(100, score)); // 确定能耗等级 let powerLevel; if (score < 30) { powerLevel = 'low'; } else if (score < 70) { powerLevel = 'medium'; } else { powerLevel = 'high'; } return { powerLevel, powerScore: score }; } /** * 获取CPU使用率历史 */ getCPUUsageHistory() { return [...this.cpuUsageHistory]; } /** * 清理历史数据 */ clearHistory() { this.cpuUsageHistory = []; } /** * 检查是否支持能耗监控 */ isSupported() { return 'getBattery' in navigator || 'memory' in performance; } } /** * 前端性能监控SDK * 支持监控FCP、LCP、TBT、TTI和内存泄漏 */ class PerformanceSDK { constructor(options = {}) { this.isStarted = false; this.observers = []; this.options = { autoStart: true, enableMemoryMonitoring: true, enableWebVitals: true, enablePowerMonitoring: true, reportInterval: 30000, ...options }; // 初始化内存泄漏检测器 this.memoryLeakDetector = new MemoryLeakDetector((leakInfo) => { console.warn('Memory leak detected:', leakInfo); this.handleMemoryLeak(leakInfo); }); // 初始化数据上报器 this.reporter = new PerformanceReporter(this.options.reportUrl, this.options.reportInterval); // 初始化能耗监控器 this.powerMonitor = new PowerMonitor((powerInfo) => { console.log('Power consumption info:', powerInfo); this.handlePowerChange(powerInfo); }); // 如果配置了自动开始,则启动监控 if (this.options.autoStart) { this.start(); } } /** * 开始性能监控 */ start() { if (this.isStarted) { console.warn('PerformanceSDK is already started'); return; } this.isStarted = true; console.log('PerformanceSDK started'); // 启动数据上报 this.reporter.start(); // 启动内存泄漏检测 if (this.options.enableMemoryMonitoring) { this.memoryLeakDetector.start(); } // 启动能耗监控 if (this.options.enablePowerMonitoring) { this.powerMonitor.start(); } // 设置性能指标监听 if (this.options.enableWebVitals) { this.setupPerformanceObservers(); } // 页面加载完成后获取初始指标 if (document.readyState === 'complete') { this.collectAndReport(); } else { window.addEventListener('load', () => { this.collectAndReport(); }); } } /** * 停止性能监控 */ stop() { if (!this.isStarted) { console.warn('PerformanceSDK is not started'); return; } this.isStarted = false; console.log('PerformanceSDK stopped'); // 停止数据上报 this.reporter.stop(); // 停止内存泄漏检测 this.memoryLeakDetector.stop(); // 停止能耗监控 this.powerMonitor.stop(); // 清理观察器 this.observers.forEach(observer => observer.disconnect()); this.observers = []; } /** * 获取当前性能指标 */ getMetrics() { return getPerformanceMetrics$1(); } /** * 手动收集并上报数据 */ collectAndReport() { const metrics = this.getMetrics(); // 调用自定义数据处理函数 if (this.options.onData) { this.options.onData(metrics); } // 添加到上报队列 this.reporter.addData(metrics); } /** * 设置性能指标观察器 */ setupPerformanceObservers() { if (!('PerformanceObserver' in window)) { console.warn('PerformanceObserver not supported'); return; } try { // 监听LCP const lcpObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); const lastEntry = entries[entries.length - 1]; if (lastEntry) { this.collectAndReport(); } }); lcpObserver.observe({ entryTypes: ['largest-contentful-paint'] }); this.observers.push(lcpObserver); // 监听FCP const fcpObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); if (entries.length > 0) { this.collectAndReport(); } }); fcpObserver.observe({ entryTypes: ['paint'] }); this.observers.push(fcpObserver); // 监听长任务 const longTaskObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); if (entries.length > 0) { this.collectAndReport(); } }); longTaskObserver.observe({ entryTypes: ['longtask'] }); this.observers.push(longTaskObserver); } catch (error) { console.warn('Failed to setup performance observers:', error); } } /** * 处理内存泄漏事件 */ handleMemoryLeak(leakInfo) { const metrics = this.getMetrics(); metrics.memory = leakInfo.current; // 添加内存泄漏标记 const leakData = { ...metrics, memoryLeak: { detected: true, trend: leakInfo.trend, timestamp: Date.now() } }; // 调用自定义数据处理函数 if (this.options.onData) { this.options.onData(leakData); } // 添加到上报队列 this.reporter.addData(leakData); } /** * 处理能耗变化事件 */ handlePowerChange(powerInfo) { const metrics = this.getMetrics(); metrics.powerConsumption = powerInfo; // 调用自定义数据处理函数 if (this.options.onData) { this.options.onData(metrics); } // 添加到上报队列 this.reporter.addData(metrics); } /** * 获取内存历史记录 */ getMemoryHistory() { return this.memoryLeakDetector.getMemoryHistory(); } /** * 获取上报队列大小 */ getQueueSize() { return this.reporter.getQueueSize(); } /** * 立即上报数据 */ async reportNow() { await this.reporter.report(); } /** * 检查是否已启动 */ isRunning() { return this.isStarted; } /** * 销毁SDK实例 */ destroy() { this.stop(); this.memoryLeakDetector.clearHistory(); this.reporter.clearQueue(); } } // 创建全局实例的工厂函数 let globalInstance = null; /** * 初始化性能监控SDK * @param options 配置选项 * @returns SDK实例 */ function initPerformanceSDK(options = {}) { if (globalInstance) { console.warn('PerformanceSDK already initialized'); return globalInstance; } globalInstance = new PerformanceSDK(options); return globalInstance; } /** * 获取全局SDK实例 * @returns SDK实例或null */ function getPerformanceSDK() { return globalInstance; } /** * 销毁全局SDK实例 */ function destroyPerformanceSDK() { if (globalInstance) { globalInstance.destroy(); globalInstance = null; } } /** * 获取当前性能指标 * @returns 性能指标数据 */ function getPerformanceMetrics() { if (globalInstance) { return globalInstance.getMetrics(); } return {}; } /** * 手动收集并上报数据 */ function collectAndReport() { if (globalInstance) { globalInstance.collectAndReport(); } } exports.PerformanceSDK = PerformanceSDK; exports.collectAndReport = collectAndReport; exports.default = PerformanceSDK; exports.destroyPerformanceSDK = destroyPerformanceSDK; exports.getPerformanceMetrics = getPerformanceMetrics; exports.getPerformanceSDK = getPerformanceSDK; exports.initPerformanceSDK = initPerformanceSDK; //# sourceMappingURL=index.js.map