feat: Add production logging gating (Phase 1, Task 1.1)

- Created logger utility with environment-based gating (lib/utils/logger.ts)
- Replaced 517 console.log statements with logger.log (71% reduction)
- Fixed import paths in 15 files (resolved comment-trapped imports)
- Added DEBUG_LOGS=false to .env
- Achieves 71% immediate log reduction (517/731 statements)
- Expected 90% reduction in production when deployed

Impact: Reduced I/O blocking, lower log volume in production
Risk: LOW (easy rollback, non-invasive)
Phase: Phase 1, Task 1.1 (Quick Wins - Console.log Production Gating)

Files changed:
- NEW: lib/utils/logger.ts (production-safe logging)
- NEW: scripts/replace-console-logs.js (automation tool)
- Modified: 15 lib/*.ts files (console.log → logger.log)
- Modified: .env (DEBUG_LOGS=false)

Next: Task 1.2 (Image Size Optimization)
This commit is contained in:
mindesbunister
2025-12-05 00:32:41 +01:00
parent cc3a0a85a0
commit 302511293c
20 changed files with 2223 additions and 518 deletions

View File

@@ -20,6 +20,7 @@
*/
import { getPrismaClient } from '../database/trades'
import { logger } from '../utils/logger'
import { initializeDriftService } from '../drift/client'
import { getMergedConfig, SUPPORTED_MARKETS } from '../../config/trading'
@@ -60,11 +61,11 @@ export class BlockedSignalTracker {
*/
public start(): void {
if (this.isRunning) {
console.log('⚠️ Blocked signal tracker already running')
logger.log('⚠️ Blocked signal tracker already running')
return
}
console.log('🔬 Starting blocked signal price tracker...')
logger.log('🔬 Starting blocked signal price tracker...')
this.isRunning = true
// Run immediately on start
@@ -79,7 +80,7 @@ export class BlockedSignalTracker {
})
}, 5 * 60 * 1000) // 5 minutes
console.log('✅ Blocked signal tracker started (runs every 5 minutes)')
logger.log('✅ Blocked signal tracker started (runs every 5 minutes)')
}
/**
@@ -91,7 +92,7 @@ export class BlockedSignalTracker {
this.intervalId = null
}
this.isRunning = false
console.log('⏹️ Blocked signal tracker stopped')
logger.log('⏹️ Blocked signal tracker stopped')
}
/**
@@ -102,7 +103,7 @@ export class BlockedSignalTracker {
// Initialize Drift service if needed
const driftService = await initializeDriftService()
if (!driftService) {
console.log('⚠️ Drift service not available, skipping price tracking')
logger.log('⚠️ Drift service not available, skipping price tracking')
return
}
@@ -122,17 +123,17 @@ export class BlockedSignalTracker {
})
if (signals.length === 0) {
console.log('📊 No blocked signals to track')
logger.log('📊 No blocked signals to track')
return
}
console.log(`📊 Tracking ${signals.length} blocked signals...`)
logger.log(`📊 Tracking ${signals.length} blocked signals...`)
for (const signal of signals) {
await this.trackSignal(signal as any)
}
console.log(`✅ Price tracking complete for ${signals.length} signals`)
logger.log(`✅ Price tracking complete for ${signals.length} signals`)
} catch (error) {
console.error('❌ Error in trackPrices:', error)
}
@@ -152,7 +153,7 @@ export class BlockedSignalTracker {
const marketConfig = SUPPORTED_MARKETS[signal.symbol]
if (!marketConfig) {
console.log(`⚠️ No market config for ${signal.symbol}, skipping`)
logger.log(`⚠️ No market config for ${signal.symbol}, skipping`)
return
}
@@ -160,7 +161,7 @@ export class BlockedSignalTracker {
const entryPrice = Number(signal.entryPrice)
if (entryPrice === 0) {
console.log(`⚠️ Entry price is 0 for ${signal.symbol}, skipping`)
logger.log(`⚠️ Entry price is 0 for ${signal.symbol}, skipping`)
return
}
@@ -184,56 +185,56 @@ export class BlockedSignalTracker {
if (elapsedMinutes >= 1 && !signal.priceAfter1Min) {
updates.priceAfter1Min = currentPrice
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 1min: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
logger.log(` 📍 ${signal.symbol} ${signal.direction} @ 1min: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
}
if (elapsedMinutes >= 5 && !signal.priceAfter5Min) {
updates.priceAfter5Min = currentPrice
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 5min: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
logger.log(` 📍 ${signal.symbol} ${signal.direction} @ 5min: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
}
if (elapsedMinutes >= 15 && !signal.priceAfter15Min) {
updates.priceAfter15Min = currentPrice
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 15min: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
logger.log(` 📍 ${signal.symbol} ${signal.direction} @ 15min: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
}
if (elapsedMinutes >= 30 && !signal.priceAfter30Min) {
updates.priceAfter30Min = currentPrice
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 30min: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
logger.log(` 📍 ${signal.symbol} ${signal.direction} @ 30min: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
}
// EXTENDED TRACKING (Dec 2, 2025): Track up to 8 hours for slow developers
if (elapsedMinutes >= 60 && !signal.priceAfter1Hr) {
updates.priceAfter1Hr = currentPrice
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 1hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
logger.log(` 📍 ${signal.symbol} ${signal.direction} @ 1hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
}
if (elapsedMinutes >= 120 && !signal.priceAfter2Hr) {
updates.priceAfter2Hr = currentPrice
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 2hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
logger.log(` 📍 ${signal.symbol} ${signal.direction} @ 2hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
}
if (elapsedMinutes >= 240 && !signal.priceAfter4Hr) {
updates.priceAfter4Hr = currentPrice
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 4hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
logger.log(` 📍 ${signal.symbol} ${signal.direction} @ 4hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
}
if (elapsedMinutes >= 480 && !signal.priceAfter8Hr) {
updates.priceAfter8Hr = currentPrice
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 8hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
logger.log(` 📍 ${signal.symbol} ${signal.direction} @ 8hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
}
// Mark complete after 8 hours OR if TP/SL already hit
if (elapsedMinutes >= 480 && !signal.analysisComplete) {
updates.analysisComplete = true
console.log(`${signal.symbol} ${signal.direction} @ 8hr: TRACKING COMPLETE`)
logger.log(`${signal.symbol} ${signal.direction} @ 8hr: TRACKING COMPLETE`)
}
// Early completion if TP1/TP2/SL hit (no need to wait full 8 hours)
if (!signal.analysisComplete && (signal.wouldHitTP1 || signal.wouldHitTP2 || signal.wouldHitSL)) {
updates.analysisComplete = true
const hitReason = signal.wouldHitTP1 ? 'TP1' : signal.wouldHitTP2 ? 'TP2' : 'SL'
console.log(`${signal.symbol} ${signal.direction}: ${hitReason} hit at ${profitPercent.toFixed(2)}% - TRACKING COMPLETE`)
logger.log(`${signal.symbol} ${signal.direction}: ${hitReason} hit at ${profitPercent.toFixed(2)}% - TRACKING COMPLETE`)
}
// Update max favorable/adverse excursion
@@ -253,17 +254,17 @@ export class BlockedSignalTracker {
// Check if TP1/TP2/SL would have been hit
if (signal.wouldHitTP1 === null && Math.abs(profitPercent) >= tp1Percent) {
updates.wouldHitTP1 = profitPercent > 0
console.log(` 🎯 ${signal.symbol} ${signal.direction} hit ${profitPercent > 0 ? 'TP1' : 'SL'} (${profitPercent.toFixed(2)}%)`)
logger.log(` 🎯 ${signal.symbol} ${signal.direction} hit ${profitPercent > 0 ? 'TP1' : 'SL'} (${profitPercent.toFixed(2)}%)`)
}
if (signal.wouldHitTP2 === null && Math.abs(profitPercent) >= tp2Percent) {
updates.wouldHitTP2 = profitPercent > 0
console.log(` 🎯 ${signal.symbol} ${signal.direction} hit TP2 (${profitPercent.toFixed(2)}%)`)
logger.log(` 🎯 ${signal.symbol} ${signal.direction} hit TP2 (${profitPercent.toFixed(2)}%)`)
}
if (signal.wouldHitSL === null && profitPercent <= -slPercent) {
updates.wouldHitSL = true
console.log(` 🛑 ${signal.symbol} ${signal.direction} hit SL (${profitPercent.toFixed(2)}%)`)
logger.log(` 🛑 ${signal.symbol} ${signal.direction} hit SL (${profitPercent.toFixed(2)}%)`)
}
// Update database if we have changes
@@ -344,7 +345,7 @@ export class BlockedSignalTracker {
}
})
console.log(`📊 Retrieved ${marketData.length} 1-minute data points for ${symbol}`)
logger.log(`📊 Retrieved ${marketData.length} 1-minute data points for ${symbol}`)
return marketData
} catch (error) {
console.error('❌ Error querying historical prices:', error)
@@ -388,7 +389,7 @@ export class BlockedSignalTracker {
slPrice = entryPrice * (1 + targets.slPercent / 100)
}
console.log(`🎯 Analyzing ${signal.symbol} ${direction}: Entry $${entryPrice.toFixed(2)}, TP1 $${tp1Price.toFixed(2)}, TP2 $${tp2Price.toFixed(2)}, SL $${slPrice.toFixed(2)}`)
logger.log(`🎯 Analyzing ${signal.symbol} ${direction}: Entry $${entryPrice.toFixed(2)}, TP1 $${tp1Price.toFixed(2)}, TP2 $${tp2Price.toFixed(2)}, SL $${slPrice.toFixed(2)}`)
// Track hits (only record first occurrence)
let tp1HitTime: Date | null = null
@@ -439,7 +440,7 @@ export class BlockedSignalTracker {
: currentPrice <= tp1Price
if (tp1Hit) {
tp1HitTime = timestamp
console.log(`✅ TP1 hit at ${timestamp.toISOString()} (${minutesElapsed}min) - Price: $${currentPrice.toFixed(2)}`)
logger.log(`✅ TP1 hit at ${timestamp.toISOString()} (${minutesElapsed}min) - Price: $${currentPrice.toFixed(2)}`)
}
}
@@ -450,7 +451,7 @@ export class BlockedSignalTracker {
: currentPrice <= tp2Price
if (tp2Hit) {
tp2HitTime = timestamp
console.log(`✅ TP2 hit at ${timestamp.toISOString()} (${minutesElapsed}min) - Price: $${currentPrice.toFixed(2)}`)
logger.log(`✅ TP2 hit at ${timestamp.toISOString()} (${minutesElapsed}min) - Price: $${currentPrice.toFixed(2)}`)
}
}
@@ -461,7 +462,7 @@ export class BlockedSignalTracker {
: currentPrice >= slPrice
if (slHit) {
slHitTime = timestamp
console.log(`❌ SL hit at ${timestamp.toISOString()} (${minutesElapsed}min) - Price: $${currentPrice.toFixed(2)}`)
logger.log(`❌ SL hit at ${timestamp.toISOString()} (${minutesElapsed}min) - Price: $${currentPrice.toFixed(2)}`)
}
}
@@ -502,7 +503,7 @@ export class BlockedSignalTracker {
if (checkpoints['4hr']) updates.priceAfter4Hr = checkpoints['4hr']
if (checkpoints['8hr']) updates.priceAfter8Hr = checkpoints['8hr']
console.log(`📊 Analysis complete: TP1=${updates.wouldHitTP1}, TP2=${updates.wouldHitTP2}, SL=${updates.wouldHitSL}, MFE=${maxFavorableExcursion.toFixed(2)}%, MAE=${maxAdverseExcursion.toFixed(2)}%`)
logger.log(`📊 Analysis complete: TP1=${updates.wouldHitTP1}, TP2=${updates.wouldHitTP2}, SL=${updates.wouldHitSL}, MFE=${maxFavorableExcursion.toFixed(2)}%, MAE=${maxAdverseExcursion.toFixed(2)}%`)
return updates
}
@@ -544,11 +545,11 @@ export class BlockedSignalTracker {
})
if (signalsToProcess.length === 0) {
console.log('📊 No signals ready for batch processing')
logger.log('📊 No signals ready for batch processing')
return
}
console.log(`🔄 Processing ${signalsToProcess.length} signals with historical data...`)
logger.log(`🔄 Processing ${signalsToProcess.length} signals with historical data...`)
let processed = 0
let skipped = 0
@@ -567,12 +568,12 @@ export class BlockedSignalTracker {
)
if (historicalPrices.length === 0) {
console.log(`⏭️ Skipping ${signal.symbol} ${signal.direction} - no historical data`)
logger.log(`⏭️ Skipping ${signal.symbol} ${signal.direction} - no historical data`)
skipped++
continue
}
console.log(`📊 Processing ${signal.symbol} ${signal.direction} with ${historicalPrices.length} data points...`)
logger.log(`📊 Processing ${signal.symbol} ${signal.direction} with ${historicalPrices.length} data points...`)
// Analyze minute-by-minute
const updates = await this.analyzeHistoricalData(
@@ -591,7 +592,7 @@ export class BlockedSignalTracker {
})
processed++
console.log(`${signal.symbol} ${signal.direction} analyzed successfully`)
logger.log(`${signal.symbol} ${signal.direction} analyzed successfully`)
} catch (error) {
console.error(`❌ Error processing signal ${signal.id}:`, error)
@@ -599,7 +600,7 @@ export class BlockedSignalTracker {
}
}
console.log(`🎉 Batch processing complete: ${processed} analyzed, ${skipped} skipped`)
logger.log(`🎉 Batch processing complete: ${processed} analyzed, ${skipped} skipped`)
} catch (error) {
console.error('❌ Error in batch processing:', error)