mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-30 18:52:12 +08:00
* fix: improve type safety and remove redundant type casts - Fix @@ts-expect-error typo (double @) in traffic-diagnostics.ts - Replace (e.target as any) with (e.target as HTMLElement) in setting-clash.tsx - Remove redundant (onFormat as any) cast in guard-state.tsx * fix: format api.ts sort callback to satisfy biome * fix: remove as any, let @ts-expect-error suppress the non-standard API error * fix: remove invalid @@ts-expect-error comment, keep as any for non-standard API
181 lines
4.9 KiB
TypeScript
181 lines
4.9 KiB
TypeScript
/**
|
|
* 流量统计诊断工具
|
|
* 用于帮助开发者和用户诊断流量统计系统的性能和状态
|
|
*/
|
|
|
|
interface IDiagnosticReport {
|
|
timestamp: string
|
|
referenceCount: number
|
|
samplerStats: {
|
|
rawBufferSize: number
|
|
compressedBufferSize: number
|
|
compressionQueueSize: number
|
|
totalMemoryPoints: number
|
|
}
|
|
performance: {
|
|
memoryUsage: number // MB
|
|
lastDataFreshness: boolean
|
|
errorCount: number
|
|
}
|
|
recommendations: string[]
|
|
}
|
|
|
|
// 全局错误计数器
|
|
let globalErrorCount = 0
|
|
|
|
/**
|
|
* 记录错误
|
|
*/
|
|
export function recordTrafficError(error: Error, component: string) {
|
|
globalErrorCount++
|
|
console.error(
|
|
`[TrafficDiagnostics] ${component} 错误 (#${globalErrorCount}):`,
|
|
error,
|
|
)
|
|
}
|
|
|
|
/**
|
|
* 获取内存使用情况(近似值)
|
|
*/
|
|
function getMemoryUsage(): number {
|
|
if ('memory' in performance) {
|
|
const memory = (performance as any).memory
|
|
if (memory && memory.usedJSHeapSize) {
|
|
return memory.usedJSHeapSize / 1024 / 1024 // 转换为MB
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
/**
|
|
* 生成诊断报告
|
|
*/
|
|
export function generateDiagnosticReport(
|
|
referenceCount: number,
|
|
samplerStats: any,
|
|
isDataFresh: boolean,
|
|
): IDiagnosticReport {
|
|
const memoryUsage = getMemoryUsage()
|
|
const recommendations: string[] = []
|
|
|
|
// 分析引用计数
|
|
if (referenceCount === 0) {
|
|
recommendations.push('✅ 没有组件在使用流量数据,数据收集已暂停')
|
|
} else if (referenceCount > 3) {
|
|
recommendations.push('⚠️ 有较多组件在使用流量数据,考虑优化组件数量')
|
|
}
|
|
|
|
// 分析内存使用
|
|
const totalPoints = samplerStats.totalMemoryPoints || 0
|
|
if (totalPoints > 1000) {
|
|
recommendations.push('⚠️ 缓存的数据点过多,可能影响性能')
|
|
} else if (totalPoints < 100) {
|
|
recommendations.push('ℹ️ 数据点较少,这是正常情况')
|
|
}
|
|
|
|
// 分析压缩效率
|
|
const compressionRatio =
|
|
samplerStats.rawBufferSize > 0
|
|
? samplerStats.compressedBufferSize / samplerStats.rawBufferSize
|
|
: 0
|
|
if (compressionRatio > 0.5) {
|
|
recommendations.push('⚠️ 数据压缩效率较低,可能需要调整压缩策略')
|
|
} else if (compressionRatio > 0) {
|
|
recommendations.push('✅ 数据压缩效率良好')
|
|
}
|
|
|
|
// 分析数据新鲜度
|
|
if (!isDataFresh) {
|
|
recommendations.push('⚠️ 数据不新鲜,可能存在网络问题或后端异常')
|
|
}
|
|
|
|
// 分析错误频率
|
|
if (globalErrorCount > 10) {
|
|
recommendations.push('🚨 错误频率过高,建议检查网络连接和后端服务')
|
|
} else if (globalErrorCount > 0) {
|
|
recommendations.push('ℹ️ 存在少量错误,这在网络波动时是正常的')
|
|
}
|
|
|
|
// 内存使用建议
|
|
if (memoryUsage > 100) {
|
|
recommendations.push('⚠️ JavaScript堆内存使用较高,可能影响性能')
|
|
}
|
|
|
|
return {
|
|
timestamp: new Date().toISOString(),
|
|
referenceCount,
|
|
samplerStats,
|
|
performance: {
|
|
memoryUsage,
|
|
lastDataFreshness: isDataFresh,
|
|
errorCount: globalErrorCount,
|
|
},
|
|
recommendations,
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 格式化诊断报告为可读字符串
|
|
*/
|
|
export function formatDiagnosticReport(report: IDiagnosticReport): string {
|
|
return `
|
|
🔍 流量统计系统诊断报告
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
📊 基本信息:
|
|
• 生成时间: ${report.timestamp}
|
|
• 活跃引用: ${report.referenceCount} 个组件
|
|
• 数据新鲜度: ${report.performance.lastDataFreshness ? '✅ 新鲜' : '❌ 过期'}
|
|
|
|
💾 数据缓存状态:
|
|
• 原始数据点: ${report.samplerStats.rawBufferSize}
|
|
• 压缩数据点: ${report.samplerStats.compressedBufferSize}
|
|
• 压缩队列: ${report.samplerStats.compressionQueueSize}
|
|
• 总内存点数: ${report.samplerStats.totalMemoryPoints}
|
|
|
|
⚡ 性能指标:
|
|
• JS堆内存: ${report.performance.memoryUsage.toFixed(2)} MB
|
|
• 累计错误: ${report.performance.errorCount} 次
|
|
|
|
💡 优化建议:
|
|
${report.recommendations.map((rec) => ` ${rec}`).join('\n')}
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
`.trim()
|
|
}
|
|
|
|
/**
|
|
* 自动诊断并打印报告
|
|
*/
|
|
export function runTrafficDiagnostics(
|
|
referenceCount: number,
|
|
samplerStats: any,
|
|
isDataFresh: boolean,
|
|
): void {
|
|
const report = generateDiagnosticReport(
|
|
referenceCount,
|
|
samplerStats,
|
|
isDataFresh,
|
|
)
|
|
console.log(formatDiagnosticReport(report))
|
|
}
|
|
|
|
/**
|
|
* 重置错误计数器
|
|
*/
|
|
export function resetErrorCount(): void {
|
|
globalErrorCount = 0
|
|
console.log('[TrafficDiagnostics] 错误计数器已重置')
|
|
}
|
|
|
|
// 导出到全局对象,方便在控制台调试
|
|
if (typeof window !== 'undefined') {
|
|
;(window as any).trafficDiagnostics = {
|
|
generateDiagnosticReport,
|
|
formatDiagnosticReport,
|
|
runTrafficDiagnostics,
|
|
resetErrorCount,
|
|
recordTrafficError,
|
|
}
|
|
}
|