Update test framework: fix run_tests.py to support all test files, add auto-import-check for test files

This commit is contained in:
qiaoxinjiu
2026-05-09 15:11:30 +08:00
parent eb053a347f
commit eaba8328da
21739 changed files with 2236758 additions and 719 deletions

View File

@@ -0,0 +1,2 @@
export * from './types.js';
export * from './system.js';

View File

@@ -0,0 +1,3 @@
// Monitoring module exports
export * from './types.js';
export * from './system.js';

View File

@@ -0,0 +1,75 @@
import { MonitoringConfig, Metrics, HealthStatus } from './types';
/**
* System Monitoring Class
* Tracks performance metrics and system health
*/
export declare class MonitoringSystem {
private config;
private metrics;
private requestHistory;
private startTime;
private metricsInterval?;
private healthCheckInterval?;
private httpServer?;
private app?;
private actualPort?;
constructor(config: MonitoringConfig);
/**
* Record a request for metrics tracking
* @param duration Request duration in milliseconds
* @param success Whether the request was successful
* @param category Optional request category
*/
recordRequest(duration: number, success: boolean, category?: string): void;
/**
* Record a rate limit violation
*/
recordRateLimitViolation(): void;
/**
* Update active browser count
* @param count Current number of active browsers
*/
updateActiveBrowsers(count: number): void;
/**
* Update active connections count
* @param count Current number of active SSE connections
*/
updateActiveConnections(count: number): void;
/**
* Get current system metrics
* @returns Current metrics snapshot
*/
getMetrics(): Metrics;
/**
* Get system health status
* @returns Current health status
*/
getHealthStatus(): HealthStatus;
/**
* Start metrics collection and HTTP server for health checks
* @param port Optional port for HTTP server (default: 3001)
*/
startMetricsCollection(port?: number): Promise<void>;
/**
* Start HTTP server for health check endpoints
* @param port Port to listen on
*/
private startHttpServer;
/**
* Stop metrics collection and HTTP server
*/
stopMetricsCollection(): Promise<void>;
/**
* Update system-level metrics
*/
private updateSystemMetrics;
/**
* Update average response time based on recent requests
*/
private updateAverageResponseTime;
/**
* Get the actual port the monitoring server is listening on
* @returns The port number, or undefined if server not started
*/
getMonitoringPort(): number | undefined;
}

View File

