feat: añade métricas de grupos/usuarios y paneles en Grafana

Co-authored-by: aider (openrouter/openai/gpt-5.1) <aider@aider.chat>
main
borja 3 weeks ago
parent e890703035
commit 0816f8fa9e

@ -482,6 +482,388 @@
], ],
"title": "Oldest pending response age (s)", "title": "Oldest pending response age (s)",
"type": "stat" "type": "stat"
},
{
"collapsed": false,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 5
},
"id": 8,
"panels": [],
"title": "Groups & Users",
"type": "row"
},
{
"datasource": {
"type": "marcusolsson-json-datasource",
"uid": "bf43dd67r9slcd"
},
"fieldConfig": {
"defaults": {
"decimals": 0,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": 0
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 3,
"w": 4,
"x": 0,
"y": 6
},
"id": 9,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"percentChangeColorMode": "standard",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showPercentChange": false,
"text": {
"titleSize": 24
},
"textMode": "auto",
"wideLayout": true
},
"pluginVersion": "12.2.1",
"targets": [
{
"cacheDurationSeconds": 300,
"datasource": {
"type": "marcusolsson-json-datasource",
"uid": "bf43dd67r9slcd"
},
"fields": [
{
"jsonPath": "$.gauges.groups_total",
"name": "groups_total",
"type": "number"
}
],
"method": "GET",
"queryParams": "",
"refId": "A",
"urlPath": ""
}
],
"title": "Groups total (non-community)",
"type": "stat"
},
{
"datasource": {
"type": "marcusolsson-json-datasource",
"uid": "bf43dd67r9slcd"
},
"fieldConfig": {
"defaults": {
"decimals": 0,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 3,
"w": 4,
"x": 4,
"y": 6
},
"id": 10,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"percentChangeColorMode": "standard",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showPercentChange": false,
"text": {
"titleSize": 24
},
"textMode": "auto",
"wideLayout": true
},
"pluginVersion": "12.2.1",
"targets": [
{
"cacheDurationSeconds": 300,
"datasource": {
"type": "marcusolsson-json-datasource",
"uid": "bf43dd67r9slcd"
},
"fields": [
{
"jsonPath": "$.gauges.groups_active_total",
"name": "groups_active_total",
"type": "number"
}
],
"method": "GET",
"queryParams": "",
"refId": "A",
"urlPath": ""
}
],
"title": "Groups active",
"type": "stat"
},
{
"datasource": {
"type": "marcusolsson-json-datasource",
"uid": "bf43dd67r9slcd"
},
"fieldConfig": {
"defaults": {
"decimals": 0,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "gray",
"value": 0
},
{
"color": "orange",
"value": 1
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 3,
"w": 4,
"x": 8,
"y": 6
},
"id": 11,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"percentChangeColorMode": "standard",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showPercentChange": false,
"text": {
"titleSize": 24
},
"textMode": "auto",
"wideLayout": true
},
"pluginVersion": "12.2.1",
"targets": [
{
"cacheDurationSeconds": 300,
"datasource": {
"type": "marcusolsson-json-datasource",
"uid": "bf43dd67r9slcd"
},
"fields": [
{
"jsonPath": "$.gauges.groups_archived_total",
"name": "groups_archived_total",
"type": "number"
}
],
"method": "GET",
"queryParams": "",
"refId": "A",
"urlPath": ""
}
],
"title": "Groups archived",
"type": "stat"
},
{
"datasource": {
"type": "marcusolsson-json-datasource",
"uid": "bf43dd67r9slcd"
},
"fieldConfig": {
"defaults": {
"decimals": 0,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": 0
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 3,
"w": 4,
"x": 12,
"y": 6
},
"id": 12,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"percentChangeColorMode": "standard",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showPercentChange": false,
"text": {
"titleSize": 24
},
"textMode": "auto",
"wideLayout": true
},
"pluginVersion": "12.2.1",
"targets": [
{
"cacheDurationSeconds": 300,
"datasource": {
"type": "marcusolsson-json-datasource",
"uid": "bf43dd67r9slcd"
},
"fields": [
{
"jsonPath": "$.gauges.group_members_total",
"name": "group_members_total",
"type": "number"
}
],
"method": "GET",
"queryParams": "",
"refId": "A",
"urlPath": ""
}
],
"title": "Group members (active / active groups)",
"type": "stat"
},
{
"datasource": {
"type": "marcusolsson-json-datasource",
"uid": "bf43dd67r9slcd"
},
"fieldConfig": {
"defaults": {
"decimals": 0,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "purple",
"value": 0
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 3,
"w": 4,
"x": 16,
"y": 6
},
"id": 13,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"percentChangeColorMode": "standard",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showPercentChange": false,
"text": {
"titleSize": 24
},
"textMode": "auto",
"wideLayout": true
},
"pluginVersion": "12.2.1",
"targets": [
{
"cacheDurationSeconds": 300,
"datasource": {
"type": "marcusolsson-json-datasource",
"uid": "bf43dd67r9slcd"
},
"fields": [
{
"jsonPath": "$.gauges.users_total",
"name": "users_total",
"type": "number"
}
],
"method": "GET",
"queryParams": "",
"refId": "A",
"urlPath": ""
}
],
"title": "Users total",
"type": "stat"
} }
], ],
"preload": false, "preload": false,
@ -502,6 +884,6 @@
"timezone": "browser", "timezone": "browser",
"title": "Taskbot - Tasks & Queue (JSON API)", "title": "Taskbot - Tasks & Queue (JSON API)",
"uid": "taskbot-tasks-queue-json", "uid": "taskbot-tasks-queue-json",
"version": 1, "version": 2,
"weekStart": "monday" "weekStart": "monday"
} }

