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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user