UNPKG

finops-mcp-server

Version:

MCP server for FinOps Center cost optimization integration

1 lines 5.23 kB
export class PerformanceMonitor{constructor(t){this.maxRequestHistory=1e3,this.maxDurationHistory=100,this.logger=t,this.data={requests:[],operations:new Map,authentication:{totalAttempts:0,successfulAttempts:0,failedAttempts:0,failureReasons:new Map},startTime:Date.now(),lastResetTime:Date.now()}}start(t=6e4){this.logger.info("Starting performance monitoring",{operation:"performance_monitor_start",interval:t}),this.metricsInterval=setInterval(()=>{this.logMetrics()},t)}stop(){this.metricsInterval&&(clearInterval(this.metricsInterval),this.metricsInterval=void 0),this.logger.info("Stopped performance monitoring",{operation:"performance_monitor_stop"})}recordRequest(t,e,a,s,r){const o={timestamp:Date.now(),duration:e,success:a,operation:t};if(void 0!==s&&(o.statusCode=s),void 0!==r&&(o.errorType=r),this.data.requests.push(o),this.data.requests.length>this.maxRequestHistory&&this.data.requests.shift(),this.updateOperationMetrics(t,e,a),e>5e3){const r={operation:t,duration:e,success:a};void 0!==s&&(r.statusCode=s),this.logger.warn("Slow request detected",r)}}recordAuthAttempt(t,e){if(this.data.authentication.totalAttempts++,t)this.data.authentication.successfulAttempts++,this.logger.debug("Authentication successful",{operation:"auth_success"});else{if(this.data.authentication.failedAttempts++,this.data.authentication.lastFailureTime=Date.now(),e){const t=this.data.authentication.failureReasons.get(e)||0;this.data.authentication.failureReasons.set(e,t+1)}this.logger.warn("Authentication failed",{operation:"auth_failure",reason:e})}}getMetrics(){const t=Date.now(),e=this.data.requests.filter(e=>t-e.timestamp<3e5),a=e.filter(t=>t.success),s=e.length,r=e.map(t=>t.duration).sort((t,e)=>t-e),o=r.length>0?r.reduce((t,e)=>t+e,0)/r.length:0;return{requestCount:s,errorCount:s-a.length,averageResponseTime:Math.round(o),p95ResponseTime:this.calculatePercentile(r,95),p99ResponseTime:this.calculatePercentile(r,99),successRate:s>0?a.length/s*100:100,lastResetTime:new Date(this.data.lastResetTime).toISOString()}}getOperationMetrics(){return Array.from(this.data.operations.entries()).map(([t,e])=>({operation:t,count:e.count,totalDuration:e.totalDuration,averageDuration:Math.round(e.totalDuration/e.count),minDuration:e.minDuration,maxDuration:e.maxDuration,errorCount:e.errorCount,lastExecuted:new Date(e.lastExecuted).toISOString()}))}getAuthMetrics(){const t=this.data.authentication,e=t.totalAttempts>0?t.successfulAttempts/t.totalAttempts*100:100;return{totalAttempts:t.totalAttempts,successfulAttempts:t.successfulAttempts,failedAttempts:t.failedAttempts,successRate:Math.round(100*e)/100,lastFailureTime:t.lastFailureTime?new Date(t.lastFailureTime).toISOString():void 0,failureReasons:Object.fromEntries(t.failureReasons)}}reset(){this.data={requests:[],operations:new Map,authentication:{totalAttempts:0,successfulAttempts:0,failedAttempts:0,failureReasons:new Map},startTime:Date.now(),lastResetTime:Date.now()},this.logger.info("Performance metrics reset",{operation:"metrics_reset"})}getRequestPatterns(){const t=Date.now(),e=this.data.requests.filter(e=>t-e.timestamp<36e5),a=new Map,s=new Map,r=new Map;return e.forEach(t=>{a.set(t.operation,(a.get(t.operation)||0)+1),t.success||(s.set(t.operation,(s.get(t.operation)||0)+1),t.errorType&&r.set(t.errorType,(r.get(t.errorType)||0)+1))}),{totalRequests:e.length,operationCounts:Object.fromEntries(a),errorsByOperation:Object.fromEntries(s),errorsByType:Object.fromEntries(r),timeWindow:"1 hour"}}updateOperationMetrics(t,e,a){let s=this.data.operations.get(t);s||(s={count:0,totalDuration:0,minDuration:e,maxDuration:e,errorCount:0,lastExecuted:Date.now(),durations:[]},this.data.operations.set(t,s)),s.count++,s.totalDuration+=e,s.minDuration=Math.min(s.minDuration,e),s.maxDuration=Math.max(s.maxDuration,e),s.lastExecuted=Date.now(),a||s.errorCount++,s.durations.push(e),s.durations.length>this.maxDurationHistory&&s.durations.shift()}calculatePercentile(t,e){if(0===t.length)return 0;const a=Math.ceil(e/100*t.length)-1,s=t[Math.max(0,a)];return Math.round(s||0)}logMetrics(){const t=this.getMetrics(),e=this.getAuthMetrics(),a=this.getRequestPatterns();this.logger.info("Performance metrics summary",{operation:"metrics_summary",metrics:t,authentication:e,patterns:a}),t.successRate<95&&this.logger.warn("Low success rate detected",{operation:"low_success_rate",successRate:t.successRate}),t.averageResponseTime>2e3&&this.logger.warn("High average response time detected",{operation:"high_response_time",averageResponseTime:t.averageResponseTime}),e.successRate<98&&this.logger.warn("Authentication issues detected",{operation:"auth_issues",authSuccessRate:e.successRate,failureReasons:e.failureReasons})}}export function createPerformanceMonitor(t){return new PerformanceMonitor(t)}export function measurePerformance(t,e){return function(a,s,r){const o=r.value;return r.value=async function(...a){const s=Date.now();let r,i=!0;try{return await o.apply(this,a)}catch(t){throw i=!1,r=t,t}finally{const a=Date.now()-s;t.recordRequest(e,a,i,void 0,r?.name)}},r}}export async function measureAsync(t,e,a){const s=Date.now();let r,o=!0;try{return await a()}catch(t){throw o=!1,r=t,t}finally{const a=Date.now()-s;t.recordRequest(e,a,o,void 0,r?.name)}}