feat: initial Blocky widget for Homepage dashboard
Parses Blocky's /metrics (Prometheus text) endpoint to show: - Blocking status (Enabled/Disabled) - Blocked domains count (denylist entries) - Total queries served - Cache hit rate % No REST stats endpoint exists in Blocky, so the proxy handler fetches and parses the Prometheus text format directly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
cc34c22aa5
7 changed files with 227 additions and 0 deletions
38
src/widgets/blocky/proxy.js
Normal file
38
src/widgets/blocky/proxy.js
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import { httpProxy } from "utils/proxy/http";
|
||||
import getServiceWidget from "utils/service-helpers";
|
||||
import { formatApiCall } from "utils/proxy/api-helpers";
|
||||
import createLogger from "utils/logger";
|
||||
|
||||
const logger = createLogger("blocky");
|
||||
|
||||
function parseMetric(text, name) {
|
||||
// Matches bare metric or metric with labels: my_metric{label="x"} 1.0
|
||||
const re = new RegExp(`^${name}(?:{[^}]*})?\\s+([0-9.e+\\-]+)`, "m");
|
||||
const m = text.match(re);
|
||||
return m ? parseFloat(m[1]) : 0;
|
||||
}
|
||||
|
||||
export default async function blockyProxyHandler(req, res) {
|
||||
const { group, service } = req.query;
|
||||
const widget = await getServiceWidget(group, service);
|
||||
const url = formatApiCall("{url}/metrics", widget);
|
||||
|
||||
const [status, , data] = await httpProxy(url);
|
||||
|
||||
if (status !== 200) {
|
||||
logger.error("HTTP %d fetching Blocky metrics from %s", status, url);
|
||||
return res.status(status).json({ error: `HTTP ${status}` });
|
||||
}
|
||||
|
||||
const text = data.toString();
|
||||
const hits = parseMetric(text, "blocky_cache_hits_total");
|
||||
const misses = parseMetric(text, "blocky_cache_misses_total");
|
||||
const total = hits + misses;
|
||||
|
||||
return res.json({
|
||||
enabled: parseMetric(text, "blocky_blocking_enabled") === 1,
|
||||
denylistEntries: parseMetric(text, "blocky_denylist_cache_entries"),
|
||||
totalQueries: total,
|
||||
cacheHitRate: total > 0 ? (hits / total) * 100 : 0,
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue