diff --git a/src/Utils/structured-logger.ts b/src/Utils/structured-logger.ts index 57053172..ffe64ab3 100644 --- a/src/Utils/structured-logger.ts +++ b/src/Utils/structured-logger.ts @@ -73,10 +73,6 @@ export interface StructuredLoggerConfig { maxLogsPerSecond?: number /** Enable async logging queue (default: false) */ enableAsyncQueue?: boolean - /** Circuit breaker failure threshold for external hooks (default: 5) */ - circuitBreakerThreshold?: number - /** Circuit breaker reset timeout in ms (default: 30000) */ - circuitBreakerResetMs?: number /** Enable Prometheus metrics integration (default: false) */ enableMetrics?: boolean } @@ -155,8 +151,6 @@ export interface LoggerMetrics { bufferFlushes: number /** External hook failures */ hookFailures: number - /** Circuit breaker trips */ - circuitBreakerTrips: number /** Average log processing time in ms */ avgProcessingTimeMs: number } @@ -169,8 +163,6 @@ export interface LoggerStatistics extends LoggerMetrics { bufferSize: number /** Rate limiter tokens available */ rateLimiterTokens: number - /** Circuit breaker state */ - circuitBreakerState: 'closed' | 'open' | 'half-open' /** Queue size (if async enabled) */ queueSize: number /** Created timestamp */ @@ -242,69 +234,6 @@ class RateLimiter { } } -// ============================================================================ -// CIRCUIT BREAKER -// ============================================================================ - -/** - * Circuit breaker for external hook protection - */ -class CircuitBreaker { - private failures = 0 - private lastFailure = 0 - private state: 'closed' | 'open' | 'half-open' = 'closed' - - constructor( - private readonly threshold: number, - private readonly resetTimeoutMs: number - ) {} - - async execute(operation: () => Promise): Promise { - if (this.state === 'open') { - if (Date.now() - this.lastFailure > this.resetTimeoutMs) { - this.state = 'half-open' - } else { - return null // Circuit is open, skip - } - } - - try { - const result = await operation() - this.onSuccess() - return result - } catch (error) { - this.onFailure() - throw error - } - } - - private onSuccess(): void { - this.failures = 0 - this.state = 'closed' - } - - private onFailure(): void { - this.failures++ - this.lastFailure = Date.now() - if (this.failures >= this.threshold) { - this.state = 'open' - } - } - - getState(): 'closed' | 'open' | 'half-open' { - // Check if should transition from open to half-open - if (this.state === 'open' && Date.now() - this.lastFailure > this.resetTimeoutMs) { - this.state = 'half-open' - } - - return this.state - } - - getFailures(): number { - return this.failures - } -} - // ============================================================================ // ASYNC LOG QUEUE // ============================================================================ @@ -403,8 +332,6 @@ export class StructuredLogger implements ILogger { private rateLimiter: RateLimiter | null = null // Circuit breaker for external hook - private circuitBreaker: CircuitBreaker | null = null - // Async queue private asyncQueue: AsyncLogQueue | null = null @@ -435,8 +362,6 @@ export class StructuredLogger implements ILogger { enableRateLimiting: config.enableRateLimiting ?? envConfig.enableRateLimiting ?? false, maxLogsPerSecond: config.maxLogsPerSecond ?? envConfig.maxLogsPerSecond ?? 1000, enableAsyncQueue: config.enableAsyncQueue ?? envConfig.enableAsyncQueue ?? false, - circuitBreakerThreshold: config.circuitBreakerThreshold ?? 5, - circuitBreakerResetMs: config.circuitBreakerResetMs ?? 30000, enableMetrics: config.enableMetrics ?? envConfig.enableMetrics ?? false } @@ -455,7 +380,6 @@ export class StructuredLogger implements ILogger { droppedLogs: 0, bufferFlushes: 0, hookFailures: 0, - circuitBreakerTrips: 0, avgProcessingTimeMs: 0 } @@ -464,11 +388,6 @@ export class StructuredLogger implements ILogger { this.rateLimiter = new RateLimiter(this.config.maxLogsPerSecond) } - // Initialize circuit breaker for external hook - if (this.config.externalHook) { - this.circuitBreaker = new CircuitBreaker(this.config.circuitBreakerThreshold, this.config.circuitBreakerResetMs) - } - // Initialize async queue if (this.config.enableAsyncQueue) { this.asyncQueue = new AsyncLogQueue() @@ -569,19 +488,23 @@ export class StructuredLogger implements ILogger { this.output(entry) } - // External hook with circuit breaker + // External hook — fire-and-forget. Failures are counted in + // hookFailures metric so chronic breakage is visible to operators + // who can fix their hook. We do not gate further calls — that is + // the consumer's responsibility (consistent with the rest of the + // codebase after the circuit-breaker removal). const externalHook = this.config.externalHook - if (externalHook && this.circuitBreaker) { - this.circuitBreaker - .execute(async () => { - await Promise.resolve(externalHook(entry)) - }) - .catch(() => { - this.metrics.hookFailures++ - if (this.circuitBreaker?.getState() === 'open') { - this.metrics.circuitBreakerTrips++ - } - }) + if (externalHook) { + try { + const hookResult = externalHook(entry) as unknown + if (hookResult && typeof (hookResult as Promise).then === 'function') { + ;(hookResult as Promise).catch(() => { + this.metrics.hookFailures++ + }) + } + } catch { + this.metrics.hookFailures++ + } } // Track processing time @@ -834,7 +757,6 @@ export class StructuredLogger implements ILogger { ...this.metrics, bufferSize: this.buffer.length, rateLimiterTokens: this.rateLimiter?.getTokens() ?? 0, - circuitBreakerState: this.circuitBreaker?.getState() ?? 'closed', queueSize: this.asyncQueue?.getSize() ?? 0, createdAt: this.createdAt, uptimeMs: Date.now() - this.createdAt @@ -860,7 +782,6 @@ export class StructuredLogger implements ILogger { droppedLogs: 0, bufferFlushes: 0, hookFailures: 0, - circuitBreakerTrips: 0, avgProcessingTimeMs: 0 } this.totalProcessingTime = 0 @@ -893,7 +814,6 @@ export class StructuredLogger implements ILogger { // Clear references this.rateLimiter = null - this.circuitBreaker = null this.metricsModule = null } }