@iota-big3/sdk-gateway
Version:
Universal API Gateway with protocol translation, intelligent routing, rate limiting, health checking, and caching
227 lines • 7.51 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SLAMonitor = void 0;
const events_1 = require("events");
class SLAMonitor extends events_1.EventEmitter {
constructor() {
super();
this.slaConfigs = new Map();
this.violations = [];
this.metrics = new Map();
this.isEnabled = true;
}
addSLA(routePath, slaConfig) {
if (!this.isEnabled) {
return;
}
this.slaConfigs.set(routePath, slaConfig);
this.metrics.set(routePath, {
responseTime: [],
errorCount: 0,
totalRequests: 0,
lastReset: Date.now()
});
this.emit('sla:added', {
routePath,
slaConfig,
timestamp: Date.now()
});
}
removeSLA(routePath) {
if (!this.isEnabled) {
return;
}
this.slaConfigs.delete(routePath);
this.metrics.delete(routePath);
this.emit('sla:removed', {
routePath,
timestamp: Date.now()
});
}
recordRequest(routePath, request, response) {
if (!this.isEnabled) {
return;
}
const slaConfig = this.slaConfigs.get(routePath);
if (!slaConfig) {
return;
}
const routeMetrics = this.metrics.get(routePath);
if (!routeMetrics) {
return;
}
// Record metrics
routeMetrics.totalRequests++;
if (response.latency !== undefined) {
routeMetrics.responseTime.push(response.latency);
}
if (response.statusCode >= 400) {
routeMetrics.errorCount++;
}
// Check for SLA violations
this.checkViolations(routePath, slaConfig, routeMetrics, response);
}
checkViolations(routePath, slaConfig, routeMetrics, response) {
const violations = [];
// Check response time violation
if (response.latency !== undefined && response.latency > slaConfig.responseTime) {
violations.push({
type: 'response_time',
threshold: slaConfig.responseTime,
actual: response.latency,
timestamp: Date.now(),
route: routePath
});
}
// Check error rate violation
const errorRate = routeMetrics.errorCount / routeMetrics.totalRequests;
if (errorRate > slaConfig.errorRate) {
violations.push({
type: 'error_rate',
threshold: slaConfig.errorRate,
actual: errorRate,
timestamp: Date.now(),
route: routePath
});
}
// Check availability violation (simplified)
const availability = (routeMetrics.totalRequests - routeMetrics.errorCount) / routeMetrics.totalRequests;
if (availability < slaConfig.availability) {
violations.push({
type: 'availability',
threshold: slaConfig.availability,
actual: availability,
timestamp: Date.now(),
route: routePath
});
}
// Process violations
violations.forEach(violation => {
this.violations.push(violation);
this.emit('sla:violation', violation);
// Execute actions if configured
if (slaConfig.actions) {
slaConfig.actions.forEach(action => {
this.executeAction(action, violation);
});
}
});
}
executeAction(action, violation) {
if (!this.isEnabled) {
return;
}
this.emit('sla:action', {
action,
violation,
timestamp: Date.now()
});
// In real implementation, would execute specific actions like:
// - Send alerts
// - Scale services
// - Circuit breaker activation
// - Logging
}
getViolations(routePath) {
if (routePath) {
return this.violations.filter(v => v.route === routePath);
}
return [...this.violations];
}
getSLAStatus(routePath) {
if (!this.isEnabled) {
return null;
}
const slaConfig = this.slaConfigs.get(routePath);
const routeMetrics = this.metrics.get(routePath);
if (!slaConfig || !routeMetrics) {
return null;
}
const responseTimes = routeMetrics.responseTime;
const averageResponseTime = responseTimes.length > 0 ?
responseTimes.reduce((sum, time) => sum + time, 0) / responseTimes.length : 0;
const sortedTimes = [...responseTimes].sort((a, b) => a - b);
const p95Index = Math.floor(sortedTimes.length * 0.95);
const p95ResponseTime = sortedTimes[p95Index] || 0;
const errorRate = routeMetrics.totalRequests > 0 ?
routeMetrics.errorCount / routeMetrics.totalRequests : 0;
const availability = routeMetrics.totalRequests > 0 ?
(routeMetrics.totalRequests - routeMetrics.errorCount) / routeMetrics.totalRequests : 1;
const isCompliant = averageResponseTime <= slaConfig.responseTime &&
errorRate <= slaConfig.errorRate &&
availability >= slaConfig.availability;
return {
isCompliant,
responseTime: {
average: averageResponseTime,
p95: p95ResponseTime,
threshold: slaConfig.responseTime
},
errorRate: {
current: errorRate,
threshold: slaConfig.errorRate
},
availability: {
current: availability,
threshold: slaConfig.availability
}
};
}
resetMetrics(routePath) {
if (!this.isEnabled) {
return;
}
if (routePath) {
const routeMetrics = this.metrics.get(routePath);
if (routeMetrics) {
routeMetrics.responseTime = [];
routeMetrics.errorCount = 0;
routeMetrics.totalRequests = 0;
routeMetrics.lastReset = Date.now();
}
}
else {
this.metrics.forEach(routeMetrics => {
routeMetrics.responseTime = [];
routeMetrics.errorCount = 0;
routeMetrics.totalRequests = 0;
routeMetrics.lastReset = Date.now();
});
}
this.emit('metrics:reset', {
routePath,
timestamp: Date.now()
});
}
clearViolations(routePath) {
if (!this.isEnabled) {
return;
}
if (routePath) {
this.violations = this.violations.filter(v => v.route !== routePath);
}
else {
this.violations = [];
}
this.emit('violations:cleared', {
routePath,
timestamp: Date.now()
});
}
getAllSLAs() {
return new Map(this.slaConfigs);
}
enable() {
this.isEnabled = true;
this.emit('sla:enabled', { timestamp: Date.now() });
}
disable() {
this.isEnabled = false;
this.emit('sla:disabled', { timestamp: Date.now() });
}
isSLAEnabled() {
return this.isEnabled;
}
}
exports.SLAMonitor = SLAMonitor;
//# sourceMappingURL=sla-monitor.js.map