feat: structured logging with timestamps, request logging, and submission details (v0.4.6)
This commit is contained in:
parent
6bfd804313
commit
39ee1fe537
|
|
@ -19,9 +19,32 @@ if (!existsSync(dbDir)) {
|
||||||
try { chmodSync(dbDir, 0o755) } catch (e) {}
|
try { chmodSync(dbDir, 0o755) } catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Logger ---
|
||||||
|
const LOG_LEVELS = { error: 0, warn: 1, info: 2, debug: 3 }
|
||||||
|
const currentLevel = LOG_LEVELS[process.env.LOG_LEVEL?.toLowerCase()] ?? LOG_LEVELS.info
|
||||||
|
|
||||||
|
const log = {
|
||||||
|
info: (...args) => { if (currentLevel >= LOG_LEVELS.info) console.log(`[${new Date().toISOString()}] INFO `, ...args) },
|
||||||
|
warn: (...args) => { if (currentLevel >= LOG_LEVELS.warn) console.warn(`[${new Date().toISOString()}] WARN `, ...args) },
|
||||||
|
error: (...args) => { if (currentLevel >= LOG_LEVELS.error) console.error(`[${new Date().toISOString()}] ERROR`, ...args) },
|
||||||
|
debug: (...args) => { if (currentLevel >= LOG_LEVELS.debug) console.debug(`[${new Date().toISOString()}] DEBUG`, ...args) },
|
||||||
|
}
|
||||||
|
|
||||||
// Middleware
|
// Middleware
|
||||||
app.use(express.json({ limit: '1mb' }))
|
app.use(express.json({ limit: '1mb' }))
|
||||||
app.use(express.urlencoded({ extended: true, limit: '1mb' }))
|
app.use(express.urlencoded({ extended: true, limit: '1mb' }))
|
||||||
|
|
||||||
|
// Request logging middleware
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
const start = Date.now()
|
||||||
|
res.on('finish', () => {
|
||||||
|
const ms = Date.now() - start
|
||||||
|
const level = res.statusCode >= 500 ? 'error' : res.statusCode >= 400 ? 'warn' : 'info'
|
||||||
|
log[level](`${req.method} ${req.originalUrl} ${res.statusCode} ${ms}ms`)
|
||||||
|
})
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
|
||||||
app.use(express.static(path.join(__dirname, '../dist')))
|
app.use(express.static(path.join(__dirname, '../dist')))
|
||||||
|
|
||||||
// --- Database ---
|
// --- Database ---
|
||||||
|
|
@ -139,14 +162,14 @@ async function getZohoAccessToken() {
|
||||||
if (data.access_token) {
|
if (data.access_token) {
|
||||||
zohoAccessToken = data.access_token
|
zohoAccessToken = data.access_token
|
||||||
zohoTokenExpiry = Date.now() + (data.expires_in || 3600) * 1000
|
zohoTokenExpiry = Date.now() + (data.expires_in || 3600) * 1000
|
||||||
console.log('[Zoho] Access token acquired, expires in', data.expires_in || 3600, 'seconds')
|
log.info('[Zoho] Access token acquired, expires in', data.expires_in || 3600, 'seconds')
|
||||||
return zohoAccessToken
|
return zohoAccessToken
|
||||||
} else {
|
} else {
|
||||||
console.error('[Zoho] Token exchange failed:', JSON.stringify(data))
|
log.error('[Zoho] Token exchange failed:', JSON.stringify(data))
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[Zoho] Token acquisition error:', err.message)
|
log.error('[Zoho] Token acquisition error:', err.message)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +180,7 @@ async function forwardToZoho(leadData) {
|
||||||
try {
|
try {
|
||||||
const accessToken = await getZohoAccessToken()
|
const accessToken = await getZohoAccessToken()
|
||||||
if (!accessToken) {
|
if (!accessToken) {
|
||||||
console.error('[Zoho] No access token available, skipping lead forwarding')
|
log.warn('[Zoho] No access token available, skipping lead forwarding')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,13 +210,13 @@ async function forwardToZoho(leadData) {
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const result = await response.json()
|
const result = await response.json()
|
||||||
console.log('[Zoho] Lead forwarded successfully:', result.data?.[0]?.details?.id || 'no id returned')
|
log.info('[Zoho] Lead forwarded successfully:', result.data?.[0]?.details?.id || 'no id returned')
|
||||||
} else {
|
} else {
|
||||||
const text = await response.text()
|
const text = await response.text()
|
||||||
console.error(`[Zoho] Lead forwarding failed (${response.status}):`, text)
|
log.error(`[Zoho] Lead forwarding failed (${response.status}):`, text)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[Zoho] Forwarding error:', err.message)
|
log.error('[Zoho] Forwarding error:', err.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,7 +261,7 @@ app.post('/api/leads', (req, res) => {
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||||
`)
|
`)
|
||||||
|
|
||||||
stmt.run(
|
const result = stmt.run(
|
||||||
sanitized.company,
|
sanitized.company,
|
||||||
sanitized.name,
|
sanitized.name,
|
||||||
sanitized.email,
|
sanitized.email,
|
||||||
|
|
@ -248,12 +271,14 @@ app.post('/api/leads', (req, res) => {
|
||||||
sanitized.service_interest || null
|
sanitized.service_interest || null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
log.info(`Lead submitted: ${sanitized.email} from ${sanitized.company} (id: ${result.lastInsertRowid})`)
|
||||||
|
|
||||||
// Fire-and-forget Zoho forwarding (best-effort, non-blocking)
|
// Fire-and-forget Zoho forwarding (best-effort, non-blocking)
|
||||||
forwardToZoho(sanitized)
|
forwardToZoho(sanitized)
|
||||||
|
|
||||||
res.json({ success: true, message: 'Thanks! We\'ll be in touch shortly.' })
|
res.json({ success: true, message: 'Thanks! We\'ll be in touch shortly.' })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error submitting lead:', err)
|
log.error('Error submitting lead:', err)
|
||||||
res.status(500).json({ error: 'Failed to submit lead' })
|
res.status(500).json({ error: 'Failed to submit lead' })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -291,7 +316,7 @@ app.post('/api/support', (req, res) => {
|
||||||
VALUES (?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?)
|
||||||
`)
|
`)
|
||||||
|
|
||||||
stmt.run(
|
const result = stmt.run(
|
||||||
sanitized.name,
|
sanitized.name,
|
||||||
sanitized.company,
|
sanitized.company,
|
||||||
sanitized.email,
|
sanitized.email,
|
||||||
|
|
@ -300,9 +325,11 @@ app.post('/api/support', (req, res) => {
|
||||||
sanitized.priority || 'medium'
|
sanitized.priority || 'medium'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
log.info(`Support request submitted: ${sanitized.email} from ${sanitized.company} priority=${sanitized.priority || 'medium'} (id: ${result.lastInsertRowid})`)
|
||||||
|
|
||||||
res.json({ success: true, message: 'Thanks! We\'ll get back to you soon.' })
|
res.json({ success: true, message: 'Thanks! We\'ll get back to you soon.' })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error submitting support request:', err)
|
log.error('Error submitting support request:', err)
|
||||||
res.status(500).json({ error: 'Failed to submit support request' })
|
res.status(500).json({ error: 'Failed to submit support request' })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -311,6 +338,11 @@ app.post('/api/support', (req, res) => {
|
||||||
const PORT = process.env.SERVER_PORT || 3001
|
const PORT = process.env.SERVER_PORT || 3001
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`Server running on http://localhost:${PORT}`)
|
log.info(`Server running on http://localhost:${PORT}`)
|
||||||
console.log(`Health check: http://localhost:${PORT}/api/health`)
|
log.info(`Health check: http://localhost:${PORT}/api/health`)
|
||||||
|
if (ZOHO_ENABLED) {
|
||||||
|
log.info(`Zoho CRM forwarding: ENABLED (domain: ${ZOHO_API_DOMAIN})`)
|
||||||
|
} else {
|
||||||
|
log.info('Zoho CRM forwarding: DISABLED (set ZOHO_ENABLED=true to enable)')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue