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

@@ -14,6 +14,7 @@
*/
import { getMarketDataCache } from './market-data-cache'
import { logger } from '../utils/logger'
import { getPythPriceMonitor } from '../pyth/price-monitor'
export interface QueuedSignal {
@@ -85,7 +86,7 @@ export class SmartEntryTimer {
monitorIntervalMs: 15000 // 15 seconds
}
console.log('💡 Smart Entry Timer initialized:', {
logger.log('💡 Smart Entry Timer initialized:', {
enabled: this.config.enabled,
maxWait: `${this.config.maxWaitMs / 1000}s`,
pullback: `${this.config.pullbackMin}-${this.config.pullbackMax}%`,
@@ -137,10 +138,10 @@ export class SmartEntryTimer {
this.queuedSignals.set(signal.id, signal)
console.log(`📥 Smart Entry: Queued signal ${signal.id}`)
console.log(` ${signal.direction.toUpperCase()} ${signal.symbol} @ $${signal.signalPrice.toFixed(2)}`)
console.log(` Target pullback: ${this.config.pullbackMin}-${this.config.pullbackMax}%`)
console.log(` Max wait: ${this.config.maxWaitMs / 1000}s`)
logger.log(`📥 Smart Entry: Queued signal ${signal.id}`)
logger.log(` ${signal.direction.toUpperCase()} ${signal.symbol} @ $${signal.signalPrice.toFixed(2)}`)
logger.log(` Target pullback: ${this.config.pullbackMin}-${this.config.pullbackMax}%`)
logger.log(` Max wait: ${this.config.maxWaitMs / 1000}s`)
// Start monitoring if not already running
if (!this.monitoringInterval) {
@@ -156,7 +157,7 @@ export class SmartEntryTimer {
private startMonitoring(): void {
if (this.monitoringInterval) return
console.log(`👁️ Smart Entry: Starting monitoring loop (${this.config.monitorIntervalMs / 1000}s interval)`)
logger.log(`👁️ Smart Entry: Starting monitoring loop (${this.config.monitorIntervalMs / 1000}s interval)`)
this.monitoringInterval = setInterval(() => {
this.checkAllSignals()
@@ -170,7 +171,7 @@ export class SmartEntryTimer {
if (this.monitoringInterval) {
clearInterval(this.monitoringInterval)
this.monitoringInterval = null
console.log(`⏸️ Smart Entry: Monitoring stopped (no active signals)`)
logger.log(`⏸️ Smart Entry: Monitoring stopped (no active signals)`)
}
}
@@ -187,7 +188,7 @@ export class SmartEntryTimer {
// Check for timeout
if (now >= signal.expiresAt) {
console.log(`⏰ Smart Entry: Timeout for ${signal.symbol} (waited ${this.config.maxWaitMs / 1000}s)`)
logger.log(`⏰ Smart Entry: Timeout for ${signal.symbol} (waited ${this.config.maxWaitMs / 1000}s)`)
const priceMonitor = getPythPriceMonitor()
const latestPrice = priceMonitor.getCachedPrice(signal.symbol)
const currentPrice = latestPrice?.price || signal.signalPrice
@@ -210,7 +211,7 @@ export class SmartEntryTimer {
const latestPrice = priceMonitor.getCachedPrice(signal.symbol)
if (!latestPrice || !latestPrice.price) {
console.log(`⚠️ Smart Entry: No price available for ${signal.symbol}, skipping check`)
logger.log(`⚠️ Smart Entry: No price available for ${signal.symbol}, skipping check`)
return
}
@@ -234,18 +235,18 @@ export class SmartEntryTimer {
}
// Log check
console.log(`🔍 Smart Entry: Checking ${signal.symbol} (check #${signal.checksPerformed})`)
console.log(` Signal: $${signal.signalPrice.toFixed(2)} → Current: $${currentPrice.toFixed(2)}`)
console.log(` Pullback: ${pullbackMagnitude.toFixed(2)}% (target ${signal.targetPullbackMin}-${signal.targetPullbackMax}%)`)
logger.log(`🔍 Smart Entry: Checking ${signal.symbol} (check #${signal.checksPerformed})`)
logger.log(` Signal: $${signal.signalPrice.toFixed(2)} → Current: $${currentPrice.toFixed(2)}`)
logger.log(` Pullback: ${pullbackMagnitude.toFixed(2)}% (target ${signal.targetPullbackMin}-${signal.targetPullbackMax}%)`)
// Check if pullback is in target range
if (pullbackMagnitude < signal.targetPullbackMin) {
console.log(` ⏳ Waiting for pullback (${pullbackMagnitude.toFixed(2)}% < ${signal.targetPullbackMin}%)`)
logger.log(` ⏳ Waiting for pullback (${pullbackMagnitude.toFixed(2)}% < ${signal.targetPullbackMin}%)`)
return
}
if (pullbackMagnitude > signal.targetPullbackMax) {
console.log(` ⚠️ Pullback too large (${pullbackMagnitude.toFixed(2)}% > ${signal.targetPullbackMax}%), might be reversal - waiting`)
logger.log(` ⚠️ Pullback too large (${pullbackMagnitude.toFixed(2)}% > ${signal.targetPullbackMax}%), might be reversal - waiting`)
return
}
@@ -262,22 +263,22 @@ export class SmartEntryTimer {
const now = Date.now()
const dataAge = (now - latestMetrics.timestamp) / 1000
console.log(` 📊 Real-time validation (data age: ${dataAge.toFixed(0)}s):`)
logger.log(` 📊 Real-time validation (data age: ${dataAge.toFixed(0)}s):`)
// 1. ADX degradation check (original logic)
if (latestMetrics.adx) {
const adxDrop = signal.signalADX - latestMetrics.adx
if (adxDrop > signal.adxTolerance) {
console.log(` ❌ ADX degraded: ${signal.signalADX.toFixed(1)}${latestMetrics.adx.toFixed(1)} (dropped ${adxDrop.toFixed(1)} points, max ${signal.adxTolerance})`)
logger.log(` ❌ ADX degraded: ${signal.signalADX.toFixed(1)}${latestMetrics.adx.toFixed(1)} (dropped ${adxDrop.toFixed(1)} points, max ${signal.adxTolerance})`)
signal.status = 'cancelled'
signal.executionReason = 'manual_override'
this.queuedSignals.delete(signal.id)
console.log(` 🚫 Signal cancelled: ADX degradation exceeded tolerance`)
logger.log(` 🚫 Signal cancelled: ADX degradation exceeded tolerance`)
return
}
console.log(` ✅ ADX: ${signal.signalADX.toFixed(1)}${latestMetrics.adx.toFixed(1)} (within tolerance)`)
logger.log(` ✅ ADX: ${signal.signalADX.toFixed(1)}${latestMetrics.adx.toFixed(1)} (within tolerance)`)
}
// 2. Volume degradation check (NEW)
@@ -289,15 +290,15 @@ export class SmartEntryTimer {
// Cancel if volume dropped >40%
if (volumeDrop > 40) {
console.log(` ❌ Volume collapsed: ${originalVolume.toFixed(2)}x → ${currentVolume.toFixed(2)}x (${volumeDrop.toFixed(0)}% drop)`)
logger.log(` ❌ Volume collapsed: ${originalVolume.toFixed(2)}x → ${currentVolume.toFixed(2)}x (${volumeDrop.toFixed(0)}% drop)`)
signal.status = 'cancelled'
signal.executionReason = 'manual_override'
this.queuedSignals.delete(signal.id)
console.log(` 🚫 Signal cancelled: Volume degradation - momentum fading`)
logger.log(` 🚫 Signal cancelled: Volume degradation - momentum fading`)
return
}
console.log(` ✅ Volume: ${originalVolume.toFixed(2)}x → ${currentVolume.toFixed(2)}x`)
logger.log(` ✅ Volume: ${originalVolume.toFixed(2)}x → ${currentVolume.toFixed(2)}x`)
}
// 3. RSI reversal check (NEW)
@@ -309,26 +310,26 @@ export class SmartEntryTimer {
if (signal.direction === 'long') {
// LONG: Cancel if RSI dropped into oversold (<30)
if (originalRSI >= 40 && currentRSI < 30) {
console.log(` ❌ RSI collapsed: ${originalRSI.toFixed(1)}${currentRSI.toFixed(1)} (now oversold)`)
logger.log(` ❌ RSI collapsed: ${originalRSI.toFixed(1)}${currentRSI.toFixed(1)} (now oversold)`)
signal.status = 'cancelled'
signal.executionReason = 'manual_override'
this.queuedSignals.delete(signal.id)
console.log(` 🚫 Signal cancelled: RSI reversal - trend weakening`)
logger.log(` 🚫 Signal cancelled: RSI reversal - trend weakening`)
return
}
} else {
// SHORT: Cancel if RSI rose into overbought (>70)
if (originalRSI <= 60 && currentRSI > 70) {
console.log(` ❌ RSI spiked: ${originalRSI.toFixed(1)}${currentRSI.toFixed(1)} (now overbought)`)
logger.log(` ❌ RSI spiked: ${originalRSI.toFixed(1)}${currentRSI.toFixed(1)} (now overbought)`)
signal.status = 'cancelled'
signal.executionReason = 'manual_override'
this.queuedSignals.delete(signal.id)
console.log(` 🚫 Signal cancelled: RSI reversal - trend weakening`)
logger.log(` 🚫 Signal cancelled: RSI reversal - trend weakening`)
return
}
}
console.log(` ✅ RSI: ${originalRSI.toFixed(1)}${currentRSI.toFixed(1)}`)
logger.log(` ✅ RSI: ${originalRSI.toFixed(1)}${currentRSI.toFixed(1)}`)
}
// 4. MAGAP divergence check (NEW)
@@ -338,36 +339,36 @@ export class SmartEntryTimer {
if (signal.direction === 'long' && currentMAGap < -1.0) {
// LONG but MAs now bearish diverging
console.log(` ❌ MA structure bearish: MAGAP ${currentMAGap.toFixed(2)}% (death cross accelerating)`)
logger.log(` ❌ MA structure bearish: MAGAP ${currentMAGap.toFixed(2)}% (death cross accelerating)`)
signal.status = 'cancelled'
signal.executionReason = 'manual_override'
this.queuedSignals.delete(signal.id)
console.log(` 🚫 Signal cancelled: MA structure turned bearish`)
logger.log(` 🚫 Signal cancelled: MA structure turned bearish`)
return
}
if (signal.direction === 'short' && currentMAGap > 1.0) {
// SHORT but MAs now bullish diverging
console.log(` ❌ MA structure bullish: MAGAP ${currentMAGap.toFixed(2)}% (golden cross accelerating)`)
logger.log(` ❌ MA structure bullish: MAGAP ${currentMAGap.toFixed(2)}% (golden cross accelerating)`)
signal.status = 'cancelled'
signal.executionReason = 'manual_override'
this.queuedSignals.delete(signal.id)
console.log(` 🚫 Signal cancelled: MA structure turned bullish`)
logger.log(` 🚫 Signal cancelled: MA structure turned bullish`)
return
}
console.log(` ✅ MAGAP: ${currentMAGap.toFixed(2)}%`)
logger.log(` ✅ MAGAP: ${currentMAGap.toFixed(2)}%`)
}
console.log(` ✅ All real-time validations passed - signal quality maintained`)
logger.log(` ✅ All real-time validations passed - signal quality maintained`)
} else {
console.log(` ⚠️ No fresh market data available - proceeding with original signal`)
logger.log(` ⚠️ No fresh market data available - proceeding with original signal`)
}
// All conditions met - execute!
console.log(`✅ Smart Entry: OPTIMAL ENTRY CONFIRMED`)
console.log(` Pullback: ${pullbackMagnitude.toFixed(2)}% (target ${signal.targetPullbackMin}-${signal.targetPullbackMax}%)`)
console.log(` Price improvement: $${signal.signalPrice.toFixed(2)}$${currentPrice.toFixed(2)}`)
logger.log(`✅ Smart Entry: OPTIMAL ENTRY CONFIRMED`)
logger.log(` Pullback: ${pullbackMagnitude.toFixed(2)}% (target ${signal.targetPullbackMin}-${signal.targetPullbackMax}%)`)
logger.log(` Price improvement: $${signal.signalPrice.toFixed(2)}$${currentPrice.toFixed(2)}`)
await this.executeSignal(signal, currentPrice, 'pullback_confirmed')
}
@@ -388,10 +389,10 @@ export class SmartEntryTimer {
const improvement = ((signal.signalPrice - entryPrice) / signal.signalPrice) * 100
const improvementDirection = signal.direction === 'long' ? improvement : -improvement
console.log(`🎯 Smart Entry: EXECUTING ${signal.direction.toUpperCase()} ${signal.symbol}`)
console.log(` Signal Price: $${signal.signalPrice.toFixed(2)}`)
console.log(` Entry Price: $${entryPrice.toFixed(2)}`)
console.log(` Improvement: ${improvementDirection >= 0 ? '+' : ''}${improvementDirection.toFixed(2)}%`)
logger.log(`🎯 Smart Entry: EXECUTING ${signal.direction.toUpperCase()} ${signal.symbol}`)
logger.log(` Signal Price: $${signal.signalPrice.toFixed(2)}`)
logger.log(` Entry Price: $${entryPrice.toFixed(2)}`)
logger.log(` Improvement: ${improvementDirection >= 0 ? '+' : ''}${improvementDirection.toFixed(2)}%`)
// Execute the actual trade through Drift
try {
@@ -423,7 +424,7 @@ export class SmartEntryTimer {
signal.qualityScore
)
console.log(` Opening position: $${positionSizeUSD.toFixed(2)} at ${leverage}x leverage`)
logger.log(` Opening position: $${positionSizeUSD.toFixed(2)} at ${leverage}x leverage`)
// Open position
const openResult = await openPosition({
@@ -439,7 +440,7 @@ export class SmartEntryTimer {
}
const fillPrice = openResult.fillPrice!
console.log(`✅ Smart Entry: Position opened at $${fillPrice.toFixed(2)}`)
logger.log(`✅ Smart Entry: Position opened at $${fillPrice.toFixed(2)}`)
// Calculate TP/SL prices
let tp1Percent = config.takeProfit1Percent
@@ -505,7 +506,7 @@ export class SmartEntryTimer {
if (exitRes.success) {
exitOrderSignatures = exitRes.signatures || []
console.log(`✅ Smart Entry: Exit orders placed - ${exitOrderSignatures.length} orders`)
logger.log(`✅ Smart Entry: Exit orders placed - ${exitOrderSignatures.length} orders`)
}
} catch (err) {
console.error(`❌ Smart Entry: Error placing exit orders:`, err)
@@ -551,7 +552,7 @@ export class SmartEntryTimer {
}
})
console.log(`💾 Smart Entry: Trade saved to database`)
logger.log(`💾 Smart Entry: Trade saved to database`)
} catch (dbError) {
console.error(`❌ Smart Entry: Failed to save trade:`, dbError)
const { logCriticalError } = await import('../utils/persistent-logger')
@@ -616,14 +617,14 @@ export class SmartEntryTimer {
}
await positionManager.addTrade(activeTrade)
console.log(`📊 Smart Entry: Added to Position Manager`)
logger.log(`📊 Smart Entry: Added to Position Manager`)
} catch (pmError) {
console.error(`❌ Smart Entry: Failed to add to Position Manager:`, pmError)
}
console.log(`✅ Smart Entry: Execution complete for ${signal.symbol}`)
console.log(` Entry improvement: ${improvementDirection >= 0 ? '+' : ''}${improvementDirection.toFixed(2)}%`)
console.log(` Estimated value: $${(Math.abs(improvementDirection) / 100 * positionSizeUSD).toFixed(2)}`)
logger.log(`✅ Smart Entry: Execution complete for ${signal.symbol}`)
logger.log(` Entry improvement: ${improvementDirection >= 0 ? '+' : ''}${improvementDirection.toFixed(2)}%`)
logger.log(` Estimated value: $${(Math.abs(improvementDirection) / 100 * positionSizeUSD).toFixed(2)}`)
} catch (error) {
console.error(`❌ Smart Entry: Execution error:`, error)
@@ -632,7 +633,7 @@ export class SmartEntryTimer {
// Remove from queue after brief delay (for logging)
setTimeout(() => {
this.queuedSignals.delete(signal.id)
console.log(`🗑️ Smart Entry: Cleaned up signal ${signal.id}`)
logger.log(`🗑️ Smart Entry: Cleaned up signal ${signal.id}`)
if (this.queuedSignals.size === 0) {
this.stopMonitoring()
@@ -688,7 +689,7 @@ export class SmartEntryTimer {
signal.status = 'cancelled'
this.queuedSignals.delete(signalId)
console.log(`🚫 Smart Entry: Cancelled signal ${signalId}`)
logger.log(`🚫 Smart Entry: Cancelled signal ${signalId}`)
return true
}
@@ -713,5 +714,5 @@ export function getSmartEntryTimer(): SmartEntryTimer {
export function startSmartEntryTracking(): void {
getSmartEntryTimer()
console.log('✅ Smart Entry Timer service initialized')
logger.log('✅ Smart Entry Timer service initialized')
}