768 lines
22 KiB
JavaScript
768 lines
22 KiB
JavaScript
// 性能监控管理器 - 微信小程序专用
|
||
// 监控应用性能、内存使用、网络请求等关键指标
|
||
|
||
/**
|
||
* 性能监控管理器
|
||
* 功能:
|
||
* 1. 页面性能监控
|
||
* 2. 内存使用监控
|
||
* 3. 网络请求监控
|
||
* 4. 错误监控和上报
|
||
* 5. 性能数据分析
|
||
* 6. 性能优化建议
|
||
*/
|
||
class PerformanceMonitor {
|
||
constructor() {
|
||
this.isInitialized = false;
|
||
|
||
// 性能配置
|
||
this.config = {
|
||
// 监控开关
|
||
enabled: true,
|
||
|
||
// 采样率 (0-1)
|
||
sampleRate: 0.1,
|
||
|
||
// 性能阈值
|
||
thresholds: {
|
||
pageLoadTime: 3000, // 页面加载时间阈值 (ms)
|
||
apiResponseTime: 5000, // API响应时间阈值 (ms)
|
||
memoryUsage: 100, // 内存使用阈值 (MB)
|
||
errorRate: 0.05, // 错误率阈值 (5%)
|
||
crashRate: 0.01 // 崩溃率阈值 (1%)
|
||
},
|
||
|
||
// 上报配置
|
||
reporting: {
|
||
enabled: true,
|
||
endpoint: '/api/v1/performance/report',
|
||
batchSize: 10,
|
||
interval: 30000 // 30秒上报一次
|
||
}
|
||
};
|
||
|
||
// 性能数据
|
||
this.performanceData = {
|
||
pageMetrics: new Map(), // 页面性能指标
|
||
apiMetrics: new Map(), // API性能指标
|
||
errorMetrics: new Map(), // 错误指标
|
||
memoryMetrics: [], // 内存使用指标
|
||
userMetrics: new Map() // 用户行为指标
|
||
};
|
||
|
||
// 监控状态
|
||
this.monitoringState = {
|
||
startTime: Date.now(),
|
||
sessionId: this.generateSessionId(),
|
||
userId: null,
|
||
deviceInfo: null,
|
||
networkType: 'unknown'
|
||
};
|
||
|
||
// 待上报数据
|
||
this.pendingReports = [];
|
||
|
||
// 定时器
|
||
this.reportTimer = null;
|
||
this.memoryTimer = null;
|
||
|
||
this.init();
|
||
}
|
||
|
||
// 初始化性能监控
|
||
async init() {
|
||
if (this.isInitialized || !this.config.enabled) return;
|
||
|
||
console.log('⚡ 初始化性能监控...');
|
||
|
||
try {
|
||
// 获取设备信息
|
||
await this.getDeviceInfo();
|
||
|
||
// 获取网络类型
|
||
await this.getNetworkType();
|
||
|
||
// 获取用户ID
|
||
this.monitoringState.userId = wx.getStorageSync('userId') || 'anonymous';
|
||
|
||
// 启动内存监控
|
||
this.startMemoryMonitoring();
|
||
|
||
// 启动上报定时器
|
||
this.startReportTimer();
|
||
|
||
// 监听应用生命周期
|
||
this.setupAppLifecycleListeners();
|
||
|
||
// 监听网络状态变化
|
||
this.setupNetworkListeners();
|
||
|
||
this.isInitialized = true;
|
||
console.log('✅ 性能监控初始化完成');
|
||
|
||
} catch (error) {
|
||
console.error('❌ 性能监控初始化失败:', error);
|
||
}
|
||
}
|
||
|
||
// ⚡ ===== 页面性能监控 =====
|
||
|
||
// 开始页面性能监控
|
||
startPageMonitoring(pagePath) {
|
||
if (!this.config.enabled) return;
|
||
|
||
const pageId = this.generatePageId(pagePath);
|
||
const startTime = Date.now();
|
||
|
||
this.performanceData.pageMetrics.set(pageId, {
|
||
pagePath: pagePath,
|
||
startTime: startTime,
|
||
loadTime: null,
|
||
renderTime: null,
|
||
interactiveTime: null,
|
||
memoryUsage: null,
|
||
errors: [],
|
||
userActions: []
|
||
});
|
||
|
||
console.log('⚡ 开始页面性能监控:', pagePath);
|
||
|
||
return pageId;
|
||
}
|
||
|
||
// 结束页面性能监控
|
||
endPageMonitoring(pageId, metrics = {}) {
|
||
if (!this.config.enabled || !this.performanceData.pageMetrics.has(pageId)) return;
|
||
|
||
const pageMetric = this.performanceData.pageMetrics.get(pageId);
|
||
const endTime = Date.now();
|
||
|
||
// 更新性能指标
|
||
pageMetric.loadTime = endTime - pageMetric.startTime;
|
||
pageMetric.renderTime = metrics.renderTime || null;
|
||
pageMetric.interactiveTime = metrics.interactiveTime || null;
|
||
pageMetric.memoryUsage = this.getCurrentMemoryUsage();
|
||
|
||
// 检查性能阈值
|
||
this.checkPagePerformance(pageMetric);
|
||
|
||
// 添加到待上报数据
|
||
this.addToReport('page_performance', pageMetric);
|
||
|
||
console.log('⚡ 页面性能监控结束:', pageMetric.pagePath, `${pageMetric.loadTime}ms`);
|
||
}
|
||
|
||
// 记录用户操作
|
||
recordUserAction(pageId, action, data = {}) {
|
||
if (!this.config.enabled || !this.performanceData.pageMetrics.has(pageId)) return;
|
||
|
||
const pageMetric = this.performanceData.pageMetrics.get(pageId);
|
||
pageMetric.userActions.push({
|
||
action: action,
|
||
timestamp: Date.now(),
|
||
data: data
|
||
});
|
||
}
|
||
|
||
// 🌐 ===== API性能监控 =====
|
||
|
||
// 开始API请求监控
|
||
startApiMonitoring(url, method = 'GET') {
|
||
if (!this.config.enabled) return null;
|
||
|
||
const requestId = this.generateRequestId();
|
||
const startTime = Date.now();
|
||
|
||
this.performanceData.apiMetrics.set(requestId, {
|
||
url: url,
|
||
method: method,
|
||
startTime: startTime,
|
||
endTime: null,
|
||
responseTime: null,
|
||
statusCode: null,
|
||
success: null,
|
||
errorMessage: null,
|
||
requestSize: null,
|
||
responseSize: null
|
||
});
|
||
|
||
return requestId;
|
||
}
|
||
|
||
// 结束API请求监控
|
||
endApiMonitoring(requestId, result = {}) {
|
||
if (!this.config.enabled || !this.performanceData.apiMetrics.has(requestId)) return;
|
||
|
||
const apiMetric = this.performanceData.apiMetrics.get(requestId);
|
||
const endTime = Date.now();
|
||
|
||
// 更新API指标
|
||
apiMetric.endTime = endTime;
|
||
apiMetric.responseTime = endTime - apiMetric.startTime;
|
||
apiMetric.statusCode = result.statusCode || null;
|
||
apiMetric.success = result.success || false;
|
||
apiMetric.errorMessage = result.errorMessage || null;
|
||
apiMetric.requestSize = result.requestSize || null;
|
||
apiMetric.responseSize = result.responseSize || null;
|
||
|
||
// 检查API性能
|
||
this.checkApiPerformance(apiMetric);
|
||
|
||
// 添加到待上报数据
|
||
this.addToReport('api_performance', apiMetric);
|
||
|
||
console.log('⚡ API性能监控:', apiMetric.url, `${apiMetric.responseTime}ms`);
|
||
}
|
||
|
||
// 📊 ===== 内存监控 =====
|
||
|
||
// 启动内存监控
|
||
startMemoryMonitoring() {
|
||
if (!this.config.enabled) return;
|
||
|
||
this.memoryTimer = setInterval(() => {
|
||
this.collectMemoryMetrics();
|
||
}, 10000); // 每10秒收集一次内存数据
|
||
}
|
||
|
||
// 收集内存指标
|
||
collectMemoryMetrics() {
|
||
try {
|
||
// 使用新的API替代已弃用的wx.getSystemInfoSync
|
||
const deviceInfo = wx.getDeviceInfo();
|
||
const memoryInfo = { system: deviceInfo.memorySize || 'unknown' };
|
||
const currentMemory = this.getCurrentMemoryUsage();
|
||
|
||
const memoryMetric = {
|
||
timestamp: Date.now(),
|
||
totalMemory: memoryInfo.system || 'unknown',
|
||
usedMemory: currentMemory,
|
||
availableMemory: memoryInfo.system ? (memoryInfo.system - currentMemory) : 'unknown',
|
||
memoryWarning: currentMemory > this.config.thresholds.memoryUsage
|
||
};
|
||
|
||
this.performanceData.memoryMetrics.push(memoryMetric);
|
||
|
||
// 保持最近100条记录
|
||
if (this.performanceData.memoryMetrics.length > 100) {
|
||
this.performanceData.memoryMetrics.shift();
|
||
}
|
||
|
||
// 检查内存使用
|
||
if (memoryMetric.memoryWarning) {
|
||
this.handleMemoryWarning(memoryMetric);
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('❌ 收集内存指标失败:', error);
|
||
}
|
||
}
|
||
|
||
// 获取当前内存使用
|
||
getCurrentMemoryUsage() {
|
||
try {
|
||
// 微信小程序没有直接的内存API,使用估算方法
|
||
const pages = getCurrentPages();
|
||
const cacheSize = this.estimateCacheSize();
|
||
|
||
// 估算内存使用 (页面数 * 5MB + 缓存大小)
|
||
return pages.length * 5 + cacheSize;
|
||
} catch (error) {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
// 估算缓存大小
|
||
estimateCacheSize() {
|
||
try {
|
||
const storageInfo = wx.getStorageInfoSync();
|
||
return Math.round(storageInfo.currentSize / 1024); // 转换为MB
|
||
} catch (error) {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
// 🚨 ===== 错误监控 =====
|
||
|
||
// 记录错误
|
||
recordError(error, context = {}) {
|
||
if (!this.config.enabled) return;
|
||
|
||
const errorId = this.generateErrorId();
|
||
const errorMetric = {
|
||
errorId: errorId,
|
||
timestamp: Date.now(),
|
||
message: error.message || error.toString(),
|
||
stack: error.stack || null,
|
||
type: error.name || 'UnknownError',
|
||
context: context,
|
||
userId: this.monitoringState.userId,
|
||
sessionId: this.monitoringState.sessionId,
|
||
pagePath: this.getCurrentPagePath(),
|
||
deviceInfo: this.monitoringState.deviceInfo,
|
||
networkType: this.monitoringState.networkType
|
||
};
|
||
|
||
this.performanceData.errorMetrics.set(errorId, errorMetric);
|
||
|
||
// 添加到待上报数据
|
||
this.addToReport('error', errorMetric);
|
||
|
||
console.error('🚨 错误记录:', errorMetric);
|
||
}
|
||
|
||
// 记录崩溃
|
||
recordCrash(crashInfo) {
|
||
if (!this.config.enabled) return;
|
||
|
||
const crashMetric = {
|
||
timestamp: Date.now(),
|
||
crashInfo: crashInfo,
|
||
userId: this.monitoringState.userId,
|
||
sessionId: this.monitoringState.sessionId,
|
||
deviceInfo: this.monitoringState.deviceInfo,
|
||
memoryUsage: this.getCurrentMemoryUsage(),
|
||
recentErrors: Array.from(this.performanceData.errorMetrics.values()).slice(-5)
|
||
};
|
||
|
||
// 立即上报崩溃数据
|
||
this.reportImmediately('crash', crashMetric);
|
||
|
||
console.error('💥 崩溃记录:', crashMetric);
|
||
}
|
||
|
||
// 📈 ===== 性能分析 =====
|
||
|
||
// 检查页面性能
|
||
checkPagePerformance(pageMetric) {
|
||
const warnings = [];
|
||
|
||
if (pageMetric.loadTime > this.config.thresholds.pageLoadTime) {
|
||
warnings.push(`页面加载时间过长: ${pageMetric.loadTime}ms`);
|
||
}
|
||
|
||
if (pageMetric.memoryUsage > this.config.thresholds.memoryUsage) {
|
||
warnings.push(`内存使用过高: ${pageMetric.memoryUsage}MB`);
|
||
}
|
||
|
||
if (warnings.length > 0) {
|
||
console.warn('⚠️ 页面性能警告:', pageMetric.pagePath, warnings);
|
||
this.addToReport('performance_warning', {
|
||
type: 'page',
|
||
pagePath: pageMetric.pagePath,
|
||
warnings: warnings,
|
||
metrics: pageMetric
|
||
});
|
||
}
|
||
}
|
||
|
||
// 检查API性能
|
||
checkApiPerformance(apiMetric) {
|
||
const warnings = [];
|
||
|
||
if (apiMetric.responseTime > this.config.thresholds.apiResponseTime) {
|
||
warnings.push(`API响应时间过长: ${apiMetric.responseTime}ms`);
|
||
}
|
||
|
||
if (!apiMetric.success) {
|
||
warnings.push(`API请求失败: ${apiMetric.errorMessage}`);
|
||
}
|
||
|
||
if (warnings.length > 0) {
|
||
console.warn('⚠️ API性能警告:', apiMetric.url, warnings);
|
||
this.addToReport('performance_warning', {
|
||
type: 'api',
|
||
url: apiMetric.url,
|
||
warnings: warnings,
|
||
metrics: apiMetric
|
||
});
|
||
}
|
||
}
|
||
|
||
// 处理内存警告
|
||
handleMemoryWarning(memoryMetric) {
|
||
console.warn('⚠️ 内存使用警告:', memoryMetric);
|
||
|
||
// 触发内存清理
|
||
this.triggerMemoryCleanup();
|
||
|
||
// 上报内存警告
|
||
this.addToReport('memory_warning', memoryMetric);
|
||
}
|
||
|
||
// 触发内存清理
|
||
triggerMemoryCleanup() {
|
||
try {
|
||
// 清理过期缓存
|
||
this.cleanupExpiredCache();
|
||
|
||
// 清理性能数据
|
||
this.cleanupPerformanceData();
|
||
|
||
// 通知应用进行内存清理
|
||
wx.triggerGC && wx.triggerGC();
|
||
|
||
console.log('🧹 内存清理完成');
|
||
} catch (error) {
|
||
console.error('❌ 内存清理失败:', error);
|
||
}
|
||
}
|
||
|
||
// 🔧 ===== 工具方法 =====
|
||
|
||
// 生成会话ID
|
||
generateSessionId() {
|
||
return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||
}
|
||
|
||
// 生成页面ID
|
||
generatePageId(pagePath) {
|
||
return `page_${pagePath.replace(/\//g, '_')}_${Date.now()}`;
|
||
}
|
||
|
||
// 生成请求ID
|
||
generateRequestId() {
|
||
return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||
}
|
||
|
||
// 生成错误ID
|
||
generateErrorId() {
|
||
return `err_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||
}
|
||
|
||
// 获取当前页面路径
|
||
getCurrentPagePath() {
|
||
try {
|
||
const pages = getCurrentPages();
|
||
const currentPage = pages[pages.length - 1];
|
||
return currentPage ? currentPage.route : 'unknown';
|
||
} catch (error) {
|
||
return 'unknown';
|
||
}
|
||
}
|
||
|
||
// 获取设备信息
|
||
async getDeviceInfo() {
|
||
try {
|
||
// 使用新的API替代已弃用的wx.getSystemInfoSync
|
||
const deviceInfo = wx.getDeviceInfo();
|
||
const windowInfo = wx.getWindowInfo();
|
||
const appBaseInfo = wx.getAppBaseInfo();
|
||
|
||
this.monitoringState.deviceInfo = {
|
||
brand: deviceInfo.brand,
|
||
model: deviceInfo.model,
|
||
system: deviceInfo.system,
|
||
platform: deviceInfo.platform,
|
||
version: appBaseInfo.version,
|
||
SDKVersion: appBaseInfo.SDKVersion,
|
||
screenWidth: windowInfo.screenWidth,
|
||
screenHeight: windowInfo.screenHeight,
|
||
pixelRatio: windowInfo.pixelRatio
|
||
};
|
||
} catch (error) {
|
||
console.error('❌ 获取设备信息失败,使用兜底方案:', error);
|
||
// 兜底方案
|
||
try {
|
||
const systemInfo = wx.getSystemInfoSync();
|
||
this.monitoringState.deviceInfo = {
|
||
brand: systemInfo.brand,
|
||
model: systemInfo.model,
|
||
system: systemInfo.system,
|
||
platform: systemInfo.platform,
|
||
version: systemInfo.version,
|
||
SDKVersion: systemInfo.SDKVersion,
|
||
screenWidth: systemInfo.screenWidth,
|
||
screenHeight: systemInfo.screenHeight,
|
||
pixelRatio: systemInfo.pixelRatio
|
||
};
|
||
} catch (fallbackError) {
|
||
console.error('❌ 兜底方案也失败了:', fallbackError);
|
||
this.monitoringState.deviceInfo = {
|
||
brand: 'unknown',
|
||
model: 'unknown',
|
||
system: 'unknown',
|
||
platform: 'unknown',
|
||
version: 'unknown',
|
||
SDKVersion: 'unknown',
|
||
screenWidth: 375,
|
||
screenHeight: 667,
|
||
pixelRatio: 2
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取网络类型
|
||
async getNetworkType() {
|
||
try {
|
||
const networkInfo = await new Promise((resolve, reject) => {
|
||
wx.getNetworkType({
|
||
success: resolve,
|
||
fail: reject
|
||
});
|
||
});
|
||
|
||
this.monitoringState.networkType = networkInfo.networkType;
|
||
} catch (error) {
|
||
console.error('❌ 获取网络类型失败:', error);
|
||
}
|
||
}
|
||
|
||
// 设置应用生命周期监听
|
||
setupAppLifecycleListeners() {
|
||
// 监听应用隐藏
|
||
wx.onAppHide(() => {
|
||
this.addToReport('app_lifecycle', {
|
||
event: 'hide',
|
||
timestamp: Date.now(),
|
||
sessionDuration: Date.now() - this.monitoringState.startTime
|
||
});
|
||
});
|
||
|
||
// 监听应用显示
|
||
wx.onAppShow(() => {
|
||
this.addToReport('app_lifecycle', {
|
||
event: 'show',
|
||
timestamp: Date.now()
|
||
});
|
||
});
|
||
}
|
||
|
||
// 设置网络状态监听
|
||
setupNetworkListeners() {
|
||
wx.onNetworkStatusChange((res) => {
|
||
this.monitoringState.networkType = res.networkType;
|
||
|
||
this.addToReport('network_change', {
|
||
networkType: res.networkType,
|
||
isConnected: res.isConnected,
|
||
timestamp: Date.now()
|
||
});
|
||
});
|
||
}
|
||
|
||
// 添加到上报队列
|
||
addToReport(type, data) {
|
||
if (!this.config.reporting.enabled) return;
|
||
|
||
// 采样控制
|
||
if (Math.random() > this.config.sampleRate) return;
|
||
|
||
this.pendingReports.push({
|
||
type: type,
|
||
data: data,
|
||
timestamp: Date.now(),
|
||
sessionId: this.monitoringState.sessionId,
|
||
userId: this.monitoringState.userId
|
||
});
|
||
|
||
// 检查是否需要立即上报
|
||
if (this.pendingReports.length >= this.config.reporting.batchSize) {
|
||
this.reportData();
|
||
}
|
||
}
|
||
|
||
// 立即上报
|
||
async reportImmediately(type, data) {
|
||
if (!this.config.reporting.enabled) return;
|
||
|
||
try {
|
||
const reportData = {
|
||
type: type,
|
||
data: data,
|
||
timestamp: Date.now(),
|
||
sessionId: this.monitoringState.sessionId,
|
||
userId: this.monitoringState.userId,
|
||
deviceInfo: this.monitoringState.deviceInfo
|
||
};
|
||
|
||
// 这里应该调用实际的上报API
|
||
console.log('📊 立即上报性能数据:', reportData);
|
||
|
||
} catch (error) {
|
||
console.error('❌ 立即上报失败:', error);
|
||
}
|
||
}
|
||
|
||
// 启动上报定时器
|
||
startReportTimer() {
|
||
if (!this.config.reporting.enabled) return;
|
||
|
||
this.reportTimer = setInterval(() => {
|
||
if (this.pendingReports.length > 0) {
|
||
this.reportData();
|
||
}
|
||
}, this.config.reporting.interval);
|
||
}
|
||
|
||
// 上报数据
|
||
async reportData() {
|
||
if (!this.config.reporting.enabled || this.pendingReports.length === 0) return;
|
||
|
||
try {
|
||
const reports = this.pendingReports.splice(0, this.config.reporting.batchSize);
|
||
|
||
// 这里应该调用实际的上报API
|
||
console.log('📊 批量上报性能数据:', reports.length, '条');
|
||
|
||
// 模拟API调用
|
||
// await apiClient.request({
|
||
// url: this.config.reporting.endpoint,
|
||
// method: 'POST',
|
||
// data: {
|
||
// reports: reports,
|
||
// deviceInfo: this.monitoringState.deviceInfo,
|
||
// sessionInfo: {
|
||
// sessionId: this.monitoringState.sessionId,
|
||
// startTime: this.monitoringState.startTime,
|
||
// userId: this.monitoringState.userId
|
||
// }
|
||
// }
|
||
// });
|
||
|
||
} catch (error) {
|
||
console.error('❌ 上报性能数据失败:', error);
|
||
|
||
// 上报失败,将数据重新加入队列
|
||
// this.pendingReports.unshift(...reports);
|
||
}
|
||
}
|
||
|
||
// 清理过期缓存
|
||
cleanupExpiredCache() {
|
||
try {
|
||
// 清理过期的性能数据
|
||
const now = Date.now();
|
||
const expireTime = 24 * 60 * 60 * 1000; // 24小时
|
||
|
||
// 清理页面指标
|
||
for (const [key, value] of this.performanceData.pageMetrics) {
|
||
if (now - value.startTime > expireTime) {
|
||
this.performanceData.pageMetrics.delete(key);
|
||
}
|
||
}
|
||
|
||
// 清理API指标
|
||
for (const [key, value] of this.performanceData.apiMetrics) {
|
||
if (now - value.startTime > expireTime) {
|
||
this.performanceData.apiMetrics.delete(key);
|
||
}
|
||
}
|
||
|
||
// 清理错误指标
|
||
for (const [key, value] of this.performanceData.errorMetrics) {
|
||
if (now - value.timestamp > expireTime) {
|
||
this.performanceData.errorMetrics.delete(key);
|
||
}
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('❌ 清理过期缓存失败:', error);
|
||
}
|
||
}
|
||
|
||
// 清理性能数据
|
||
cleanupPerformanceData() {
|
||
try {
|
||
// 保留最近的数据
|
||
const maxPageMetrics = 50;
|
||
const maxApiMetrics = 100;
|
||
const maxErrorMetrics = 50;
|
||
|
||
// 清理页面指标
|
||
if (this.performanceData.pageMetrics.size > maxPageMetrics) {
|
||
const entries = Array.from(this.performanceData.pageMetrics.entries());
|
||
entries.sort((a, b) => b[1].startTime - a[1].startTime);
|
||
|
||
this.performanceData.pageMetrics.clear();
|
||
entries.slice(0, maxPageMetrics).forEach(([key, value]) => {
|
||
this.performanceData.pageMetrics.set(key, value);
|
||
});
|
||
}
|
||
|
||
// 清理API指标
|
||
if (this.performanceData.apiMetrics.size > maxApiMetrics) {
|
||
const entries = Array.from(this.performanceData.apiMetrics.entries());
|
||
entries.sort((a, b) => b[1].startTime - a[1].startTime);
|
||
|
||
this.performanceData.apiMetrics.clear();
|
||
entries.slice(0, maxApiMetrics).forEach(([key, value]) => {
|
||
this.performanceData.apiMetrics.set(key, value);
|
||
});
|
||
}
|
||
|
||
// 清理错误指标
|
||
if (this.performanceData.errorMetrics.size > maxErrorMetrics) {
|
||
const entries = Array.from(this.performanceData.errorMetrics.entries());
|
||
entries.sort((a, b) => b[1].timestamp - a[1].timestamp);
|
||
|
||
this.performanceData.errorMetrics.clear();
|
||
entries.slice(0, maxErrorMetrics).forEach(([key, value]) => {
|
||
this.performanceData.errorMetrics.set(key, value);
|
||
});
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('❌ 清理性能数据失败:', error);
|
||
}
|
||
}
|
||
|
||
// 获取性能报告
|
||
getPerformanceReport() {
|
||
return {
|
||
sessionInfo: this.monitoringState,
|
||
pageMetrics: Array.from(this.performanceData.pageMetrics.values()),
|
||
apiMetrics: Array.from(this.performanceData.apiMetrics.values()),
|
||
errorMetrics: Array.from(this.performanceData.errorMetrics.values()),
|
||
memoryMetrics: this.performanceData.memoryMetrics,
|
||
summary: this.generatePerformanceSummary()
|
||
};
|
||
}
|
||
|
||
// 生成性能摘要
|
||
generatePerformanceSummary() {
|
||
const pageMetrics = Array.from(this.performanceData.pageMetrics.values());
|
||
const apiMetrics = Array.from(this.performanceData.apiMetrics.values());
|
||
const errorMetrics = Array.from(this.performanceData.errorMetrics.values());
|
||
|
||
return {
|
||
totalPages: pageMetrics.length,
|
||
averagePageLoadTime: pageMetrics.length > 0 ?
|
||
pageMetrics.reduce((sum, m) => sum + (m.loadTime || 0), 0) / pageMetrics.length : 0,
|
||
totalApiRequests: apiMetrics.length,
|
||
averageApiResponseTime: apiMetrics.length > 0 ?
|
||
apiMetrics.reduce((sum, m) => sum + (m.responseTime || 0), 0) / apiMetrics.length : 0,
|
||
totalErrors: errorMetrics.length,
|
||
errorRate: pageMetrics.length > 0 ? errorMetrics.length / pageMetrics.length : 0,
|
||
currentMemoryUsage: this.getCurrentMemoryUsage(),
|
||
sessionDuration: Date.now() - this.monitoringState.startTime
|
||
};
|
||
}
|
||
|
||
// 销毁监控器
|
||
destroy() {
|
||
if (this.reportTimer) {
|
||
clearInterval(this.reportTimer);
|
||
this.reportTimer = null;
|
||
}
|
||
|
||
if (this.memoryTimer) {
|
||
clearInterval(this.memoryTimer);
|
||
this.memoryTimer = null;
|
||
}
|
||
|
||
// 最后一次上报
|
||
if (this.pendingReports.length > 0) {
|
||
this.reportData();
|
||
}
|
||
|
||
this.isInitialized = false;
|
||
console.log('⚡ 性能监控器已销毁');
|
||
}
|
||
}
|
||
|
||
// 创建全局实例
|
||
const performanceMonitor = new PerformanceMonitor();
|
||
|
||
module.exports = performanceMonitor;
|