All files / middleware performance.ts

0% Statements 0/65
100% Branches 1/1
100% Functions 1/1
0% Lines 0/65

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110                                                                                                                                                                                                                           
/**
 * 性能监控中间件
 * 监控 API 响应时间、慢查询、错误率
 */
 
interface PerformanceMetrics {
  totalRequests: number;
  avgResponseTime: number;
  slowRequests: number;
  errors: number;
  endpoints: Record<string, {
    count: number;
    avgTime: number;
    maxTime: number;
    errors: number;
  }>;
}
 
const metrics: PerformanceMetrics = {
  totalRequests: 0,
  avgResponseTime: 0,
  slowRequests: 0,
  errors: 0,
  endpoints: {},
};
 
const SLOW_THRESHOLD = 1000; // 1 秒视为慢请求
 
export function performanceMonitor() {
  return async (ctx: any, next: any) => {
    const start = Date.now();
    const endpoint = `${ctx.method} ${ctx.path}`;
 
    // 初始化端点指标
    if (!metrics.endpoints[endpoint]) {
      metrics.endpoints[endpoint] = {
        count: 0,
        avgTime: 0,
        maxTime: 0,
        errors: 0,
      };
    }
 
    try {
      await next();
 
      const duration = Date.now() - start;
      
      // 更新指标
      metrics.totalRequests++;
      metrics.avgResponseTime = 
        (metrics.avgResponseTime * (metrics.totalRequests - 1) + duration) / metrics.totalRequests;
 
      const epMetrics = metrics.endpoints[endpoint];
      epMetrics.count++;
      epMetrics.avgTime = (epMetrics.avgTime * (epMetrics.count - 1) + duration) / epMetrics.count;
      epMetrics.maxTime = Math.max(epMetrics.maxTime, duration);
 
      // 慢请求日志
      if (duration > SLOW_THRESHOLD) {
        metrics.slowRequests++;
        console.warn(`[Performance] 慢请求: ${endpoint} - ${duration}ms`);
      }
 
      // 添加响应头
      ctx.set('X-Response-Time', `${duration}ms`);
 
    } catch (error) {
      metrics.errors++;
      if (metrics.endpoints[endpoint]) {
        metrics.endpoints[endpoint].errors++;
      }
      throw error;
    }
  };
}
 
/**
 * 获取性能指标
 */
export function getPerformanceMetrics(): PerformanceMetrics {
  return { ...metrics };
}
 
/**
 * 重置性能指标
 */
export function resetPerformanceMetrics(): void {
  metrics.totalRequests = 0;
  metrics.avgResponseTime = 0;
  metrics.slowRequests = 0;
  metrics.errors = 0;
  metrics.endpoints = {};
}
 
/**
 * 性能指标路由
 */
export async function getMetrics(ctx: any) {
  ctx.body = {
    code: 0,
    data: {
      ...metrics,
      errorRate: metrics.totalRequests > 0 
        ? ((metrics.errors / metrics.totalRequests) * 100).toFixed(2) + '%'
        : '0%',
    },
  };
}