@@ -0,0 +1,214 @@
import express from 'express';
/**
* System Monitoring Class
* Tracks performance metrics and system health
*/
export class MonitoringSystem {
constructor(config) {
this.requestHistory = [];
this.config = config;
this.startTime = Date.now();
this.metrics = {
requestCount: 0,
errorCount: 0,
averageResponseTime: 0,
activeBrowsers: 0,
memoryUsage: 0,
uptime: 0,
activeConnections: 0,
rateLimitViolations: 0
};
}
/**
* Record a request for metrics tracking
* @param duration Request duration in milliseconds
* @param success Whether the request was successful
* @param category Optional request category
*/
recordRequest(duration, success, category) {
const requestMetric = {
duration,
success,
timestamp: Date.now(),
category
};
this.requestHistory.push(requestMetric);
this.metrics.requestCount++;
if (!success) {
this.metrics.errorCount++;
}
// Keep only recent requests for average calculation (last 1000)
if (this.requestHistory.length > 1000) {
this.requestHistory = this.requestHistory.slice(-1000);
}
this.updateAverageResponseTime();
}
/**
* Record a rate limit violation
*/
recordRateLimitViolation() {
this.metrics.rateLimitViolations++;
}
/**
* Update active browser count
* @param count Current number of active browsers
*/
updateActiveBrowsers(count) {
this.metrics.activeBrowsers = count;
}
/**
* Update active connections count
* @param count Current number of active SSE connections
*/
updateActiveConnections(count) {
this.metrics.activeConnections = count;
}
/**
* Get current system metrics
* @returns Current metrics snapshot
*/
getMetrics() {
this.updateSystemMetrics();
return { ...this.metrics };
}
/**
* Get system health status
* @returns Current health status
*/
getHealthStatus() {
const checks = {};
// Memory check
const memoryUsage = process.memoryUsage();
const memoryUsagePercent = (memoryUsage.heapUsed / memoryUsage.heapTotal) * 100;
checks.memory = {
status: memoryUsagePercent > this.config.memoryThreshold ? 'warn' : 'pass',
description: `Memory usage: ${memoryUsagePercent.toFixed(2)}%`,
data: { memoryUsage, threshold: this.config.memoryThreshold }
};
// Response time check
const avgResponseTime = this.metrics.averageResponseTime;
checks.responseTime = {
status: avgResponseTime > this.config.responseTimeThreshold ? 'warn' : 'pass',
description: `Average response time: ${avgResponseTime.toFixed(2)}ms`,
data: { averageResponseTime: avgResponseTime, threshold: this.config.responseTimeThreshold }
};
// Error rate check
const errorRate = this.metrics.requestCount > 0 ? (this.metrics.errorCount / this.metrics.requestCount) * 100 : 0;
checks.errorRate = {
status: errorRate > 10 ? 'warn' : errorRate > 5 ? 'warn' : 'pass',
description: `Error rate: ${errorRate.toFixed(2)}%`,
data: { errorRate, errorCount: this.metrics.errorCount, requestCount: this.metrics.requestCount }
};
// Overall status
const hasFailures = Object.values(checks).some(check => check.status === 'fail');
const hasWarnings = Object.values(checks).some(check => check.status === 'warn');
const status = hasFailures ? 'unhealthy' : hasWarnings ? 'degraded' : 'healthy';
return {
status,
checks,
timestamp: Date.now(),
version: process.env.npm_package_version
};
}
/**
* Start metrics collection and HTTP server for health checks
* @param port Optional port for HTTP server (default: 3001)
*/
async startMetricsCollection(port = 3001) {
if (!this.config.enabled)
return;
this.metricsInterval = setInterval(() => {
this.updateSystemMetrics();
}, this.config.metricsInterval);
this.healthCheckInterval = setInterval(() => {
// Health checks are performed on-demand via getHealthStatus()
// This interval can be used for proactive health monitoring
}, this.config.healthCheckInterval);
// Start HTTP server for health check endpoints
await this.startHttpServer(port);
}
/**
* Start HTTP server for health check endpoints
* @param port Port to listen on
*/
async startHttpServer(port) {
this.app = express();
this.app.use(express.json());
// Health check endpoint
this.app.get('/health', (req, res) => {
const healthStatus = this.getHealthStatus();
const statusCode = healthStatus.status === 'healthy' ? 200 :
healthStatus.status === 'degraded' ? 200 : 503;
res.status(statusCode).json(healthStatus);
});
// Metrics endpoint
this.app.get('/metrics', (req, res) => {
const metrics = this.getMetrics();
res.json(metrics);
});
// Ready endpoint (simple health check)
this.app.get('/ready', (req, res) => {
res.json({ status: 'ready', timestamp: Date.now() });
});
return new Promise((resolve, reject) => {
this.httpServer = this.app.listen(port, () => {
// Get the actual port assigned (important when using port 0 for dynamic allocation)
const address = this.httpServer.address();
this.actualPort = typeof address === 'object' && address !== null ? address.port : port;
console.log(`Monitoring HTTP server listening on port ${this.actualPort}`);
console.log(`Health check: http://localhost:${this.actualPort}/health`);
console.log(`Metrics: http://localhost:${this.actualPort}/metrics`);
resolve();
});
this.httpServer.on('error', (error) => {
reject(error);
});
});
}
/**
* Stop metrics collection and HTTP server
*/
async stopMetricsCollection() {
if (this.metricsInterval) {
clearInterval(this.metricsInterval);
this.metricsInterval = undefined;
}
if (this.healthCheckInterval) {
clearInterval(this.healthCheckInterval);
this.healthCheckInterval = undefined;
}
if (this.httpServer) {
return new Promise((resolve) => {
this.httpServer.close(() => {
console.log('Monitoring HTTP server stopped');
resolve();
});
});
}
}
/**
* Update system-level metrics
*/
updateSystemMetrics() {
this.metrics.uptime = Date.now() - this.startTime;
this.metrics.memoryUsage = process.memoryUsage().heapUsed;
}
/**
* Update average response time based on recent requests
*/
updateAverageResponseTime() {
if (this.requestHistory.length === 0) {
this.metrics.averageResponseTime = 0;
return;
}
const totalTime = this.requestHistory.reduce((sum, req) => sum + req.duration, 0);
this.metrics.averageResponseTime = totalTime / this.requestHistory.length;
}
/**
* Get the actual port the monitoring server is listening on
* @returns The port number, or undefined if server not started
*/
getMonitoringPort() {
return this.actualPort;
}
}

View File

@@ -0,0 +1,77 @@
/**
* System Metrics Interface
*/
export interface Metrics {
/** Total number of requests processed */
requestCount: number;
/** Total number of errors encountered */
errorCount: number;
/** Average response time in milliseconds */
averageResponseTime: number;
/** Number of active browser instances */
activeBrowsers: number;
/** Memory usage in bytes */
memoryUsage: number;
/** Server uptime in milliseconds */
uptime: number;
/** Number of active SSE connections */
activeConnections: number;
/** Rate limit violations count */
rateLimitViolations: number;
}
/**
* Health Check Status
*/
export interface HealthStatus {
/** Overall system status */
status: 'healthy' | 'degraded' | 'unhealthy';
/** Individual health checks */
checks: Record<string, HealthCheck>;
/** Status timestamp */
timestamp: number;
/** System version */
version?: string;
}
/**
* Individual Health Check
*/
export interface HealthCheck {
/** Check status */
status: 'pass' | 'fail' | 'warn';
/** Check description */
description?: string;
/** Check duration in milliseconds */
duration?: number;
/** Additional check data */
data?: Record<string, any>;
}
/**
* Performance Metrics Configuration
*/
export interface MonitoringConfig {
/** Enable metrics collection */
enabled: boolean;
/** Metrics collection interval in milliseconds */
metricsInterval: number;
/** Health check interval in milliseconds */
healthCheckInterval: number;
/** Memory usage threshold for warnings (percentage) */
memoryThreshold: number;
/** Response time threshold for warnings (milliseconds) */
responseTimeThreshold: number;
}
/**
* Request Performance Data
*/
export interface RequestMetrics {
/** Request duration in milliseconds */
duration: number;
/** Whether request was successful */
success: boolean;
/** Request timestamp */
timestamp: number;
/** Request type/category */
category?: string;
/** Response size in bytes */
responseSize?: number;
}

View File

@@ -0,0 +1 @@
export {};