@ -28,6 +28,70 @@ export async function handleMetricsRequest(request: Request, db: Database): Prom
Metrics.set('allowed_groups_total_blocked', blocked); Metrics.set('allowed_groups_total_blocked', blocked);
} catch {} } catch {}
// Métricas de grupos y usuarios (gauges derivadas desde BD)
try {
// Grupos: totales, activos y archivados (siempre excluyendo comunidades)
const groupRow = db
.prepare(`
SELECT
COUNT(*) AS total,
SUM(
CASE
WHEN COALESCE(active, 0) = 1
AND COALESCE(archived, 0) = 0
THEN 1 ELSE 0
END
) AS active,
SUM(
CASE
WHEN COALESCE(archived, 0) = 1
THEN 1 ELSE 0
END
) AS archived
FROM groups
WHERE COALESCE(is_community, 0) = 0;
`)
.get() as any;
if (groupRow) {
const groupsTotal = Number(groupRow.total ?? 0);
const groupsActive = Number(groupRow.active ?? 0);
const groupsArchived = Number(groupRow.archived ?? 0);
Metrics.set('groups_total', groupsTotal);
Metrics.set('groups_active_total', groupsActive);
Metrics.set('groups_archived_total', groupsArchived);
}
// Miembros de grupos: solo miembros activos en grupos activos, no comunidad, no archivados
const gmRow = db
.prepare(`
SELECT COUNT(*) AS total
FROM group_members gm
JOIN groups g ON g.id = gm.group_id
WHERE gm.is_active = 1
AND COALESCE(g.active, 0) = 1
AND COALESCE(g.is_community, 0) = 0
AND COALESCE(g.archived, 0) = 0;
`)
.get() as any;
if (gmRow) {
const gmTotal = Number(gmRow.total ?? 0);
Metrics.set('group_members_total', gmTotal);
}
// Usuarios totales
const usersRow = db
.prepare(`SELECT COUNT(*) AS total FROM users;`)
.get() as any;
if (usersRow) {
const usersTotal = Number(usersRow.total ?? 0);
Metrics.set('users_total', usersTotal);
}
} catch {}
// Métricas de tareas (gauges derivadas desde BD) // Métricas de tareas (gauges derivadas desde BD)
try { try {
const row = db const row = db

Loading…
Cancel
Save