mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-15 05:40:47 +08:00
refactor(frontend): remove obsolete monitor diagnostics
This commit is contained in:
Vendored
-39
@@ -162,45 +162,6 @@ interface IFormattedMemoryData {
|
|||||||
is_fresh: boolean
|
is_fresh: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
// 增强的类型安全接口定义,确保所有字段必需
|
|
||||||
interface ISystemMonitorOverview {
|
|
||||||
traffic: {
|
|
||||||
raw: {
|
|
||||||
up: number
|
|
||||||
down: number
|
|
||||||
up_rate: number
|
|
||||||
down_rate: number
|
|
||||||
}
|
|
||||||
formatted: {
|
|
||||||
up_rate: string
|
|
||||||
down_rate: string
|
|
||||||
total_up: string
|
|
||||||
total_down: string
|
|
||||||
}
|
|
||||||
is_fresh: boolean
|
|
||||||
}
|
|
||||||
memory: {
|
|
||||||
raw: {
|
|
||||||
inuse: number
|
|
||||||
oslimit: number
|
|
||||||
usage_percent: number
|
|
||||||
}
|
|
||||||
formatted: {
|
|
||||||
inuse: string
|
|
||||||
oslimit: string
|
|
||||||
usage_percent: number
|
|
||||||
}
|
|
||||||
is_fresh: boolean
|
|
||||||
}
|
|
||||||
overall_status: 'active' | 'inactive' | 'error' | 'unknown' | 'healthy'
|
|
||||||
}
|
|
||||||
|
|
||||||
// 类型安全的数据验证器
|
|
||||||
interface ISystemMonitorOverviewValidator {
|
|
||||||
validate(data: any): data is ISystemMonitorOverview
|
|
||||||
sanitize(data: any): ISystemMonitorOverview
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ILogItem {
|
interface ILogItem {
|
||||||
type: string
|
type: string
|
||||||
time?: string
|
time?: string
|
||||||
|
|||||||
@@ -1,230 +0,0 @@
|
|||||||
/**
|
|
||||||
* 类型安全的数据验证器
|
|
||||||
* 确保从后端接收的数据符合预期的接口定义
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 数字验证器
|
|
||||||
function isValidNumber(value: any): value is number {
|
|
||||||
return typeof value === 'number' && !isNaN(value) && isFinite(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字符串验证器
|
|
||||||
function isValidString(value: any): value is string {
|
|
||||||
return typeof value === 'string' && value.length > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// 布尔值验证器
|
|
||||||
function isValidBoolean(value: any): value is boolean {
|
|
||||||
return typeof value === 'boolean'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 系统监控数据验证器
|
|
||||||
*/
|
|
||||||
export class SystemMonitorValidator implements ISystemMonitorOverviewValidator {
|
|
||||||
/**
|
|
||||||
* 验证数据是否符合ISystemMonitorOverview接口
|
|
||||||
*/
|
|
||||||
validate(data: any): data is ISystemMonitorOverview {
|
|
||||||
if (!data || typeof data !== 'object') {
|
|
||||||
console.warn('[DataValidator] 数据不是对象:', data)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证traffic字段
|
|
||||||
if (!this.validateTrafficData(data.traffic)) {
|
|
||||||
console.warn('[DataValidator] traffic字段验证失败:', data.traffic)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证memory字段
|
|
||||||
if (!this.validateMemoryData(data.memory)) {
|
|
||||||
console.warn('[DataValidator] memory字段验证失败:', data.memory)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证overall_status字段
|
|
||||||
if (!this.validateOverallStatus(data.overall_status)) {
|
|
||||||
console.warn(
|
|
||||||
'[DataValidator] overall_status字段验证失败:',
|
|
||||||
data.overall_status,
|
|
||||||
)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清理和修复数据,确保返回有效的ISystemMonitorOverview
|
|
||||||
*/
|
|
||||||
sanitize(data: any): ISystemMonitorOverview {
|
|
||||||
// debugLog("[DataValidator] 开始数据清理:", data);
|
|
||||||
|
|
||||||
const sanitized: ISystemMonitorOverview = {
|
|
||||||
traffic: this.sanitizeTrafficData(data?.traffic),
|
|
||||||
memory: this.sanitizeMemoryData(data?.memory),
|
|
||||||
overall_status: this.sanitizeOverallStatus(data?.overall_status),
|
|
||||||
}
|
|
||||||
|
|
||||||
// debugLog("[DataValidator] 数据清理完成:", sanitized);
|
|
||||||
return sanitized
|
|
||||||
}
|
|
||||||
|
|
||||||
private validateTrafficData(traffic: any): boolean {
|
|
||||||
if (!traffic || typeof traffic !== 'object') return false
|
|
||||||
|
|
||||||
// 验证raw字段
|
|
||||||
const raw = traffic.raw
|
|
||||||
if (!raw || typeof raw !== 'object') return false
|
|
||||||
if (
|
|
||||||
!isValidNumber(raw.up) ||
|
|
||||||
!isValidNumber(raw.down) ||
|
|
||||||
!isValidNumber(raw.up_rate) ||
|
|
||||||
!isValidNumber(raw.down_rate)
|
|
||||||
) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证formatted字段
|
|
||||||
const formatted = traffic.formatted
|
|
||||||
if (!formatted || typeof formatted !== 'object') return false
|
|
||||||
if (
|
|
||||||
!isValidString(formatted.up_rate) ||
|
|
||||||
!isValidString(formatted.down_rate) ||
|
|
||||||
!isValidString(formatted.total_up) ||
|
|
||||||
!isValidString(formatted.total_down)
|
|
||||||
) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证is_fresh字段
|
|
||||||
if (!isValidBoolean(traffic.is_fresh)) return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private validateMemoryData(memory: any): boolean {
|
|
||||||
if (!memory || typeof memory !== 'object') return false
|
|
||||||
|
|
||||||
// 验证raw字段
|
|
||||||
const raw = memory.raw
|
|
||||||
if (!raw || typeof raw !== 'object') return false
|
|
||||||
if (
|
|
||||||
!isValidNumber(raw.inuse) ||
|
|
||||||
!isValidNumber(raw.oslimit) ||
|
|
||||||
!isValidNumber(raw.usage_percent)
|
|
||||||
) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证formatted字段
|
|
||||||
const formatted = memory.formatted
|
|
||||||
if (!formatted || typeof formatted !== 'object') return false
|
|
||||||
if (
|
|
||||||
!isValidString(formatted.inuse) ||
|
|
||||||
!isValidString(formatted.oslimit) ||
|
|
||||||
!isValidNumber(formatted.usage_percent)
|
|
||||||
) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证is_fresh字段
|
|
||||||
if (!isValidBoolean(memory.is_fresh)) return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private validateOverallStatus(status: any): boolean {
|
|
||||||
return (
|
|
||||||
typeof status === 'string' &&
|
|
||||||
['active', 'inactive', 'error', 'unknown', 'healthy'].includes(status)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private sanitizeTrafficData(traffic: any) {
|
|
||||||
const raw = traffic?.raw || {}
|
|
||||||
const formatted = traffic?.formatted || {}
|
|
||||||
|
|
||||||
return {
|
|
||||||
raw: {
|
|
||||||
up: isValidNumber(raw.up) ? raw.up : 0,
|
|
||||||
down: isValidNumber(raw.down) ? raw.down : 0,
|
|
||||||
up_rate: isValidNumber(raw.up_rate) ? raw.up_rate : 0,
|
|
||||||
down_rate: isValidNumber(raw.down_rate) ? raw.down_rate : 0,
|
|
||||||
},
|
|
||||||
formatted: {
|
|
||||||
up_rate: isValidString(formatted.up_rate) ? formatted.up_rate : '0B',
|
|
||||||
down_rate: isValidString(formatted.down_rate)
|
|
||||||
? formatted.down_rate
|
|
||||||
: '0B',
|
|
||||||
total_up: isValidString(formatted.total_up) ? formatted.total_up : '0B',
|
|
||||||
total_down: isValidString(formatted.total_down)
|
|
||||||
? formatted.total_down
|
|
||||||
: '0B',
|
|
||||||
},
|
|
||||||
is_fresh: isValidBoolean(traffic?.is_fresh) ? traffic.is_fresh : false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sanitizeMemoryData(memory: any) {
|
|
||||||
const raw = memory?.raw || {}
|
|
||||||
const formatted = memory?.formatted || {}
|
|
||||||
|
|
||||||
return {
|
|
||||||
raw: {
|
|
||||||
inuse: isValidNumber(raw.inuse) ? raw.inuse : 0,
|
|
||||||
oslimit: isValidNumber(raw.oslimit) ? raw.oslimit : 0,
|
|
||||||
usage_percent: isValidNumber(raw.usage_percent) ? raw.usage_percent : 0,
|
|
||||||
},
|
|
||||||
formatted: {
|
|
||||||
inuse: isValidString(formatted.inuse) ? formatted.inuse : '0B',
|
|
||||||
oslimit: isValidString(formatted.oslimit) ? formatted.oslimit : '0B',
|
|
||||||
usage_percent: isValidNumber(formatted.usage_percent)
|
|
||||||
? formatted.usage_percent
|
|
||||||
: 0,
|
|
||||||
},
|
|
||||||
is_fresh: isValidBoolean(memory?.is_fresh) ? memory.is_fresh : false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sanitizeOverallStatus(
|
|
||||||
status: any,
|
|
||||||
): 'active' | 'inactive' | 'error' | 'unknown' | 'healthy' {
|
|
||||||
if (
|
|
||||||
typeof status === 'string' &&
|
|
||||||
['active', 'inactive', 'error', 'unknown', 'healthy'].includes(status)
|
|
||||||
) {
|
|
||||||
return status as 'active' | 'inactive' | 'error' | 'unknown' | 'healthy'
|
|
||||||
}
|
|
||||||
return 'unknown'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 全局验证器实例
|
|
||||||
export const systemMonitorValidator = new SystemMonitorValidator()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 安全的API调用包装器
|
|
||||||
*/
|
|
||||||
export function withDataValidation<T extends (...args: any[]) => Promise<any>>(
|
|
||||||
apiCall: T,
|
|
||||||
validator: { validate: (data: any) => boolean; sanitize: (data: any) => any },
|
|
||||||
): T {
|
|
||||||
return (async (...args: Parameters<T>) => {
|
|
||||||
try {
|
|
||||||
const result = await apiCall(...args)
|
|
||||||
|
|
||||||
if (validator.validate(result)) {
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
console.warn('[DataValidator] API返回数据验证失败,尝试修复:', result)
|
|
||||||
return validator.sanitize(result)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[DataValidator] API调用失败:', error)
|
|
||||||
// 返回安全的默认值
|
|
||||||
return validator.sanitize(null)
|
|
||||||
}
|
|
||||||
}) as T
|
|
||||||
}
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
/**
|
|
||||||
* 流量统计诊断工具
|
|
||||||
* 用于帮助开发者和用户诊断流量统计系统的性能和状态
|
|
||||||
*/
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user