refactor: replace console.log/error with structured logger across server
Migrate all server modules to use the centralized logger (lib/logger.ts) instead of raw console calls. Lint warnings reduced from 74 to 25. Remaining warnings are only no-floating-promises in game engine code. Files updated: orchestrator.ts, ranked-queue.ts, human-responses.ts, payments.ts, fight-loop.ts, app.ts, routes/payments.ts Files suppressed: logger.ts, fight-loop-cli.ts, migrate.ts (legitimate console use) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
1f532681df
commit
4cc18048e8
@@ -1,5 +1,6 @@
|
||||
import { z } from 'zod'
|
||||
import { nanoid } from 'nanoid'
|
||||
import { logger } from '../lib/logger.js'
|
||||
import { toError } from '../lib/utils.js'
|
||||
import { db, schema, sqlite } from '../db/index.js'
|
||||
import { eq, sql } from 'drizzle-orm'
|
||||
@@ -156,11 +157,11 @@ async function callWebhook(
|
||||
})
|
||||
|
||||
const start = Date.now()
|
||||
console.log(`[webhook] POST ${url} round=${roundNumber} type=${challenge.type}`)
|
||||
logger.info('webhook', `POST ${url} round=${roundNumber} type=${challenge.type}`)
|
||||
|
||||
// SSRF check
|
||||
if (!isAllowedWebhookUrl(url)) {
|
||||
console.log(`[webhook] ${url} BLOCKED (private/internal URL)`)
|
||||
logger.warn('webhook', `${url} BLOCKED (private/internal URL)`)
|
||||
return { answer: null, timeMs: 0, timedOut: false, error: true }
|
||||
}
|
||||
|
||||
@@ -179,7 +180,7 @@ async function callWebhook(
|
||||
const elapsed = Date.now() - start
|
||||
|
||||
if (!res.ok) {
|
||||
console.log(`[webhook] ${url} returned ${res.status} in ${elapsed}ms`)
|
||||
logger.warn('webhook', `${url} returned ${res.status} in ${elapsed}ms`)
|
||||
return { answer: null, timeMs: elapsed, timedOut: false, error: true }
|
||||
}
|
||||
|
||||
@@ -187,7 +188,7 @@ async function callWebhook(
|
||||
try {
|
||||
text = await readLimitedBody(res, MAX_RESPONSE_BYTES)
|
||||
} catch {
|
||||
console.log(`[webhook] ${url} response too large (>${MAX_RESPONSE_BYTES} bytes)`)
|
||||
logger.warn('webhook', `${url} response too large (>${MAX_RESPONSE_BYTES} bytes)`)
|
||||
return { answer: null, timeMs: elapsed, timedOut: false, error: true }
|
||||
}
|
||||
|
||||
@@ -195,13 +196,13 @@ async function callWebhook(
|
||||
try {
|
||||
parsed = JSON.parse(text)
|
||||
} catch {
|
||||
console.log(`[webhook] ${url} returned non-JSON in ${elapsed}ms: ${text.slice(0, 200)}`)
|
||||
logger.warn('webhook', `${url} returned non-JSON in ${elapsed}ms: ${text.slice(0, 200)}`)
|
||||
return { answer: null, timeMs: elapsed, timedOut: false, error: true }
|
||||
}
|
||||
|
||||
const data = webhookResponseSchema.safeParse(parsed)
|
||||
if (!data.success) {
|
||||
console.log(`[webhook] ${url} invalid response shape in ${elapsed}ms: ${data.error.message}`)
|
||||
logger.warn('webhook', `${url} invalid response shape in ${elapsed}ms: ${data.error.message}`)
|
||||
return { answer: null, timeMs: elapsed, timedOut: false, error: true }
|
||||
}
|
||||
|
||||
@@ -209,7 +210,7 @@ async function callWebhook(
|
||||
const answer = data.data.answer ? data.data.answer.slice(0, MAX_ANSWER_LENGTH) : null
|
||||
const trashTalk = data.data.trash_talk ? data.data.trash_talk.slice(0, MAX_TRASH_TALK_LENGTH) : undefined
|
||||
|
||||
console.log(`[webhook] ${url} OK in ${elapsed}ms answer=${(answer || '').slice(0, 80)}`)
|
||||
logger.info('webhook', `${url} OK in ${elapsed}ms answer=${(answer || '').slice(0, 80)}`)
|
||||
return {
|
||||
answer,
|
||||
trashTalk,
|
||||
@@ -220,7 +221,7 @@ async function callWebhook(
|
||||
} catch (err: unknown) {
|
||||
const elapsed = Date.now() - start
|
||||
const isAbort = err instanceof Error && err.name === 'AbortError'
|
||||
console.log(`[webhook] ${url} ${isAbort ? "TIMEOUT" : "ERROR"} in ${elapsed}ms: ${toError(err).message}`)
|
||||
logger.warn('webhook', `${url} ${isAbort ? "TIMEOUT" : "ERROR"} in ${elapsed}ms: ${toError(err).message}`)
|
||||
return {
|
||||
answer: null,
|
||||
timeMs: elapsed,
|
||||
@@ -243,7 +244,7 @@ async function getBotResponse(
|
||||
arena: Arena,
|
||||
): Promise<WebhookResponse> {
|
||||
if (isHumanPlayer(bot.webhookUrl)) {
|
||||
console.log(`[fight] ${bot.name} is human player, waiting for browser response`)
|
||||
logger.info('fight', `${bot.name} is human player, waiting for browser response`)
|
||||
emit(fightId, 'human_challenge', {
|
||||
botId: bot.id,
|
||||
round: roundNumber,
|
||||
@@ -260,7 +261,7 @@ async function getBotResponse(
|
||||
}
|
||||
|
||||
if (isClassicBot(bot.webhookUrl)) {
|
||||
console.log(`[fight] ${bot.name} is classic bot, generating response`)
|
||||
logger.info('fight', `${bot.name} is classic bot, generating response`)
|
||||
const classic = generateClassicBotResponse(challenge, bot.name)
|
||||
return {
|
||||
answer: classic.answer || null,
|
||||
@@ -272,7 +273,7 @@ async function getBotResponse(
|
||||
}
|
||||
|
||||
if (isMockBot(bot.webhookUrl)) {
|
||||
console.log(`[fight] ${bot.name} is mock bot, generating response`)
|
||||
logger.info('fight', `${bot.name} is mock bot, generating response`)
|
||||
const mock = generateMockBotResponse(challenge, bot.name)
|
||||
return {
|
||||
answer: mock.answer || null,
|
||||
@@ -282,7 +283,7 @@ async function getBotResponse(
|
||||
error: mock.error,
|
||||
}
|
||||
}
|
||||
console.log(`[fight] ${bot.name} has real webhook: ${bot.webhookUrl}`)
|
||||
logger.info('fight', `${bot.name} has real webhook: ${bot.webhookUrl}`)
|
||||
return callWebhook(bot.webhookUrl, challenge, roundNumber, fightId, opponent, arena)
|
||||
}
|
||||
|
||||
@@ -339,7 +340,7 @@ async function trackWebhookResult(botId: string, webhookUrl: string, succeeded:
|
||||
.from(schema.bots).where(eq(schema.bots.id, botId)).limit(1)
|
||||
if (bot[0] && bot[0].consecutiveErrors >= 5) {
|
||||
await db.update(schema.bots).set({ isActive: false }).where(eq(schema.bots.id, botId))
|
||||
console.log(`[fight] bot ${botId} auto-deactivated after 5 consecutive webhook errors`)
|
||||
logger.warn('fight', `bot ${botId} auto-deactivated after 5 consecutive webhook errors`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -568,7 +569,7 @@ async function executeFightRounds(fightId: string, botA: BotRecord, botB: BotRec
|
||||
winnerEloChange, loserEloChange,
|
||||
isPerfect: !!isPerfect, isKO, isUpset,
|
||||
totalRounds: lastRound, arena: arena.name,
|
||||
}).catch(err => console.warn('[nostr] publish failed:', err))
|
||||
}).catch(err => logger.warn('nostr', `publish failed: ${err}`))
|
||||
}
|
||||
|
||||
// Settle bets
|
||||
@@ -583,7 +584,7 @@ async function executeFightRounds(fightId: string, botA: BotRecord, botB: BotRec
|
||||
}).where(eq(schema.bets.id, s.betId)).run()
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`[betting] settlement failed for fight ${fightId}:`, err)
|
||||
logger.error('betting', `settlement failed for fight ${fightId}: ${err}`)
|
||||
}
|
||||
|
||||
// Ranked fight payout
|
||||
@@ -596,7 +597,7 @@ async function executeFightRounds(fightId: string, botA: BotRecord, botB: BotRec
|
||||
|
||||
if (humanBotId) {
|
||||
payWinner(fightId, humanBotId).catch(err => {
|
||||
console.error(`[payments] payout failed for fight ${fightId}:`, err)
|
||||
logger.error('payments', `payout failed for fight ${fightId}: ${err}`)
|
||||
})
|
||||
} else if (!winnerId) {
|
||||
// Draw — refund both entry fees
|
||||
@@ -604,7 +605,7 @@ async function executeFightRounds(fightId: string, botA: BotRecord, botB: BotRec
|
||||
.where(sql`${schema.payments.fightId} = ${fightId} AND ${schema.payments.direction} = 'in' AND ${schema.payments.status} = 'confirmed'`)
|
||||
for (const payment of entryPayments) {
|
||||
refundEntry(payment.id).catch(err => {
|
||||
console.error(`[payments] draw refund failed for ${payment.id}:`, err)
|
||||
logger.error('payments', `draw refund failed for ${payment.id}: ${err}`)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -651,7 +652,7 @@ export async function runFightAsync(botAId: string, botBId: string, mode: 'free'
|
||||
|
||||
executeFightRounds(fightId, botA, botB, arena, mode)
|
||||
.catch(err => {
|
||||
console.error(`[botfights] fight ${fightId} error:`, err)
|
||||
logger.error('fight', `fight ${fightId} error: ${err}`)
|
||||
// Mark fight as cancelled so it doesn't stay 'live' forever
|
||||
db.update(schema.fights).set({
|
||||
status: 'cancelled',
|
||||
|
||||
Reference in New Issue
Block a user