Skip to content

Commit 7759712

Browse files
feat(fabric): add prometheus exporter
Primary Change -------------- 1. The fabric ledger connector plugin now includes the prometheus metrics exporter integration 2. OpenAPI spec now has api endpoint for the getting the prometheus metrics Refactorings that were also necessary to accomodate 1) and 2) ------------------------------------------------------------ 3. The generate-sdk command now has DateTime mapping to Date (to read Date as Date object instead of string) 4. GetPrometheusMetricsV1 class is created to handle the corresponding api endpoint 5. IPluginLedgerConnectorFabricOptions interface in PluginLedgerConnectorFabric class now has a prometheusExporter optional field 6. The PluginLedgerConnectorFabric class has relevant functions and codes to incorporate prometheus exporter 7. run-transaction-endpoint-v1.test is changed to incorporate the prometheus exporter for both fabric 1.4.x and 2.x versions 8. Added Readme.md on the prometheus exporter usage Fixes hyperledger-cacti#531 Signed-off-by: jagpreetsinghsasan <[email protected]>
1 parent add9cd9 commit 7759712

File tree

18 files changed

+449
-93
lines changed

18 files changed

+449
-93
lines changed

packages/cactus-plugin-ledger-connector-besu/src/main/typescript/generated/openapi/typescript-axios/api.ts

+28-52
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,6 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
531531
if (configuration) {
532532
baseOptions = configuration.baseOptions;
533533
}
534-
535534
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
536535
const localVarHeaderParameter = {} as any;
537536
const localVarQueryParameter = {} as any;
@@ -540,23 +539,18 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
540539

541540
localVarHeaderParameter['Content-Type'] = 'application/json';
542541

