fix(webhooks): Load collapsed by default, add webhook metrics to status panel
All checks were successful
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m8s
CI / Security audit (push) Successful in 1m28s
CI / Tests & coverage (push) Successful in 1m53s
Build and Push Docker Image / build (push) Successful in 35s

- Fixed webhooks section to load collapsed (content hidden, toggle arrow reset)
- Added webhook metrics card to status panel for admin users:
  - Shows Sonarr/Radarr enabled/disabled status
  - Shows events received and polls skipped counts
- Updated /api/dashboard/status endpoint to include webhook metrics
- Metrics are aggregated from all Sonarr/Radarr instances
This commit is contained in:
2026-05-19 21:24:28 +01:00
parent aeacadbe68
commit 2e85fae57a
2 changed files with 59 additions and 2 deletions

View File

@@ -782,6 +782,35 @@ router.get('/status', requireAuth, (req, res) => {
const cacheStats = cache.getStats();
const uptime = process.uptime();
// Get webhook metrics
const { getGlobalWebhookMetrics } = require('../utils/cache');
const webhookMetrics = getGlobalWebhookMetrics();
// Find Sonarr and Radarr metrics from instances
const sonarrMetrics = {};
const radarrMetrics = {};
for (const [url, metrics] of Object.entries(webhookMetrics.instances || {})) {
if (url.includes('sonarr')) {
sonarrMetrics[url] = metrics;
} else if (url.includes('radarr')) {
radarrMetrics[url] = metrics;
}
}
// Aggregate metrics for each service
const aggregateMetrics = (metricsMap) => {
const values = Object.values(metricsMap);
if (values.length === 0) return null;
return {
enabled: true,
eventsReceived: values.reduce((sum, m) => sum + (m.eventsReceived || 0), 0),
pollsSkipped: values.reduce((sum, m) => sum + (m.pollsSkipped || 0), 0),
lastEvent: values.reduce((latest, m) => {
return m.lastWebhookTimestamp > latest ? m.lastWebhookTimestamp : latest;
}, 0)
};
};
res.json({
server: {
uptimeSeconds: Math.floor(uptime),
@@ -796,7 +825,11 @@ router.get('/status', requireAuth, (req, res) => {
lastPoll: getLastPollTimings()
},
cache: cacheStats,
clients: getActiveClients()
clients: getActiveClients(),
webhooks: {
sonarr: aggregateMetrics(sonarrMetrics),
radarr: aggregateMetrics(radarrMetrics)
}
});
} catch (err) {
res.status(500).json({ error: 'Failed to get status', details: err.message });