Skip to content

Commit 112d182

Browse files
committed
chore(server): leveled logger, quiet per-event chatter in production
Add a minimal logger that filters by LOG_LEVEL (error|warn|info|debug, default info) and route per-connection lifecycle, per-broadcast counts and per-poll state diffs through logger.debug so they're silent in prod. Critical startup/shutdown lines stay at info; errors are unchanged. Document LOG_LEVEL in .env.example.
1 parent 79772c5 commit 112d182

5 files changed

Lines changed: 69 additions & 26 deletions

File tree

.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,8 @@ PORT=8080
2727
# unauthenticated rate limit. Generate a fine-grained read-only token; leave
2828
# blank to use anonymous requests (lower rate limit).
2929
GITHUB_TOKEN=
30+
31+
# Logging
32+
# error | warn | info (default) | debug.
33+
# At info, per-connection / per-broadcast / per-poll chatter is suppressed.
34+
LOG_LEVEL=info

server/lib/blockchain-monitor.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
NetworkStatsEvent
1313
} from './websocket-types'
1414
import { blockCache } from './cache'
15+
import { logger } from './logger'
1516

1617
export class BlockchainMonitor {
1718
private wsManager: WebSocketManager
@@ -47,24 +48,24 @@ export class BlockchainMonitor {
4748
})
4849
})
4950

50-
console.log('[BlockchainMonitor] Initialized with config:', this.config)
51+
logger.debug('[BlockchainMonitor] Initialized with config:', this.config)
5152
}
5253