543-
const queryParameters = new URLSearchParams(localVarUrlObj.search);
542+
const query = new URLSearchParams(localVarUrlObj.search);
544543
for (const key in localVarQueryParameter) {
545-
queryParameters.set(key, localVarQueryParameter[key]);
544+
query.set(key, localVarQueryParameter[key]);
546545
}
547546
for (const key in options.query) {
548-
queryParameters.set(key, options.query[key]);
547+
query.set(key, options.query[key]);
549548
}
550-
localVarUrlObj.search = (new URLSearchParams(queryParameters)).toString();
549+
localVarUrlObj.search = (new URLSearchParams(query)).toString();
551550
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
552551
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
553-
const nonString = typeof deployContractSolidityBytecodeV1Request !== 'string';
554-
const needsSerialization = nonString && configuration && configuration.isJsonMime
555-
? configuration.isJsonMime(localVarRequestOptions.headers['Content-Type'])
556-
: nonString;
557-
localVarRequestOptions.data = needsSerialization
558-
? JSON.stringify(deployContractSolidityBytecodeV1Request !== undefined ? deployContractSolidityBytecodeV1Request : {})
559-
: (deployContractSolidityBytecodeV1Request || "");
552+
const needsSerialization = (typeof deployContractSolidityBytecodeV1Request !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
553+
localVarRequestOptions.data = needsSerialization ? JSON.stringify(deployContractSolidityBytecodeV1Request !== undefined ? deployContractSolidityBytecodeV1Request : {}) : (deployContractSolidityBytecodeV1Request || "");
560554

561555
return {
562556
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
@@ -578,7 +572,6 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
578572
if (configuration) {
579573
baseOptions = configuration.baseOptions;
580574
}
581-
582575
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
583576
const localVarHeaderParameter = {} as any;
584577
const localVarQueryParameter = {} as any;
@@ -587,23 +580,18 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
587580

588581
localVarHeaderParameter['Content-Type'] = 'application/json';
589582

590-
const queryParameters = new URLSearchParams(localVarUrlObj.search);
583+
const query = new URLSearchParams(localVarUrlObj.search);
591584
for (const key in localVarQueryParameter) {
592-
queryParameters.set(key, localVarQueryParameter[key]);
585+
query.set(key, localVarQueryParameter[key]);
593586
}
594587
for (const key in options.query) {
595-
queryParameters.set(key, options.query[key]);
588+
query.set(key, options.query[key]);
596589
}
597-
localVarUrlObj.search = (new URLSearchParams(queryParameters)).toString();
590+
localVarUrlObj.search = (new URLSearchParams(query)).toString();
598591
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
599592
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
600-
const nonString = typeof invokeContractV1Request !== 'string';
601-
const needsSerialization = nonString && configuration && configuration.isJsonMime
602-
? configuration.isJsonMime(localVarRequestOptions.headers['Content-Type'])
603-
: nonString;
604-
localVarRequestOptions.data = needsSerialization
605-
? JSON.stringify(invokeContractV1Request !== undefined ? invokeContractV1Request : {})
606-
: (invokeContractV1Request || "");
593+
const needsSerialization = (typeof invokeContractV1Request !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
594+
localVarRequestOptions.data = needsSerialization ? JSON.stringify(invokeContractV1Request !== undefined ? invokeContractV1Request : {}) : (invokeContractV1Request || "");
607595

608596
return {
609597
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
@@ -625,7 +613,6 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
625613
if (configuration) {
626614
baseOptions = configuration.baseOptions;
627615
}
628-
629616
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
630617
const localVarHeaderParameter = {} as any;
631618
const localVarQueryParameter = {} as any;
@@ -634,23 +621,18 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
634621

635622
localVarHeaderParameter['Content-Type'] = 'application/json';
636623

637-
const queryParameters = new URLSearchParams(localVarUrlObj.search);
624+
const query = new URLSearchParams(localVarUrlObj.search);
638625
for (const key in localVarQueryParameter) {
639-
queryParameters.set(key, localVarQueryParameter[key]);
626+
query.set(key, localVarQueryParameter[key]);
640627
}
641628
for (const key in options.query) {
642-
queryParameters.set(key, options.query[key]);
629+
query.set(key, options.query[key]);
643630
}
644-
localVarUrlObj.search = (new URLSearchParams(queryParameters)).toString();
631+
localVarUrlObj.search = (new URLSearchParams(query)).toString();
645632
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
646633
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
647-
const nonString = typeof runTransactionRequest !== 'string';
648-
const needsSerialization = nonString && configuration && configuration.isJsonMime
649-
? configuration.isJsonMime(localVarRequestOptions.headers['Content-Type'])
650-
: nonString;
651-
localVarRequestOptions.data = needsSerialization
652-
? JSON.stringify(runTransactionRequest !== undefined ? runTransactionRequest : {})
653-
: (runTransactionRequest || "");
634+
const needsSerialization = (typeof runTransactionRequest !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
635+
localVarRequestOptions.data = needsSerialization ? JSON.stringify(runTransactionRequest !== undefined ? runTransactionRequest : {}) : (runTransactionRequest || "");
654636

655637
return {
656638
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
@@ -676,7 +658,6 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
676658
if (configuration) {
677659
baseOptions = configuration.baseOptions;
678660
}
679-
680661
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
681662
const localVarHeaderParameter = {} as any;
682663
const localVarQueryParameter = {} as any;
@@ -685,23 +666,18 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
685666

686667
localVarHeaderParameter['Content-Type'] = 'application/json';
687668

688-
const queryParameters = new URLSearchParams(localVarUrlObj.search);
669+
const query = new URLSearchParams(localVarUrlObj.search);
689670
for (const key in localVarQueryParameter) {
690-
queryParameters.set(key, localVarQueryParameter[key]);
671+
query.set(key, localVarQueryParameter[key]);
691672
}
692673
for (const key in options.query) {
693-
queryParameters.set(key, options.query[key]);
674+
query.set(key, options.query[key]);
694675
}
695-
localVarUrlObj.search = (new URLSearchParams(queryParameters)).toString();
676+
localVarUrlObj.search = (new URLSearchParams(query)).toString();
696677
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
697678
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
698-
const nonString = typeof signTransactionRequest !== 'string';
699-
const needsSerialization = nonString && configuration && configuration.isJsonMime
700-
? configuration.isJsonMime(localVarRequestOptions.headers['Content-Type'])
701-
: nonString;
702-
localVarRequestOptions.data = needsSerialization
703-
? JSON.stringify(signTransactionRequest !== undefined ? signTransactionRequest : {})
704-
: (signTransactionRequest || "");
679+
const needsSerialization = (typeof signTransactionRequest !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
680+
localVarRequestOptions.data = needsSerialization ? JSON.stringify(signTransactionRequest !== undefined ? signTransactionRequest : {}) : (signTransactionRequest || "");
705681

706682
return {
707683
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
@@ -727,7 +703,7 @@ export const DefaultApiFp = function(configuration?: Configuration) {
727703
async apiV1BesuDeployContractSolidityBytecode(deployContractSolidityBytecodeV1Request?: DeployContractSolidityBytecodeV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<DeployContractSolidityBytecodeV1Response>> {
728704
const localVarAxiosArgs = await DefaultApiAxiosParamCreator(configuration).apiV1BesuDeployContractSolidityBytecode(deployContractSolidityBytecodeV1Request, options);
729705
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
730-
const axiosRequestArgs = {...localVarAxiosArgs.options, url: (configuration?.basePath || basePath) + localVarAxiosArgs.url};
706+
const axiosRequestArgs = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
731707
return axios.request(axiosRequestArgs);
732708
};
733709
},
@@ -741,7 +717,7 @@ export const DefaultApiFp = function(configuration?: Configuration) {
741717
async apiV1BesuInvokeContract(invokeContractV1Request?: InvokeContractV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InvokeContractV1Response>> {
742718
const localVarAxiosArgs = await DefaultApiAxiosParamCreator(configuration).apiV1BesuInvokeContract(invokeContractV1Request, options);
743719
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
744-
const axiosRequestArgs = {...localVarAxiosArgs.options, url: (configuration?.basePath || basePath) + localVarAxiosArgs.url};
720+
const axiosRequestArgs = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
745721
return axios.request(axiosRequestArgs);
746722
};
747723
},
@@ -755,7 +731,7 @@ export const DefaultApiFp = function(configuration?: Configuration) {
755731
async apiV1BesuRunTransaction(runTransactionRequest?: RunTransactionRequest, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<RunTransactionResponse>> {
756732
const localVarAxiosArgs = await DefaultApiAxiosParamCreator(configuration).apiV1BesuRunTransaction(runTransactionRequest, options);
757733
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
758-
const axiosRequestArgs = {...localVarAxiosArgs.options, url: (configuration?.basePath || basePath) + localVarAxiosArgs.url};
734+
const axiosRequestArgs = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
759735
return axios.request(axiosRequestArgs);
760736
};
761737
},
@@ -769,7 +745,7 @@ export const DefaultApiFp = function(configuration?: Configuration) {
769745
async signTransactionV1(signTransactionRequest: SignTransactionRequest, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SignTransactionResponse>> {
770746
const localVarAxiosArgs = await DefaultApiAxiosParamCreator(configuration).signTransactionV1(signTransactionRequest, options);
771747
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
772-
const axiosRequestArgs = {...localVarAxiosArgs.options, url: (configuration?.basePath || basePath) + localVarAxiosArgs.url};
748+
const axiosRequestArgs = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
773749
return axios.request(axiosRequestArgs);
774750
};
775751
},

packages/cactus-plugin-ledger-connector-besu/src/main/typescript/generated/openapi/typescript-axios/configuration.ts

-25
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ export interface ConfigurationParameters {
2020
accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise<string>);
2121
basePath?: string;
2222
baseOptions?: any;
23-
formDataCtor?: new () => any;
2423
}
2524

2625
export class Configuration {
@@ -65,14 +64,6 @@ export class Configuration {
6564
* @memberof Configuration
6665
*/
6766
baseOptions?: any;
68-
/**
69-
* The FormData constructor that will be used to create multipart form data
70-
* requests. You can inject this here so that execution environments that
71-
* do not support the FormData class can still run the generated client.
72-
*
73-
* @type {new () => FormData}
74-
*/
75-
formDataCtor?: new () => any;
7667

7768
constructor(param: ConfigurationParameters = {}) {
7869
this.apiKey = param.apiKey;
@@ -81,21 +72,5 @@ export class Configuration {
8172
this.accessToken = param.accessToken;
8273
this.basePath = param.basePath;
8374
this.baseOptions = param.baseOptions;
84-
this.formDataCtor = param.formDataCtor;
85-
}
86-
87-
/**
88-
* Check if the given MIME is a JSON MIME.
89-
* JSON MIME examples:
90-
* application/json
91-
* application/json; charset=UTF8
92-
* APPLICATION/JSON
93-
* application/vnd.company+json
94-
* @param mime - MIME (Multipurpose Internet Mail Extensions)
95-
* @return True if the given MIME is JSON, false otherwise.
96-
*/
97-
public isJsonMime(mime: string): boolean {
98-
const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i');
99-
return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json');
10075
}
10176
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,41 @@
11
# `@hyperledger/cactus-plugin-ledger-connector-fabric`
22

3-
> TODO: description
3+
## Prometheus Exporter
44

5-
## Usage
5+
This class creates a prometheus exporter, which scraps the transactions (total transaction count) for the use cases incorporating the use of Fabric connector plugin.
66

7+
8+
### Usage
9+
The prometheus exporter object is initialized in the `PluginLedgerConnectorFabric` class constructor itself, so instantiating the object of the `PluginLedgerConnectorFabric` class, gives access to the exporter object.
10+
You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginLedgerConnectorFabricOptions` interface for `PluginLedgerConnectoFabric` constructor.
11+
12+
`getPrometheusExporterMetricsEndpointV1` function returns the prometheus exporter metrics, currently displaying the total transaction count, which currently increments everytime the `transact()` method of the `PluginLedgerConnectorFabric` class is called.
13+
14+
### Prometheus Integration
15+
To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/).
16+
Once Prometheus is setup, the corresponding scrape_config needs to be added to the prometheus.yml
17+
18+
```(yaml)
19+
- job_name: 'fabric_ledger_connector_exporter'
20+
metrics_path: api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-prometheus-exporter-metrics
21+
scrape_interval: 5s
22+
static_configs:
23+
- targets: ['{host}:{port}']
724
```
8-
// TODO: DEMONSTRATE API
9-
```
25+
26+
Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL)
27+
`Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-prometheus-exporter-metrics`
28+
29+
Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file.
30+
On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **totalTxCount** and click **execute**
31+
32+
### Helper code
33+
34+
###### response.type.ts
35+
This file contains the various responses of the metrics.
36+
37+
###### data-fetcher.ts
38+
This file contains functions encasing the logic to process the data points
39+
40+
###### metrics.ts
41+
This file lists all the prometheus metrics and what they are used for.

0 commit comments

Comments
 (0)