refactor: centralize auth middleware and standardize logging
1. API Key Middleware (api.ts) - Create apiKeyAuth Hono middleware with timing-safe comparison - Apply to /deposit/balance and /deposit/deduct routes - Remove duplicate requireApiKey() calls from handlers - Reduce ~15 lines of duplicated code 2. Logger Standardization (6 files, 27 replacements) - webhook.ts: 2 console.error → logger - message-handler.ts: 7 console → logger - deposit-matcher.ts: 4 console → logger - n8n-service.ts: 3 console.error → logger - circuit-breaker.ts: 8 console → logger - retry.ts: 3 console → logger Benefits: - Single point of auth change - Structured logging with context - Better observability in production Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import { metrics } from './metrics';
|
||||
import { notifyAdmin, NotificationOptions } from '../services/notification';
|
||||
import { createLogger } from './logger';
|
||||
|
||||
const logger = createLogger('circuit-breaker');
|
||||
|
||||
/**
|
||||
* Circuit Breaker pattern implementation
|
||||
@@ -99,7 +102,7 @@ export class CircuitBreaker {
|
||||
this.serviceName = options?.serviceName ?? 'unknown';
|
||||
this.notification = options?.notification;
|
||||
|
||||
console.log('[CircuitBreaker] Initialized', {
|
||||
logger.info('Initialized', {
|
||||
serviceName: this.serviceName,
|
||||
failureThreshold: this.failureThreshold,
|
||||
resetTimeoutMs: this.resetTimeoutMs,
|
||||
@@ -146,7 +149,7 @@ export class CircuitBreaker {
|
||||
* Manually reset the circuit to closed state
|
||||
*/
|
||||
reset(): void {
|
||||
console.log('[CircuitBreaker] Manual reset');
|
||||
logger.info('Manual reset', { service: this.serviceName });
|
||||
this.state = CircuitState.CLOSED;
|
||||
this.failures = [];
|
||||
this.openedAt = null;
|
||||
@@ -178,7 +181,10 @@ export class CircuitBreaker {
|
||||
const elapsed = now - this.openedAt;
|
||||
|
||||
if (elapsed >= this.resetTimeoutMs) {
|
||||
console.log('[CircuitBreaker] Reset timeout reached, transitioning to HALF_OPEN');
|
||||
logger.info('Reset timeout reached, transitioning to HALF_OPEN', {
|
||||
service: this.serviceName,
|
||||
elapsedMs: elapsed
|
||||
});
|
||||
this.state = CircuitState.HALF_OPEN;
|
||||
|
||||
// 상태 메트릭 기록 (HALF_OPEN)
|
||||
@@ -194,7 +200,9 @@ export class CircuitBreaker {
|
||||
this.successCount++;
|
||||
|
||||
if (this.state === CircuitState.HALF_OPEN) {
|
||||
console.log('[CircuitBreaker] Half-open test succeeded, closing circuit');
|
||||
logger.info('Half-open test succeeded, closing circuit', {
|
||||
service: this.serviceName
|
||||
});
|
||||
this.state = CircuitState.CLOSED;
|
||||
this.failures = [];
|
||||
this.openedAt = null;
|
||||
@@ -218,7 +226,10 @@ export class CircuitBreaker {
|
||||
|
||||
// If in half-open state, one failure reopens the circuit
|
||||
if (this.state === CircuitState.HALF_OPEN) {
|
||||
console.log('[CircuitBreaker] Half-open test failed, reopening circuit');
|
||||
logger.warn('Half-open test failed, reopening circuit', {
|
||||
service: this.serviceName,
|
||||
error: error.message
|
||||
});
|
||||
this.state = CircuitState.OPEN;
|
||||
this.openedAt = now;
|
||||
|
||||
@@ -246,9 +257,11 @@ export class CircuitBreaker {
|
||||
// Check if we should open the circuit
|
||||
if (this.state === CircuitState.CLOSED) {
|
||||
if (this.failures.length >= this.failureThreshold) {
|
||||
console.log(
|
||||
`[CircuitBreaker] Failure threshold (${this.failureThreshold}) exceeded, opening circuit`
|
||||
);
|
||||
logger.warn('Failure threshold exceeded, opening circuit', {
|
||||
service: this.serviceName,
|
||||
failureThreshold: this.failureThreshold,
|
||||
currentFailures: this.failures.length
|
||||
});
|
||||
this.state = CircuitState.OPEN;
|
||||
this.openedAt = now;
|
||||
|
||||
@@ -291,7 +304,9 @@ export class CircuitBreaker {
|
||||
'Circuit breaker is open - service unavailable',
|
||||
this.state
|
||||
);
|
||||
console.log('[CircuitBreaker] Request blocked - circuit is OPEN');
|
||||
logger.warn('Request blocked - circuit is OPEN', {
|
||||
service: this.serviceName
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -315,10 +330,11 @@ export class CircuitBreaker {
|
||||
this.onFailure(err);
|
||||
|
||||
// Log failure
|
||||
console.error(
|
||||
`[CircuitBreaker] Operation failed (${this.failures.length}/${this.failureThreshold} failures):`,
|
||||
err.message
|
||||
);
|
||||
logger.error('Operation failed', err, {
|
||||
service: this.serviceName,
|
||||
failures: this.failures.length,
|
||||
threshold: this.failureThreshold
|
||||
});
|
||||
|
||||
// Re-throw the original error
|
||||
throw err;
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
|
||||
import { metrics } from './metrics';
|
||||
import { notifyAdmin, NotificationOptions } from '../services/notification';
|
||||
import { createLogger } from './logger';
|
||||
|
||||
const logger = createLogger('retry');
|
||||
|
||||
/**
|
||||
* Configuration options for retry behavior
|
||||
@@ -123,7 +126,11 @@ export async function retryWithBackoff<T>(
|
||||
|
||||
// Log success if this was a retry
|
||||
if (attempt > 0) {
|
||||
console.log(`[Retry] Success on attempt ${attempt + 1}/${maxRetries + 1}`);
|
||||
logger.info('Success on retry', {
|
||||
service: serviceName,
|
||||
attempt: attempt + 1,
|
||||
totalAttempts: maxRetries + 1
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -132,10 +139,10 @@ export async function retryWithBackoff<T>(
|
||||
|
||||
// If this was the last attempt, throw RetryError
|
||||
if (attempt === maxRetries) {
|
||||
console.error(
|
||||
`[Retry] All ${maxRetries + 1} attempts failed. Last error:`,
|
||||
lastError.message
|
||||
);
|
||||
logger.error('All attempts failed', lastError, {
|
||||
service: serviceName,
|
||||
totalAttempts: maxRetries + 1
|
||||
});
|
||||
|
||||
// Send admin notification if configured
|
||||
if (notification) {
|
||||
@@ -176,10 +183,13 @@ export async function retryWithBackoff<T>(
|
||||
jitter
|
||||
);
|
||||
|
||||
console.log(
|
||||
`[Retry] Attempt ${attempt + 1}/${maxRetries + 1} failed. Retrying in ${delay}ms...`,
|
||||
lastError.message
|
||||
);
|
||||
logger.warn('Attempt failed, retrying', {
|
||||
service: serviceName,
|
||||
attempt: attempt + 1,
|
||||
totalAttempts: maxRetries + 1,
|
||||
delayMs: delay,
|
||||
error: lastError.message
|
||||
});
|
||||
|
||||
// Wait before next retry
|
||||
await sleep(delay);
|
||||
|
||||
Reference in New Issue
Block a user