5354
/**
5455
* Start monitoring blockchain for all configured networks
5556
*/
5657
async start(): Promise<void> {
5758
if (this.isRunning) {
58-
console.log('[BlockchainMonitor] Already running')
59+
logger.debug('[BlockchainMonitor] Already running')
5960
return
6061
}
6162

6263
if (!this.config.enabled) {
63-
console.log('[BlockchainMonitor] WebSocket disabled, not starting')
64+
logger.debug('[BlockchainMonitor] WebSocket disabled, not starting')
6465
return
6566
}
6667

67-
console.log('[BlockchainMonitor] Starting monitor...')
68+
logger.debug('[BlockchainMonitor] Starting monitor...')
6869
this.isRunning = true
6970

7071
// Initialize states for all networks
@@ -86,7 +87,7 @@ export class BlockchainMonitor {
8687
await this.pollAllNetworks()
8788
await this.pollNetworkStats()
8889

89-
console.log('[BlockchainMonitor] Monitor started successfully')
90+
logger.info('[BlockchainMonitor] Monitor started successfully')
9091
}
9192

9293
/**
@@ -97,7 +98,7 @@ export class BlockchainMonitor {
9798
return
9899
}
99100

100-
console.log('[BlockchainMonitor] Stopping monitor...')
101+
logger.debug('[BlockchainMonitor] Stopping monitor...')
101102
this.isRunning = false
102103

103104
if (this.pollInterval) {
@@ -110,15 +111,15 @@ export class BlockchainMonitor {
110111
this.statsInterval = null
111112
}
112113

113-
console.log('[BlockchainMonitor] Monitor stopped')
114+
logger.info('[BlockchainMonitor] Monitor stopped')
114115
}
115116

116117
/**
117118
* Initialize network state
118119
*/
119120
private async initializeNetworkState(network: NetworkType): Promise<void> {
120121
try {
121-
console.log(`[BlockchainMonitor] Initializing ${network} state...`)
122+
logger.debug(`[BlockchainMonitor] Initializing ${network} state...`)
122123

123124
const blockCount = await blockCache.getBlockCount(network)
124125
const block = await blockCache.getBlock(blockCount, network, true)
@@ -133,7 +134,7 @@ export class BlockchainMonitor {
133134
state.lastUpdate = new Date()
134135
}
135136

136-
console.log(`[BlockchainMonitor] ${network} initialized: Block ${blockCount}`)
137+
logger.debug(`[BlockchainMonitor] ${network} initialized: Block ${blockCount}`)
137138
} catch (error) {
138139
console.error(`[BlockchainMonitor] Error initializing ${network}:`, error)
139140
}
@@ -162,7 +163,7 @@ export class BlockchainMonitor {
162163
const newBlockCount = await blockCache.getBlockCount(network)
163164

164165
if (newBlockCount > state.blockHeight) {
165-
console.log(`[BlockchainMonitor] ${network}: New blocks detected (${state.blockHeight} -> ${newBlockCount})`)
166+
logger.debug(`[BlockchainMonitor] ${network}: New blocks detected (${state.blockHeight} -> ${newBlockCount})`)
166167

167168
// Fetch new blocks
168169
for (let height = state.blockHeight + 1; height <= newBlockCount; height++) {
@@ -207,7 +208,7 @@ export class BlockchainMonitor {
207208
state.blockHash = block.hash
208209
}
209210

210-
console.log(`[BlockchainMonitor] ${network}: Broadcasting new block ${height} (${block.hash})`)
211+
logger.debug(`[BlockchainMonitor] ${network}: Broadcasting new block ${height} (${block.hash})`)
211212

212213
// Broadcast new block event
213214
const newBlockEvent: NewBlockEvent = {
@@ -249,7 +250,7 @@ export class BlockchainMonitor {
249250
mempoolInfo &&
250251
(mempoolInfo.size !== state.mempoolSize || mempoolInfo.bytes !== state.mempoolBytes)
251252
) {
252-
console.log(`[BlockchainMonitor] ${network}: Mempool changed (${state.mempoolSize} -> ${mempoolInfo.size} tx)`)
253+
logger.debug(`[BlockchainMonitor] ${network}: Mempool changed (${state.mempoolSize} -> ${mempoolInfo.size} tx)`)
253254

254255
state.mempoolSize = mempoolInfo.size
255256
state.mempoolBytes = mempoolInfo.bytes
@@ -326,7 +327,7 @@ export class BlockchainMonitor {
326327
}
327328
this.wsManager.broadcast(statsEvent, network)
328329

329-
console.log(`[BlockchainMonitor] ${network}: Broadcasted network stats update`)
330+
logger.debug(`[BlockchainMonitor] ${network}: Broadcasted network stats update`)
330331
}
331332
} catch (error) {
332333
console.error(`[BlockchainMonitor] Error polling network stats for ${network}:`, error)

server/lib/logger.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Minimal log-level filter so debug-level chatter (per-connection lifecycle,
2+
// per-broadcast counts, per-poll state diffs) is silent in production by
3+
// default but can be re-enabled via LOG_LEVEL=debug.
4+
//
5+
// Levels follow the standard ordering: error > warn > info > debug. Setting
6+
// LOG_LEVEL=info (the default) drops anything tagged 'debug'.
7+
8+
type Level = 'error' | 'warn' | 'info' | 'debug'
9+
10+
const LEVELS: Record<Level, number> = { error: 0, warn: 1, info: 2, debug: 3 }
11+
12+
function resolveLevel(): Level {
13+
const raw = (process.env.LOG_LEVEL ?? 'info').toLowerCase()
14+
return raw in LEVELS ? (raw as Level) : 'info'
15+
}
16+
17+
const active = LEVELS[resolveLevel()]
18+
19+
function emit(level: Level, args: unknown[]): void {
20+
if (LEVELS[level] > active) return
21+
// Route through the matching console method so structured log collectors
22+
// (DO/Render/Vercel) keep their colouring and severity routing.
23+
const fn =
24+
level === 'error' ? console.error :
25+
level === 'warn' ? console.warn :
26+
console.log
27+
fn(...args)
28+
}
29+
30+
export const logger = {
31+
error: (...args: unknown[]) => emit('error', args),
32+
warn: (...args: unknown[]) => emit('warn', args),
33+
info: (...args: unknown[]) => emit('info', args),
34+
debug: (...args: unknown[]) => emit('debug', args),
35+
}

server/lib/websocket-handler.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
SubscribeEvent,
1313
UnsubscribeEvent
1414
} from './websocket-types'
15+
import { logger } from './logger'
1516

1617
// Initialize WebSocket manager and blockchain monitor
1718
const wsManager = getWebSocketManager({
@@ -36,7 +37,7 @@ const blockchainMonitor = getBlockchainMonitor(wsManager, {
3637
// Start blockchain monitor once at module load (this module is evaluated a
3738
// single time via the lazy import in server/index.ts).
3839
blockchainMonitor.start().then(() => {
39-
console.log('[WebSocketHandler] Blockchain monitor started')
40+
logger.info('[WebSocketHandler] Blockchain monitor started')
4041
}).catch(error => {
4142
console.error('[WebSocketHandler] Failed to start blockchain monitor:', error)
4243
})
@@ -53,7 +54,7 @@ export function handleConnection(ws: WebSocket, request: unknown, ip?: string):
5354
// Register connection
5455
connectionId = wsManager.register(ws, currentNetwork, ip)
5556

56-
console.log(`[WebSocketHandler] New connection: ${connectionId} from ${ip || 'unknown'}`)
57+
logger.debug(`[WebSocketHandler] New connection: ${connectionId} from ${ip || 'unknown'}`)
5758

5859
// Send welcome message
5960
const welcomeEvent: WebSocketEvent = {
@@ -83,7 +84,7 @@ export function handleConnection(ws: WebSocket, request: unknown, ip?: string):
8384

8485
// Handle connection close
8586
ws.on('close', (code: number, reason: Buffer) => {
86-
console.log(`[WebSocketHandler] Connection closed: ${connectionId} (${code}: ${reason.toString()})`)
87+
logger.debug(`[WebSocketHandler] Connection closed: ${connectionId} (${code}: ${reason.toString()})`)
8788
if (connectionId) {
8889
wsManager.unregister(connectionId)
8990
}
@@ -257,7 +258,7 @@ function startHeartbeat(ws: WebSocket, connectionId: string): void {
257258
* Shutdown handler
258259
*/
259260
export function shutdown(): void {
260-
console.log('[WebSocketHandler] Shutting down...')
261+
logger.info('[WebSocketHandler] Shutting down...')
261262
shutdownBlockchainMonitor()
262263
shutdownWebSocketManager()
263264
}

server/lib/websocket-manager.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
WebSocketManagerConfig,
99
ServerMessage
1010
} from './websocket-types'
11+
import { logger } from './logger'
1112

1213
export class WebSocketManager {
1314
private connections: Map<string, ConnectionInfo>
@@ -69,7 +70,7 @@ export class WebSocketManager {
6970
this.connectionsByIP.get(ip)?.add(connectionId)
7071
}
7172

72-
console.log(`[WebSocketManager] Registered connection ${connectionId} for ${network} (Total: ${this.connections.size})`)
73+
logger.debug(`[WebSocketManager] Registered connection ${connectionId} for ${network} (Total: ${this.connections.size})`)
7374

7475
return connectionId
7576
}
@@ -100,7 +101,7 @@ export class WebSocketManager {
100101
// Remove main connection
101102
this.connections.delete(connectionId)
102103

103-
console.log(`[WebSocketManager] Unregistered connection ${connectionId} (Remaining: ${this.connections.size})`)
104+
logger.debug(`[WebSocketManager] Unregistered connection ${connectionId} (Remaining: ${this.connections.size})`)
104105

105106
return true
106107
}
@@ -134,7 +135,7 @@ export class WebSocketManager {
134135
events.forEach(event => connection.subscribedEvents.add(event))
135136
this.updateActivity(connectionId)
136137

137-
console.log(`[WebSocketManager] Connection ${connectionId} subscribed to:`, events)
138+
logger.debug(`[WebSocketManager] Connection ${connectionId} subscribed to:`, events)
138139

139140
return true
140141
}
@@ -172,7 +173,7 @@ export class WebSocketManager {
172173

173174
this.updateActivity(connectionId)
174175

175-
console.log(`[WebSocketManager] Connection ${connectionId} switched to ${newNetwork}`)
176+
logger.debug(`[WebSocketManager] Connection ${connectionId} switched to ${newNetwork}`)
176177

177178
return true
178179
}
@@ -200,7 +201,7 @@ export class WebSocketManager {
200201
})
201202

202203
if (sentCount > 0) {
203-
console.log(`[WebSocketManager] Broadcasted ${event.type} to ${sentCount} connections`)
204+
logger.debug(`[WebSocketManager] Broadcasted ${event.type} to ${sentCount} connections`)
204205
}
205206

206207
return sentCount
@@ -313,7 +314,7 @@ export class WebSocketManager {
313314
inactiveConnections.forEach(id => {
314315
const connection = this.connections.get(id)
315316
if (connection) {
316-
console.log(`[WebSocketManager] Closing inactive connection ${id}`)
317+
logger.debug(`[WebSocketManager] Closing inactive connection ${id}`)
317318
try {
318319
connection.socket.close()
319320
} catch (error) {
@@ -324,15 +325,15 @@ export class WebSocketManager {
324325
})
325326

326327
if (inactiveConnections.length > 0) {
327-
console.log(`[WebSocketManager] Cleaned up ${inactiveConnections.length} inactive connections`)
328+
logger.debug(`[WebSocketManager] Cleaned up ${inactiveConnections.length} inactive connections`)
328329
}
329330
}
330331

331332
/**
332333
* Shutdown manager and close all connections
333334
*/
334335
shutdown(): void {
335-
console.log(`[WebSocketManager] Shutting down (${this.connections.size} active connections)`)
336+
logger.info(`[WebSocketManager] Shutting down (${this.connections.size} active connections)`)
336337

337338
// Clear cleanup interval
338339
if (this.cleanupInterval) {
@@ -354,7 +355,7 @@ export class WebSocketManager {
354355
this.connectionsByIP.clear()
355356
this.connectionsByNetwork.clear()
356357

357-
console.log('[WebSocketManager] Shutdown complete')
358+
logger.info('[WebSocketManager] Shutdown complete')
358359
}
359360
}
360361

0 commit comments

Comments
 (0)