refactor: update metrics endpoint to return pending monitor count for KEDA autoscaling

This commit is contained in:
Nawaz Dhandala
2025-12-28 13:33:52 +00:00
parent 694f20f231
commit 3311e9d354
2 changed files with 77 additions and 12 deletions

View File

@@ -19,6 +19,7 @@ import ProxyConfig from "../Utils/ProxyConfig";
const router: ExpressRouter = Express.getRouter();
// Metrics endpoint for Keda autoscaling
// Returns the number of monitors pending to be probed by this probe
router.get(
"/queue-size",
async (
@@ -28,11 +29,14 @@ router.get(
): Promise<void> => {
try {
// Get the pending monitor count for this specific probe from ProbeIngest API
const queueSizeUrl: URL = URL.fromString(
// This is the correct metric - the number of monitors waiting to be probed
const pendingMonitorsUrl: URL = URL.fromString(
PROBE_INGEST_URL.toString(),
).addRoute("/metrics/queue-size");
).addRoute("/monitor/pending-count");
logger.debug("Fetching queue size from ProbeIngest API");
logger.debug(
"Fetching pending monitor count from ProbeIngest API for KEDA scaling",
);
// Use probe authentication (probe key and probe ID)
const requestBody: JSONObject = ProbeAPIRequest.getDefaultRequestBody();
@@ -40,37 +44,40 @@ router.get(
const result: HTTPResponse<JSONObject> | HTTPErrorResponse =
await API.fetch<JSONObject>({
method: HTTPMethod.POST,
url: queueSizeUrl,
url: pendingMonitorsUrl,
data: requestBody,
headers: {},
options: { ...ProxyConfig.getRequestProxyAgents(queueSizeUrl) },
options: { ...ProxyConfig.getRequestProxyAgents(pendingMonitorsUrl) },
});
if (result instanceof HTTPErrorResponse) {
logger.error("Error fetching queue size from ProbeIngest API");
logger.error("Error fetching pending monitor count from ProbeIngest API");
logger.error(result);
throw result;
}
logger.debug("Queue size fetched successfully from ProbeIngest API");
logger.debug(
"Pending monitor count fetched successfully from ProbeIngest API",
);
logger.debug(result.data);
// Extract queueSize from the response
let queueSize: number = (result.data["queueSize"] as number) || 0;
// Extract count from the response - this is the number of monitors pending to be probed
let queueSize: number = (result.data["count"] as number) || 0;
// if string then convert to number
if (typeof queueSize === "string") {
const parsedQueueSize: number = parseInt(queueSize, 10);
if (!isNaN(parsedQueueSize)) {
queueSize = parsedQueueSize;
} else {
logger.warn("Queue size is not a valid number, defaulting to 0");
logger.warn(
"Pending monitor count is not a valid number, defaulting to 0",
);
queueSize = 0;
}
}
logger.debug(`Queue size fetched: ${queueSize}`);
logger.debug(`Pending monitor count for KEDA: ${queueSize}`);
return Response.sendJsonObjectResponse(req, res, {
queueSize: queueSize,

View File

@@ -277,6 +277,64 @@ router.get(
},
);
// This API returns the count of monitors pending to be probed for the authenticated probe.
// Used by KEDA for autoscaling probes based on pending monitor count.
router.post(
"/monitor/pending-count",
ProbeAuthorization.isAuthorizedServiceMiddleware,
async (
req: ExpressRequest,
res: ExpressResponse,
next: NextFunction,
): Promise<void> => {
try {
if (
!(req as ProbeExpressRequest).probe ||
!(req as ProbeExpressRequest).probe?.id
) {
logger.error("Probe not found for pending-count request");
return Response.sendErrorResponse(
req,
res,
new BadDataException("Probe not found"),
);
}
const probeId: ObjectID = (req as ProbeExpressRequest).probe!.id!;
if (!probeId) {
logger.error("Probe ID not found for pending-count request");
return Response.sendErrorResponse(
req,
res,
new BadDataException("Probe not found"),
);
}
// Get count of monitors pending to be probed
const monitorProbesCount: PositiveNumber =
await MonitorProbeService.countBy({
query: getMonitorFetchQuery(probeId),
props: {
isRoot: true,
},
});
logger.debug(
`Pending monitor count for probe ${probeId.toString()}: ${monitorProbesCount.toNumber()}`,
);
return Response.sendJsonObjectResponse(req, res, {
count: monitorProbesCount.toNumber(),
});
} catch (err) {
return next(err);
}
},
);
router.post(
"/monitor/list",
ProbeAuthorization.isAuthorizedServiceMiddleware,