Skip to main content
Glama
monitoring.service.ts3.03 kB
import { Injectable, Logger } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; export interface MCPMetrics { serversCreated: number; toolsGenerated: number; apiCalls: number; errors: number; uptime: number; activeConnections: number; lastActivity: Date; } export interface MCPEvent { type: 'server_created' | 'server_stopped' | 'tools_reloaded' | 'api_call' | 'error'; timestamp: Date; data: any; } @Injectable() export class MCPMonitoringService { private readonly logger = new Logger(MCPMonitoringService.name); private metrics: MCPMetrics; private events: MCPEvent[] = []; private startTime: Date; constructor(private eventEmitter: EventEmitter2) { this.startTime = new Date(); this.metrics = { serversCreated: 0, toolsGenerated: 0, apiCalls: 0, errors: 0, uptime: 0, activeConnections: 0, lastActivity: new Date(), }; // 监听事件 this.setupEventListeners(); } private setupEventListeners() { this.eventEmitter.on('mcp.server.created', (data) => { this.recordEvent('server_created', data); this.metrics.serversCreated++; this.metrics.toolsGenerated += data.toolsCount || 0; }); this.eventEmitter.on('mcp.server.stopped', (data) => { this.recordEvent('server_stopped', data); }); this.eventEmitter.on('mcp.tools.reloaded', (data) => { this.recordEvent('tools_reloaded', data); }); this.eventEmitter.on('mcp.api.call', (data) => { this.recordEvent('api_call', data); this.metrics.apiCalls++; }); this.eventEmitter.on('mcp.error', (data) => { this.recordEvent('error', data); this.metrics.errors++; }); } recordEvent(type: MCPEvent['type'], data: any) { const event: MCPEvent = { type, timestamp: new Date(), data, }; this.events.push(event); this.metrics.lastActivity = event.timestamp; // 保持最近1000个事件 if (this.events.length > 1000) { this.events = this.events.slice(-1000); } this.logger.debug(`Event recorded: ${type}`, data); } getMetrics(): MCPMetrics { return { ...this.metrics, uptime: Date.now() - this.startTime.getTime(), }; } getRecentEvents(limit: number = 50): MCPEvent[] { return this.events.slice(-limit).reverse(); } getEventsByType(type: MCPEvent['type'], limit: number = 50): MCPEvent[] { return this.events .filter(event => event.type === type) .slice(-limit) .reverse(); } getHealthStatus() { const metrics = this.getMetrics(); const errorRate = metrics.errors / Math.max(metrics.apiCalls, 1); return { status: errorRate > 0.1 ? 'unhealthy' : 'healthy', uptime: metrics.uptime, errorRate: errorRate, lastActivity: metrics.lastActivity, activeConnections: metrics.activeConnections, }; } updateActiveConnections(count: number) { this.metrics.activeConnections = count; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/zaizaizhao/mcp-swagger-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server