Skip to content

Commit

Permalink
feat(iroha-connector): add prometheus exporter to the plugin
Browse files Browse the repository at this point in the history
 
Primary Changes
----------------
1. Added Prometheus Exporter to Iroha ledger plugin
2. Added Prometheus Metrics tracker to relevant iroha tests.
 
Fixes #1260

Signed-off-by: ashnashahgrover <[email protected]>
  • Loading branch information
ashnashahgrover committed Aug 14, 2024
1 parent 30cde8b commit 4740710
Show file tree
Hide file tree
Showing 15 changed files with 377 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -480,4 +480,4 @@ describe("PluginLedgerConnectorBesu", () => {
expect(res.status).toEqual(200);
expect(res.data.includes(promMetricsOutput)).toBeTrue();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"express": "4.19.2",
"fast-safe-stringify": "2.1.1",
"hada": "0.0.8",
"prom-client": "15.1.3",
"rxjs": "7.8.1",
"sanitize-html": "2.12.1",
"socket.io": "4.6.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,10 @@
}
}
},
"PrometheusExporterMetricsResponse": {
"type": "string",
"nullable": false
},
"GenerateTransactionRequestV1": {
"type": "object",
"description": "Request for generating transaction or query payload that can be signed on the client side.",
Expand Down Expand Up @@ -623,6 +627,31 @@
}
}
},
"/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-iroha2/get-prometheus-exporter-metrics": {
"get": {
"x-hyperledger-cacti": {
"http": {
"verbLowerCase": "get",
"path": "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-iroha2/get-prometheus-exporter-metrics"
}
},
"operationId": "getPrometheusMetricsV1",
"summary": "Get the Prometheus Metrics",
"parameters": [],
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/PrometheusExporterMetricsResponse"
}
}
}
}
}
}
},
"/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-iroha2/query": {
"post": {
"x-hyperledger-cacti": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,10 @@
}
}
},
"PrometheusExporterMetricsResponse": {
"type": "string",
"nullable": false
},
"GenerateTransactionRequestV1": {
"type": "object",
"description": "Request for generating transaction or query payload that can be signed on the client side.",
Expand Down Expand Up @@ -623,6 +627,31 @@
}
}
},
"/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-iroha2/get-prometheus-exporter-metrics": {
"get": {
"x-hyperledger-cacti": {
"http": {
"verbLowerCase": "get",
"path": "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-iroha2/get-prometheus-exporter-metrics"
}
},
"operationId": "getPrometheusMetricsV1",
"summary": "Get the Prometheus Metrics",
"parameters": [],
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/PrometheusExporterMetricsResponse"
}
}
}
}
}
}
},
"/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-iroha2/query": {
"post": {
"x-hyperledger-cacti": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import {
Iroha2BaseConfigTorii,
} from "../generated/openapi/typescript-axios";
import { IrohaV2PrerequisitesProvider } from "./prerequisites-provider";
import { PrometheusExporter } from "../prometheus-exporter/prometheus-exporter";

setCrypto(crypto);

Expand Down Expand Up @@ -792,6 +793,7 @@ export class CactusIrohaV2Client {
* @returns `TransactResponseV1`
*/
public async send(
prometheusExporter: PrometheusExporter,
txParams?: TransactionPayloadParameters,
waitForCommit = false,
): Promise<TransactResponseV1> {
Expand Down Expand Up @@ -820,6 +822,9 @@ export class CactusIrohaV2Client {
this.prerequisitesProvider.getApiHttpProperties(),
signedTx,
);
// counter will increase here
prometheusExporter.addCurrentTransaction()

this.clear();

if (statusPromise) {
Expand All @@ -843,6 +848,7 @@ export class CactusIrohaV2Client {
public async sendSignedPayload(
signedPayload: VersionedSignedTransaction | ArrayBufferView,
waitForCommit = false,
prometheusExporter: PrometheusExporter,
): Promise<TransactResponseV1> {
Checks.truthy(signedPayload, "sendSigned arg signedPayload");

Expand All @@ -853,16 +859,26 @@ export class CactusIrohaV2Client {
const hash = computeTransactionHash(signedPayload.as("V1").payload);
if (waitForCommit) {
const statusPromise = this.waitForTransactionStatus(hash);

await Torii.submit(
this.prerequisitesProvider.getApiHttpProperties(),
signedPayload,
);

// counter will increase here
prometheusExporter.addCurrentTransaction()

return await statusPromise;
} else {

await Torii.submit(
this.prerequisitesProvider.getApiHttpProperties(),
signedPayload,
);

// counter will increase here
prometheusExporter.addCurrentTransaction()

return {
hash: bytesToHex([...hash]),
status: TransactionStatusV1.Submitted,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,36 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
options: localVarRequestOptions,
};
},
/**
*
* @summary Get the Prometheus Metrics
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getPrometheusMetricsV1: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-iroha2/get-prometheus-exporter-metrics`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}

const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;



setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};

return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @summary Executes a query on a Iroha V2 ledger and returns it\'s results.
Expand Down Expand Up @@ -748,6 +778,16 @@ export const DefaultApiFp = function(configuration?: Configuration) {
const localVarAxiosArgs = await localVarAxiosParamCreator.generateTransactionV1(generateTransactionRequestV1, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @summary Get the Prometheus Metrics
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getPrometheusMetricsV1(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<string>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getPrometheusMetricsV1(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @summary Executes a query on a Iroha V2 ledger and returns it\'s results.
Expand Down Expand Up @@ -790,6 +830,15 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa
generateTransactionV1(generateTransactionRequestV1?: GenerateTransactionRequestV1, options?: any): AxiosPromise<string> {
return localVarFp.generateTransactionV1(generateTransactionRequestV1, options).then((request) => request(axios, basePath));
},
/**
*
* @summary Get the Prometheus Metrics
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getPrometheusMetricsV1(options?: any): AxiosPromise<string> {
return localVarFp.getPrometheusMetricsV1(options).then((request) => request(axios, basePath));
},
/**
*
* @summary Executes a query on a Iroha V2 ledger and returns it\'s results.
Expand Down Expand Up @@ -832,6 +881,17 @@ export class DefaultApi extends BaseAPI {
return DefaultApiFp(this.configuration).generateTransactionV1(generateTransactionRequestV1, options).then((request) => request(this.axios, this.basePath));
}

/**
*
* @summary Get the Prometheus Metrics
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof DefaultApi
*/
public getPrometheusMetricsV1(options?: AxiosRequestConfig) {
return DefaultApiFp(this.configuration).getPrometheusMetricsV1(options).then((request) => request(this.axios, this.basePath));
}

/**
*
* @summary Executes a query on a Iroha V2 ledger and returns it\'s results.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ import { CactusIrohaV2QueryClient } from "./cactus-iroha-sdk-wrapper/query";
import { LengthOf, stringifyBigIntReplacer } from "./utils";
import { createAccountId } from "./cactus-iroha-sdk-wrapper/data-factories";

import {
GetPrometheusExporterMetricsEndpointV1,
IGetPrometheusExporterMetricsEndpointV1Options,
} from "./web-services/get-prometheus-exporter-metrics-endpoint-v1";
import { PrometheusExporter } from "./prometheus-exporter/prometheus-exporter";


/**
* Input options for PluginLedgerConnectorIroha2.
*/
Expand All @@ -72,6 +79,7 @@ export interface IPluginLedgerConnectorIroha2Options
pluginRegistry: PluginRegistry;
logLevel?: LogLevelDesc;
defaultConfig?: Iroha2BaseConfig;
prometheusExporter?: PrometheusExporter;
}

/**
Expand All @@ -84,6 +92,7 @@ export class PluginLedgerConnectorIroha2
IPluginWebService
{
private readonly instanceId: string;
public prometheusExporter: PrometheusExporter;
private readonly log: Logger;
private readonly defaultConfig: Iroha2BaseConfig | undefined;
private endpoints: IWebServiceEndpoint[] | undefined;
Expand All @@ -102,6 +111,17 @@ export class PluginLedgerConnectorIroha2

this.instanceId = options.instanceId;

this.prometheusExporter =
options.prometheusExporter ||
new PrometheusExporter({ pollingIntervalInMin: 1 });
Checks.truthy(
this.prometheusExporter,
`${fnTag} options.prometheusExporter`,
);

this.prometheusExporter.startMetricsCollection();


this.defaultConfig = options.defaultConfig;
// Remove proto in case we use merge method vulnerable to proto pollution
if (this.defaultConfig instanceof Object) {
Expand Down Expand Up @@ -133,6 +153,16 @@ export class PluginLedgerConnectorIroha2
return OAS;
}

public getPrometheusExporter(): PrometheusExporter {
return this.prometheusExporter;
}

public async getPrometheusExporterMetrics(): Promise<string> {
const res: string = await this.prometheusExporter.getPrometheusMetrics();
this.log.debug(`getPrometheusExporterMetrics() response: %o`, res);
return res;
}

/**
* @warning Method not implemented - do not use!
*/
Expand Down Expand Up @@ -266,6 +296,15 @@ export class PluginLedgerConnectorIroha2
}),
];

{
const opts: IGetPrometheusExporterMetricsEndpointV1Options = {
connector: this,
logLevel: this.options.logLevel,
};
const endpoint = new GetPrometheusExporterMetricsEndpointV1(opts);
endpoints.push(endpoint);
}

this.endpoints = endpoints;
return endpoints;
}
Expand Down Expand Up @@ -589,7 +628,6 @@ export class PluginLedgerConnectorIroha2
if (!reqParams) {
return undefined;
}

return {
ttl: reqParams.ttl ? BigInt(reqParams.ttl) : undefined,
creationTime: reqParams.creationTime
Expand All @@ -610,11 +648,12 @@ export class PluginLedgerConnectorIroha2
public async transact(req: TransactRequestV1): Promise<TransactResponseV1> {
const fnTag = `${this.className}:transact()`;
const client = await this.createClient(req.baseConfig);

try {
if (req.transaction) {
this.processInstructionsRequests(client, req.transaction.instruction);
return await client.send(
this.prometheusExporter,
this.tryParseTransactionParams(req.transaction.params),
req.waitForCommit,
);
Expand All @@ -625,6 +664,7 @@ export class PluginLedgerConnectorIroha2
return await client.sendSignedPayload(
transactionBinary,
req.waitForCommit,
this.prometheusExporter
);
} else {
const eMsg =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Transactions } from "./response.type";

import { totalTxCount, K_CACTUS_IROHA2_TOTAL_TX_COUNT } from "./metrics";

export async function collectMetrics(
transactions: Transactions,
): Promise<void> {
transactions.counter++;
totalTxCount.labels(K_CACTUS_IROHA2_TOTAL_TX_COUNT).set(transactions.counter);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Gauge } from "prom-client";

export const K_CACTUS_IROHA2_TOTAL_TX_COUNT = "cactus_iroha2_total_tx_count";

export const totalTxCount = new Gauge({
registers: [],
name: "cactus_iroha2_total_tx_count",
help: "Total transactions executed",
labelNames: ["type"],
});
Loading

0 comments on commit 4740710

Please sign in to comment.