Initial Commit
This commit is contained in:
commit
1d71a02738
237 changed files with 64293 additions and 0 deletions
768
utils/performance-monitor.js
Normal file
768
utils/performance-monitor.js
Normal file
|
|
@ -0,0 +1,768 @@
|
|||
// 性能监控管理器 - 微信小程序专用
|
||||
// 监控应用性能、内存使用、网络请求等关键指标
|
||||
|
||||
/**
|
||||
* 性能监控管理器
|
||||
* 功能:
|
||||
* 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;
|
||||
Loading…
Add table
Add a link
Reference in a new issue