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:
144
scripts/replace-console-logs.js
Executable file
144
scripts/replace-console-logs.js
Executable file
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Automated console.log replacement script
|
||||
* Replaces console.log → logger.log
|
||||
* Preserves console.error and console.warn
|
||||
* Adds logger import to files
|
||||
*/
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const { execSync } = require('child_process')
|
||||
|
||||
// Files to process (from grep analysis)
|
||||
const targetFiles = [
|
||||
'lib/trading/position-manager.ts',
|
||||
'lib/drift/orders.ts',
|
||||
'lib/database/trades.ts',
|
||||
'lib/trading/smart-entry-timer.ts',
|
||||
'lib/trading/signal-quality.ts',
|
||||
'lib/pyth/price-monitor.ts',
|
||||
'lib/drift/client.ts',
|
||||
'lib/startup/init-position-manager.ts',
|
||||
'lib/trading/market-data-cache.ts',
|
||||
'lib/analysis/blocked-signal-tracker.ts',
|
||||
'lib/trading/stop-hunt-tracker.ts',
|
||||
'lib/notifications/telegram.ts',
|
||||
'lib/trading/smart-validation-queue.ts',
|
||||
'lib/monitoring/drift-health-monitor.ts',
|
||||
'lib/database/client.ts',
|
||||
'lib/utils/persistent-logger.ts',
|
||||
'lib/drift/drift-service.ts',
|
||||
'lib/startup/index.ts'
|
||||
]
|
||||
|
||||
const loggerImport = "import { logger } from '../utils/logger'"
|
||||
const loggerImportAlt = "import { logger } from './utils/logger'" // For root level files
|
||||
|
||||
let totalReplacements = 0
|
||||
let filesModified = 0
|
||||
|
||||
function addLoggerImport(content, filePath) {
|
||||
// Skip if logger already imported
|
||||
if (content.includes("from '../utils/logger'") || content.includes("from './utils/logger'")) {
|
||||
return content
|
||||
}
|
||||
|
||||
// Determine correct import path based on file location
|
||||
const depth = filePath.split('/').length - 2 // Subtract 'lib/' and filename
|
||||
const importPath = depth === 1 ? './utils/logger' : '../'.repeat(depth - 1) + 'utils/logger'
|
||||
const importStatement = `import { logger } from '${importPath}'`
|
||||
|
||||
// Find first import statement and add logger import after it
|
||||
const lines = content.split('\n')
|
||||
let insertIndex = 0
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i].startsWith('import ')) {
|
||||
insertIndex = i + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If no imports found, add at top after any comments
|
||||
if (insertIndex === 0) {
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (!lines[i].trim().startsWith('//') && !lines[i].trim().startsWith('/*') && lines[i].trim() !== '') {
|
||||
insertIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lines.splice(insertIndex, 0, importStatement)
|
||||
return lines.join('\n')
|
||||
}
|
||||
|
||||
function replaceConsoleLogs(content) {
|
||||
let count = 0
|
||||
|
||||
// Replace console.log with logger.log
|
||||
// Match: console.log(...) but not console.error or console.warn
|
||||
const logRegex = /console\.log\(/g
|
||||
const matches = content.match(logRegex)
|
||||
if (matches) {
|
||||
count = matches.length
|
||||
content = content.replace(logRegex, 'logger.log(')
|
||||
}
|
||||
|
||||
// Replace console.info with logger.info
|
||||
const infoRegex = /console\.info\(/g
|
||||
const infoMatches = content.match(infoRegex)
|
||||
if (infoMatches) {
|
||||
count += infoMatches.length
|
||||
content = content.replace(infoRegex, 'logger.info(')
|
||||
}
|
||||
|
||||
// Keep console.error and console.warn as-is (already correct)
|
||||
|
||||
return { content, count }
|
||||
}
|
||||
|
||||
function processFile(filePath) {
|
||||
const fullPath = path.join(process.cwd(), filePath)
|
||||
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
console.log(`⚠️ File not found: ${filePath}`)
|
||||
return
|
||||
}
|
||||
|
||||
let content = fs.readFileSync(fullPath, 'utf8')
|
||||
const originalContent = content
|
||||
|
||||
// Add logger import
|
||||
content = addLoggerImport(content, filePath)
|
||||
|
||||
// Replace console.log statements
|
||||
const { content: newContent, count } = replaceConsoleLogs(content)
|
||||
|
||||
if (count > 0) {
|
||||
fs.writeFileSync(fullPath, newContent, 'utf8')
|
||||
console.log(`✅ ${filePath}: ${count} replacements`)
|
||||
totalReplacements += count
|
||||
filesModified++
|
||||
} else {
|
||||
console.log(`⏭️ ${filePath}: No console.log found`)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('🚀 Starting console.log replacement...\n')
|
||||
|
||||
targetFiles.forEach(processFile)
|
||||
|
||||
console.log('\n📊 Summary:')
|
||||
console.log(` Files modified: ${filesModified}`)
|
||||
console.log(` Total replacements: ${totalReplacements}`)
|
||||
console.log(` Estimated log reduction: ${Math.round((totalReplacements / 731) * 100)}%`)
|
||||
console.log('\n✅ Replacement complete!')
|
||||
console.log('\n📝 Next steps:')
|
||||
console.log(' 1. Review changes: git diff')
|
||||
console.log(' 2. Test build: npm run build')
|
||||
console.log(' 3. Update .env: NODE_ENV=production, DEBUG_LOGS=false')
|
||||
console.log(' 4. Rebuild Docker: docker compose build trading-bot')
|
||||
console.log(' 5. Deploy: docker compose up -d --force-recreate trading-bot')
|
||||
Reference in New Issue
Block a user