migrated grpc keyword to the newer monitoringtype (#4821)

Co-authored-by: Louis Lam <louislam@users.noreply.github.com>
This commit is contained in:
Frank Elsinga
2025-11-29 16:21:45 +01:00
committed by GitHub
parent 46b07953ad
commit b230ab0a06
7 changed files with 427 additions and 92 deletions
+89
View File
@@ -0,0 +1,89 @@
const { MonitorType } = require("./monitor-type");
const { UP, log } = require("../../src/util");
const dayjs = require("dayjs");
const grpc = require("@grpc/grpc-js");
const protojs = require("protobufjs");
class GrpcKeywordMonitorType extends MonitorType {
name = "grpc-keyword";
/**
* @inheritdoc
*/
async check(monitor, heartbeat, _server) {
const startTime = dayjs().valueOf();
const service = this.constructGrpcService(monitor.grpcUrl, monitor.grpcProtobuf, monitor.grpcServiceName, monitor.grpcEnableTls);
let response = await this.grpcQuery(service, monitor.grpcMethod, monitor.grpcBody);
heartbeat.ping = dayjs().valueOf() - startTime;
log.debug(this.name, "gRPC response:", response);
let keywordFound = response.toString().includes(monitor.keyword);
if (keywordFound !== !monitor.isInvertKeyword()) {
log.debug(this.name, `GRPC response [${response}] + ", but keyword [${monitor.keyword}] is ${keywordFound ? "present" : "not"} in [" + ${response} + "]"`);
let truncatedResponse = (response.length > 50) ? response.toString().substring(0, 47) + "..." : response;
throw new Error(`keyword [${monitor.keyword}] is ${keywordFound ? "present" : "not"} in [" + ${truncatedResponse} + "]`);
}
heartbeat.status = UP;
heartbeat.msg = `${response}, keyword [${monitor.keyword}] ${keywordFound ? "is" : "not"} found`;
}
/**
* Create gRPC client
* @param {string} url grpc Url
* @param {string} protobufData grpc ProtobufData
* @param {string} serviceName grpc ServiceName
* @param {string} enableTls grpc EnableTls
* @returns {grpc.Service} grpc Service
*/
constructGrpcService(url, protobufData, serviceName, enableTls) {
const protocObject = protojs.parse(protobufData);
const protoServiceObject = protocObject.root.lookupService(serviceName);
const Client = grpc.makeGenericClientConstructor({});
const credentials = enableTls ? grpc.credentials.createSsl() : grpc.credentials.createInsecure();
const client = new Client(url, credentials);
return protoServiceObject.create((method, requestData, cb) => {
const fullServiceName = method.fullName;
const serviceFQDN = fullServiceName.split(".");
const serviceMethod = serviceFQDN.pop();
const serviceMethodClientImpl = `/${serviceFQDN.slice(1).join(".")}/${serviceMethod}`;
log.debug(this.name, `gRPC method ${serviceMethodClientImpl}`);
client.makeUnaryRequest(
serviceMethodClientImpl,
arg => arg,
arg => arg,
requestData,
cb);
}, false, false);
}
/**
* Create gRPC client stib
* @param {grpc.Service} service grpc Url
* @param {string} method grpc Method
* @param {string} body grpc Body
* @returns {Promise<string>} Result of gRPC query
*/
async grpcQuery(service, method, body) {
return new Promise((resolve, reject) => {
try {
service[method](JSON.parse(body), (err, response) => {
if (err) {
if (err.code !== 1) {
reject(err);
}
log.debug(this.name, `ignoring ${err.code} ${err.details}, as code=1 is considered OK`);
resolve(`${err.code} is considered OK because ${err.details}`);
}
resolve(JSON.stringify(response));
});
} catch (err) {
reject(err);
}
});
}
}
module.exports = {
GrpcKeywordMonitorType,
};