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:
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
import { getPrismaClient } from '../database/trades'
|
||||
import { logger } from '../utils/logger'
|
||||
import { initializeDriftService } from '../drift/client'
|
||||
import { getPythPriceMonitor } from '../pyth/price-monitor'
|
||||
|
||||
@@ -70,7 +71,7 @@ export class StopHuntTracker {
|
||||
}): Promise<void> {
|
||||
// Only track quality 85+ stop-outs (high-confidence trades)
|
||||
if (params.originalQualityScore < 85) {
|
||||
console.log(`⚠️ Stop hunt not tracked: Quality ${params.originalQualityScore} < 85 threshold`)
|
||||
logger.log(`⚠️ Stop hunt not tracked: Quality ${params.originalQualityScore} < 85 threshold`)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -93,9 +94,9 @@ export class StopHuntTracker {
|
||||
}
|
||||
})
|
||||
|
||||
console.log(`🎯 STOP HUNT RECORDED: ${params.symbol} ${params.direction.toUpperCase()}`)
|
||||
console.log(` Quality: ${params.originalQualityScore}, Loss: $${params.stopLossAmount.toFixed(2)}`)
|
||||
console.log(` Revenge window: 4 hours (expires ${revengeExpiresAt.toLocaleTimeString()})`)
|
||||
logger.log(`🎯 STOP HUNT RECORDED: ${params.symbol} ${params.direction.toUpperCase()}`)
|
||||
logger.log(` Quality: ${params.originalQualityScore}, Loss: $${params.stopLossAmount.toFixed(2)}`)
|
||||
logger.log(` Revenge window: 4 hours (expires ${revengeExpiresAt.toLocaleTimeString()})`)
|
||||
|
||||
// Start monitoring if not already running
|
||||
if (!this.isMonitoring) {
|
||||
@@ -113,7 +114,7 @@ export class StopHuntTracker {
|
||||
if (this.isMonitoring) return
|
||||
|
||||
this.isMonitoring = true
|
||||
console.log('🔍 Stop Hunt Revenge Tracker: Monitoring started')
|
||||
logger.log('🔍 Stop Hunt Revenge Tracker: Monitoring started')
|
||||
|
||||
// Check every 30 seconds
|
||||
monitoringInterval = setInterval(async () => {
|
||||
@@ -130,7 +131,7 @@ export class StopHuntTracker {
|
||||
monitoringInterval = null
|
||||
}
|
||||
this.isMonitoring = false
|
||||
console.log('🛑 Stop Hunt Revenge Tracker: Monitoring stopped')
|
||||
logger.log('🛑 Stop Hunt Revenge Tracker: Monitoring stopped')
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,13 +153,13 @@ export class StopHuntTracker {
|
||||
if (activeStopHunts.length === 0) {
|
||||
// No active stop hunts, stop monitoring to save resources
|
||||
if (this.isMonitoring) {
|
||||
console.log('📊 No active stop hunts - pausing monitoring')
|
||||
logger.log('📊 No active stop hunts - pausing monitoring')
|
||||
this.stopMonitoring()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
console.log(`🔍 Checking ${activeStopHunts.length} active stop hunt(s)...`)
|
||||
logger.log(`🔍 Checking ${activeStopHunts.length} active stop hunt(s)...`)
|
||||
|
||||
for (const stopHunt of activeStopHunts) {
|
||||
await this.checkStopHunt(stopHunt as StopHuntRecord)
|
||||
@@ -211,7 +212,7 @@ export class StopHuntTracker {
|
||||
const shouldRevenge = await this.shouldExecuteRevenge(stopHunt, currentPrice)
|
||||
|
||||
if (shouldRevenge) {
|
||||
console.log(`🔥 REVENGE CONDITIONS MET: ${stopHunt.symbol} ${stopHunt.direction.toUpperCase()}`)
|
||||
logger.log(`🔥 REVENGE CONDITIONS MET: ${stopHunt.symbol} ${stopHunt.direction.toUpperCase()}`)
|
||||
await this.executeRevengeTrade(stopHunt, currentPrice)
|
||||
}
|
||||
|
||||
@@ -260,7 +261,7 @@ export class StopHuntTracker {
|
||||
lowestInZone: currentPrice,
|
||||
}
|
||||
})
|
||||
console.log(` ⏱️ LONG revenge zone entered at ${currentPrice.toFixed(2)}, waiting for 90s confirmation...`)
|
||||
logger.log(` ⏱️ LONG revenge zone entered at ${currentPrice.toFixed(2)}, waiting for 90s confirmation...`)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -274,17 +275,17 @@ export class StopHuntTracker {
|
||||
// Check if we've been in zone for 90+ seconds (1.5 minutes)
|
||||
const timeInZone = now - stopHunt.firstCrossTime.getTime()
|
||||
if (timeInZone >= 90000) { // 90 seconds = 1.5 minutes
|
||||
console.log(` ✅ LONG revenge: Price held below entry for ${(timeInZone/60000).toFixed(1)}min, confirmed!`)
|
||||
console.log(` Entry ${originalEntryPrice.toFixed(2)} → Current ${currentPrice.toFixed(2)}`)
|
||||
logger.log(` ✅ LONG revenge: Price held below entry for ${(timeInZone/60000).toFixed(1)}min, confirmed!`)
|
||||
logger.log(` Entry ${originalEntryPrice.toFixed(2)} → Current ${currentPrice.toFixed(2)}`)
|
||||
return true
|
||||
} else {
|
||||
console.log(` ⏱️ LONG revenge: ${(timeInZone/60000).toFixed(1)}min in zone (need 1.5min)`)
|
||||
logger.log(` ⏱️ LONG revenge: ${(timeInZone/60000).toFixed(1)}min in zone (need 1.5min)`)
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
// Price left revenge zone - reset timer and increment counter
|
||||
if (stopHunt.firstCrossTime) {
|
||||
console.log(` ❌ LONG revenge: Price bounced back up to ${currentPrice.toFixed(2)}, resetting timer`)
|
||||
logger.log(` ❌ LONG revenge: Price bounced back up to ${currentPrice.toFixed(2)}, resetting timer`)
|
||||
await this.prisma.stopHunt.update({
|
||||
where: { id: stopHunt.id },
|
||||
data: {
|
||||
@@ -310,7 +311,7 @@ export class StopHuntTracker {
|
||||
highestInZone: currentPrice,
|
||||
}
|
||||
})
|
||||
console.log(` ⏱️ SHORT revenge zone entered at ${currentPrice.toFixed(2)}, waiting for 90s confirmation...`)
|
||||
logger.log(` ⏱️ SHORT revenge zone entered at ${currentPrice.toFixed(2)}, waiting for 90s confirmation...`)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -324,17 +325,17 @@ export class StopHuntTracker {
|
||||
// Check if we've been in zone for 90+ seconds (1.5 minutes)
|
||||
const timeInZone = now - stopHunt.firstCrossTime.getTime()
|
||||
if (timeInZone >= 90000) { // 90 seconds = 1.5 minutes
|
||||
console.log(` ✅ SHORT revenge: Price held above entry for ${(timeInZone/60000).toFixed(1)}min, confirmed!`)
|
||||
console.log(` Entry ${originalEntryPrice.toFixed(2)} → Current ${currentPrice.toFixed(2)}`)
|
||||
logger.log(` ✅ SHORT revenge: Price held above entry for ${(timeInZone/60000).toFixed(1)}min, confirmed!`)
|
||||
logger.log(` Entry ${originalEntryPrice.toFixed(2)} → Current ${currentPrice.toFixed(2)}`)
|
||||
return true
|
||||
} else {
|
||||
console.log(` ⏱️ SHORT revenge: ${(timeInZone/60000).toFixed(1)}min in zone (need 1.5min)`)
|
||||
logger.log(` ⏱️ SHORT revenge: ${(timeInZone/60000).toFixed(1)}min in zone (need 1.5min)`)
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
// Price left revenge zone - reset timer and increment counter
|
||||
if (stopHunt.firstCrossTime) {
|
||||
console.log(` ❌ SHORT revenge: Price dropped back to ${currentPrice.toFixed(2)}, resetting timer`)
|
||||
logger.log(` ❌ SHORT revenge: Price dropped back to ${currentPrice.toFixed(2)}, resetting timer`)
|
||||
await this.prisma.stopHunt.update({
|
||||
where: { id: stopHunt.id },
|
||||
data: {
|
||||
@@ -354,9 +355,9 @@ export class StopHuntTracker {
|
||||
*/
|
||||
private async executeRevengeTrade(stopHunt: StopHuntRecord, currentPrice: number): Promise<void> {
|
||||
try {
|
||||
console.log(`🔥 EXECUTING REVENGE TRADE: ${stopHunt.symbol} ${stopHunt.direction.toUpperCase()}`)
|
||||
console.log(` Original loss: $${stopHunt.stopLossAmount.toFixed(2)}`)
|
||||
console.log(` Revenge size: 1.2x (getting our money back!)`)
|
||||
logger.log(`🔥 EXECUTING REVENGE TRADE: ${stopHunt.symbol} ${stopHunt.direction.toUpperCase()}`)
|
||||
logger.log(` Original loss: $${stopHunt.stopLossAmount.toFixed(2)}`)
|
||||
logger.log(` Revenge size: 1.2x (getting our money back!)`)
|
||||
|
||||
// CRITICAL: Validate current ADX from 1-minute data cache
|
||||
// Block revenge if trend has weakened (ADX < 20)
|
||||
@@ -368,10 +369,10 @@ export class StopHuntTracker {
|
||||
const currentADX = cachedData.adx
|
||||
const dataAge = Date.now() - cachedData.timestamp
|
||||
|
||||
console.log(` 📊 Fresh ADX check: ${currentADX.toFixed(1)} (${(dataAge/1000).toFixed(0)}s old)`)
|
||||
logger.log(` 📊 Fresh ADX check: ${currentADX.toFixed(1)} (${(dataAge/1000).toFixed(0)}s old)`)
|
||||
|
||||
if (currentADX < 20) {
|
||||
console.log(` ❌ REVENGE BLOCKED: ADX ${currentADX.toFixed(1)} < 20 (weak trend, not worth re-entry)`)
|
||||
logger.log(` ❌ REVENGE BLOCKED: ADX ${currentADX.toFixed(1)} < 20 (weak trend, not worth re-entry)`)
|
||||
|
||||
// Update database with failed reason
|
||||
await this.prisma.stopHunt.update({
|
||||
@@ -397,10 +398,10 @@ export class StopHuntTracker {
|
||||
return
|
||||
}
|
||||
|
||||
console.log(` ✅ ADX validation passed: ${currentADX.toFixed(1)} ≥ 20 (strong trend)`)
|
||||
logger.log(` ✅ ADX validation passed: ${currentADX.toFixed(1)} ≥ 20 (strong trend)`)
|
||||
} else {
|
||||
console.log(` ⚠️ No fresh ADX data (cache age: ${cachedData ? (Date.now() - cachedData.timestamp)/1000 : 'N/A'}s)`)
|
||||
console.log(` ⚠️ Proceeding with revenge but using original ADX ${stopHunt.originalADX}`)
|
||||
logger.log(` ⚠️ No fresh ADX data (cache age: ${cachedData ? (Date.now() - cachedData.timestamp)/1000 : 'N/A'}s)`)
|
||||
logger.log(` ⚠️ Proceeding with revenge but using original ADX ${stopHunt.originalADX}`)
|
||||
}
|
||||
|
||||
// Call execute endpoint with revenge parameters
|
||||
@@ -454,9 +455,9 @@ export class StopHuntTracker {
|
||||
}
|
||||
})
|
||||
|
||||
console.log(`✅ REVENGE TRADE EXECUTED: ${result.trade?.id}`)
|
||||
console.log(`📊 SL Distance: $${Math.abs(slDistance).toFixed(2)} (${stopHunt.originalATR ? `${(Math.abs(slDistance) / stopHunt.originalATR).toFixed(2)}× ATR` : 'no ATR'})`)
|
||||
console.log(`🔥 LET'S GET OUR MONEY BACK!`)
|
||||
logger.log(`✅ REVENGE TRADE EXECUTED: ${result.trade?.id}`)
|
||||
logger.log(`📊 SL Distance: $${Math.abs(slDistance).toFixed(2)} (${stopHunt.originalATR ? `${(Math.abs(slDistance) / stopHunt.originalATR).toFixed(2)}× ATR` : 'no ATR'})`)
|
||||
logger.log(`🔥 LET'S GET OUR MONEY BACK!`)
|
||||
|
||||
// Send special Telegram notification
|
||||
await this.sendRevengeNotification(stopHunt, result.trade)
|
||||
@@ -524,7 +525,7 @@ Reversal Confirmed: Price crossed back through entry
|
||||
})
|
||||
|
||||
if (!stopHunt) {
|
||||
console.log(`⚠️ No stop hunt found for revenge trade ${params.revengeTradeId}`)
|
||||
logger.log(`⚠️ No stop hunt found for revenge trade ${params.revengeTradeId}`)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -538,10 +539,10 @@ Reversal Confirmed: Price crossed back through entry
|
||||
})
|
||||
|
||||
const emoji = params.outcome.includes('TP') ? '✅' : '❌'
|
||||
console.log(`${emoji} REVENGE OUTCOME: ${params.outcome} (${params.pnl >= 0 ? '+' : ''}$${params.pnl.toFixed(2)})`)
|
||||
logger.log(`${emoji} REVENGE OUTCOME: ${params.outcome} (${params.pnl >= 0 ? '+' : ''}$${params.pnl.toFixed(2)})`)
|
||||
|
||||
if (params.failedReason) {
|
||||
console.log(` Reason: ${params.failedReason}`)
|
||||
logger.log(` Reason: ${params.failedReason}`)
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
@@ -568,7 +569,7 @@ Reversal Confirmed: Price crossed back through entry
|
||||
})
|
||||
|
||||
if (expired.count > 0) {
|
||||
console.log(`⏰ Expired ${expired.count} stop hunt revenge window(s)`)
|
||||
logger.log(`⏰ Expired ${expired.count} stop hunt revenge window(s)`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Error expiring stop hunts:', error)
|
||||
@@ -605,10 +606,10 @@ export async function startStopHuntTracking(): Promise<void> {
|
||||
})
|
||||
|
||||
if (activeCount > 0) {
|
||||
console.log(`🎯 Found ${activeCount} active stop hunt(s) - starting revenge tracker`)
|
||||
logger.log(`🎯 Found ${activeCount} active stop hunt(s) - starting revenge tracker`)
|
||||
tracker.startMonitoring()
|
||||
} else {
|
||||
console.log('📊 No active stop hunts - tracker will start when needed')
|
||||
logger.log('📊 No active stop hunts - tracker will start when needed')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Error starting stop hunt tracker:', error)
|
||||
|
||||
Reference in New Issue
Block a user