tinylink/core/http/dashboardRouter.js

80 lines
2.1 KiB
JavaScript
Raw Normal View History

const express = require('express');
const queue = require('../queue/queue');
const { renderDashboardPage } = require('./dashboard/page');
function toIsoFromEpochSeconds(epochSeconds) {
if (epochSeconds === null || epochSeconds === undefined) return null;
const value = Number(epochSeconds);
if (!Number.isFinite(value) || value <= 0) return null;
return new Date(value * 1000).toISOString();
}
function createDashboardRouter(connectors = []) {
const router = express.Router();
router.get('/', (req, res) => {
res.type('html').send(renderDashboardPage());
});
router.get('/api/summary', async (req, res) => {
const [pending, retrying, deadLetters, attempts, avgLatency] = await Promise.all([
queue.pendingCount(),
queue.retryingCount(),
queue.deadLetterCount(),
queue.getDeliveryAttempts(),
queue.getAverageLatency()
]);
res.json({
status: 'ok',
metrics: {
pending,
retrying,
deadLetters,
attempts,
avgLatency
}
});
});
router.get('/api/queue', async (req, res) => {
const limit = Number(req.query.limit || 20);
const rows = await queue.listOutbox({ limit });
res.json({
status: 'ok',
items: rows.map((row) => ({
...row,
next_attempt_at_iso: toIsoFromEpochSeconds(row.next_attempt_at)
}))
});
});
router.get('/api/instruments', async (req, res) => {
const items = connectors.map((connector) => {
const status = connector.health();
const address = status.comPort
|| status.port
|| [status.remoteAddress, status.remotePort].filter(Boolean).join(':')
|| '-';
return {
instrument_id: status.instrument_id || null,
connector: connector.type(),
status: status.status,
address
};
});
res.json({ status: 'ok', items });
});
router.get('/api/recent', async (req, res) => {
const limit = Number(req.query.limit || 20);
const items = await queue.listRecentDeliveryAttempts(limit);
res.json({ status: 'ok', items });
});
return router;
}
module.exports = { createDashboardRouter };