const express = require('express'); const queue = require('./queue'); const instrumentConfig = require('../domain/instrumentConfig'); function createHealthRouter(connectors = []) { const router = express.Router(); router.get('/', async (req, res) => { const connectorStatuses = connectors.map((connector) => connector.health()); const pending = await queue.pendingCount(); const retrying = await queue.retryingCount(); const deadLetters = await queue.deadLetterCount(); res.json({ status: 'ok', connectors: connectorStatuses, metrics: { pending, retrying, deadLetters } }); }); router.get('/ready', async (req, res) => { try { await queue.ping(); res.json({ status: 'ready' }); } catch (err) { res.status(503).json({ status: 'unready', reason: err.message }); } }); return router; } const instrumentRouter = express.Router(); instrumentRouter.get('/', async (req, res) => { res.json(instrumentConfig.list()); }); instrumentRouter.get('/:id', async (req, res) => { const entry = instrumentConfig.get(req.params.id); if (!entry) { return res.status(404).json({ error: 'not found' }); } res.json(entry); }); const metricsRouter = express.Router(); function formatMetric(name, value, type = 'gauge', help = '') { const lines = []; if (help) { lines.push(`# HELP ${name} ${help}`); } lines.push(`# TYPE ${name} ${type}`); lines.push(`${name} ${value}`); return lines.join('\n'); } metricsRouter.get('/', async (req, res) => { try { const pending = await queue.pendingCount(); const retrying = await queue.retryingCount(); const deadLetters = await queue.deadLetterCount(); const lastSuccess = await queue.getLastSuccessTimestamp(); const avgLatency = await queue.getAverageLatency(); const attempts = await queue.getDeliveryAttempts(); const timestamp = lastSuccess ? new Date(lastSuccess).getTime() / 1000 : 0; const metrics = [ formatMetric('workstation_pending_total', pending, 'gauge', 'Number of pending payloads'), formatMetric('workstation_retrying_total', retrying, 'gauge', 'Number of payloads currently retrying'), formatMetric('workstation_dead_letters_total', deadLetters, 'gauge', 'Total dead-lettered payloads'), formatMetric('workstation_delivery_attempts_total', attempts, 'counter', 'Total delivery attempts logged'), formatMetric('workstation_last_success_timestamp', timestamp, 'gauge', 'Epoch seconds of last successful delivery'), formatMetric('workstation_avg_latency_ms', Math.round(avgLatency), 'gauge', 'Average delivery latency in milliseconds') ]; res.set('content-type', 'text/plain; version=0.0.4; charset=utf-8'); res.send(metrics.join('\n')); } catch (error) { res.status(500).send('metrics unavailable'); } }); function createHttpServer(connectors) { const app = express(); app.use('/health', createHealthRouter(connectors)); app.use('/instruments', instrumentRouter); app.use('/metrics', metricsRouter); return app; } module.exports = { createHttpServer };