Move middleware sources into core/, refresh config paths, and update design/user docs to reflect the raw payload pipeline.
95 lines
3.1 KiB
JavaScript
95 lines
3.1 KiB
JavaScript
const express = require('express');
|
|
const queue = require('./queue/queue');
|
|
const instrumentConfig = require('./config/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 };
|