- 新增 Prometheus 指标端点 /metrics(HTTP + DB + 作业统计) - request.log 绑定 requestId/actorId,避免日志难追踪 - cron/pg-boss 作业增加 metrics 计数(runs/processed) - 更新 env/runbook/README 与 v3 CSV 状态推进
106 行
2.6 KiB
JavaScript
106 行
2.6 KiB
JavaScript
const client = require("prom-client");
|
|
|
|
function resolveRouteLabel(request) {
|
|
const url = request?.routeOptions?.url;
|
|
if (typeof url === "string" && url.trim()) {
|
|
return url;
|
|
}
|
|
|
|
const routerPath = request?.routerPath;
|
|
if (typeof routerPath === "string" && routerPath.trim()) {
|
|
return routerPath;
|
|
}
|
|
|
|
const rawUrl = request?.raw?.url;
|
|
if (typeof rawUrl === "string" && rawUrl.trim()) {
|
|
return rawUrl.split("?")[0];
|
|
}
|
|
|
|
return "unknown";
|
|
}
|
|
|
|
function initMetrics(app) {
|
|
const registry = new client.Registry();
|
|
|
|
client.collectDefaultMetrics({
|
|
register: registry,
|
|
});
|
|
|
|
const httpRequestsTotal = new client.Counter({
|
|
name: "hyb_http_requests_total",
|
|
help: "Total number of HTTP requests",
|
|
labelNames: ["method", "route", "status_code"],
|
|
registers: [registry],
|
|
});
|
|
|
|
const httpRequestDurationSeconds = new client.Histogram({
|
|
name: "hyb_http_request_duration_seconds",
|
|
help: "HTTP request duration in seconds",
|
|
labelNames: ["method", "route", "status_code"],
|
|
buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
|
|
registers: [registry],
|
|
});
|
|
|
|
const jobRunsTotal = new client.Counter({
|
|
name: "hyb_job_runs_total",
|
|
help: "Total number of background job runs",
|
|
labelNames: ["job", "driver", "outcome"],
|
|
registers: [registry],
|
|
});
|
|
|
|
const jobProcessedTotal = new client.Counter({
|
|
name: "hyb_job_processed_total",
|
|
help: "Total number of processed items per job",
|
|
labelNames: ["job", "driver", "kind"],
|
|
registers: [registry],
|
|
});
|
|
|
|
const dbReady = new client.Gauge({
|
|
name: "hyb_db_ready",
|
|
help: "Database readiness probe result (1=ready, 0=not ready)",
|
|
registers: [registry],
|
|
});
|
|
|
|
app.decorate("metrics", {
|
|
registry,
|
|
httpRequestsTotal,
|
|
httpRequestDurationSeconds,
|
|
jobRunsTotal,
|
|
jobProcessedTotal,
|
|
dbReady,
|
|
});
|
|
|
|
app.decorateRequest("metricsStart", null);
|
|
|
|
app.addHook("onRequest", async (request) => {
|
|
request.metricsStart = process.hrtime.bigint();
|
|
});
|
|
|
|
app.addHook("onResponse", async (request, reply) => {
|
|
const start = request.metricsStart;
|
|
if (typeof start !== "bigint") {
|
|
return;
|
|
}
|
|
|
|
const end = process.hrtime.bigint();
|
|
const durationSeconds = Number(end - start) / 1e9;
|
|
|
|
const method = request.method;
|
|
const route = resolveRouteLabel(request);
|
|
const statusCode = String(reply.statusCode);
|
|
|
|
httpRequestsTotal.inc({ method, route, status_code: statusCode });
|
|
httpRequestDurationSeconds.observe(
|
|
{ method, route, status_code: statusCode },
|
|
durationSeconds,
|
|
);
|
|
});
|
|
|
|
return app.metrics;
|
|
}
|
|
|
|
module.exports = {
|
|
initMetrics,
|
|
};
|
|
|