From 7e90a1adfbc7eefbf58d0cecae3827a5473fb70d Mon Sep 17 00:00:00 2001 From: Iulia Mihaiu Date: Tue, 3 Aug 2021 01:01:00 +0300 Subject: [PATCH] feat(cc-tx-visualization): initial commit Signed-off-by: Iulia Mihaiu --- .../CHANGELOG.md | 94 +++++ .../README.md | 39 +++ .../openapitools.json | 7 + .../package.json | 96 ++++++ .../typescript-axios/.openapi-generator/FILES | 6 + .../.openapi-generator/VERSION | 1 + .../generated/openapi/typescript-axios/api.ts | 326 ++++++++++++++++++ .../openapi/typescript-axios/base.ts | 71 ++++ .../openapi/typescript-axios/common.ts | 138 ++++++++ .../openapi/typescript-axios/configuration.ts | 101 ++++++ .../openapi/typescript-axios/index.ts | 18 + .../src/main/typescript/index.ts | 1 + .../src/main/typescript/index.web.ts | 1 + .../typescript/plugin-cc-tx-visualization.ts | 213 ++++++++++++ .../plugin-factory-cc-tx-visualization.ts | 20 ++ .../prometheus-exporter/data-fetcher.ts | 12 + .../typescript/prometheus-exporter/metrics.ts | 10 + .../prometheus-exporter.ts | 42 +++ .../prometheus-exporter/response.type.ts | 3 + .../src/main/typescript/public-api.ts | 18 + .../integration/api-surface.test.ts | 8 + .../test/typescript/unit/api-surface.test.ts | 8 + .../typescript/unit/instantiation.test.ts | 18 + .../tsconfig.json | 25 ++ 24 files changed, 1276 insertions(+) create mode 100644 packages/cactus-plugin-cc-tx-visualization/CHANGELOG.md create mode 100644 packages/cactus-plugin-cc-tx-visualization/README.md create mode 100644 packages/cactus-plugin-cc-tx-visualization/openapitools.json create mode 100644 packages/cactus-plugin-cc-tx-visualization/package.json create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/api.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/base.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/common.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/configuration.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/index.ts create mode 100755 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/index.ts create mode 100755 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/index.web.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/plugin-cc-tx-visualization.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/plugin-factory-cc-tx-visualization.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/data-fetcher.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/metrics.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/prometheus-exporter.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/response.type.ts create mode 100755 packages/cactus-plugin-cc-tx-visualization/src/main/typescript/public-api.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/test/typescript/integration/api-surface.test.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/test/typescript/unit/api-surface.test.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/src/test/typescript/unit/instantiation.test.ts create mode 100644 packages/cactus-plugin-cc-tx-visualization/tsconfig.json diff --git a/packages/cactus-plugin-cc-tx-visualization/CHANGELOG.md b/packages/cactus-plugin-cc-tx-visualization/CHANGELOG.md new file mode 100644 index 00000000000..9ad69f127a2 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/CHANGELOG.md @@ -0,0 +1,94 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [0.6.0](https://github.com/hyperledger/cactus/compare/v0.4.1...v0.6.0) (2021-07-19) + + +### Bug Fixes + +* **connector-corda:** container image kotlin compilation fails in model ([a8a4531](https://github.com/hyperledger/cactus/commit/a8a4531d379fe16d4c991802525ec573a7e3ede1)) + + +### Features + +* **core-api:** decouple web service install & registration [#771](https://github.com/hyperledger/cactus/issues/771) ([b50e148](https://github.com/hyperledger/cactus/commit/b50e148f43c0b27138471c972aab391486e761e6)) +* **core-api:** jwt authorization [#770](https://github.com/hyperledger/cactus/issues/770) ([2016750](https://github.com/hyperledger/cactus/commit/2016750849b4333bb4dd78897468771f0642a4f5)) +* **core-api:** plugin async initializer method ([9678c2e](https://github.com/hyperledger/cactus/commit/9678c2e9288a73589e84f9fd254c26aed6a93297)) + + + + + +# [0.5.0](https://github.com/hyperledger/cactus/compare/v0.4.1...v0.5.0) (2021-05-19) + + +### Features + +* **core-api:** decouple web service install & registration [#771](https://github.com/hyperledger/cactus/issues/771) ([b50e148](https://github.com/hyperledger/cactus/commit/b50e148f43c0b27138471c972aab391486e761e6)) +* **core-api:** jwt authorization [#770](https://github.com/hyperledger/cactus/issues/770) ([2016750](https://github.com/hyperledger/cactus/commit/2016750849b4333bb4dd78897468771f0642a4f5)) + + + + + +## [0.4.1](https://github.com/hyperledger/cactus/compare/v0.4.0...v0.4.1) (2021-04-02) + + +### Bug Fixes + +* **release:** package.json publish config non-public [#753](https://github.com/hyperledger/cactus/issues/753) ([5a1b7a6](https://github.com/hyperledger/cactus/commit/5a1b7a6eba9a18d4f7474a3c44d4a4035fc99e84)) + + +### Features + +* **api-server:** add prometheus exporter ([c348aa4](https://github.com/hyperledger/cactus/commit/c348aa4f858536bca350af6abd524a5d345aacc7)), closes [#539](https://github.com/hyperledger/cactus/issues/539) + + + + + +# [0.4.0](https://github.com/hyperledger/cactus/compare/v0.3.0...v0.4.0) (2021-03-30) + + +### Bug Fixes + +* **deps:** missing uuid from plugins [#529](https://github.com/hyperledger/cactus/issues/529) ([04ea8bb](https://github.com/hyperledger/cactus/commit/04ea8bb8a035382de078d082889c8fdfd48479f8)) +* **general:** fixed unused deps and updated them ([b76a970](https://github.com/hyperledger/cactus/commit/b76a9703341c5a4cabe056e743338cbedebbeaad)) +* **npm:** clean script was missing folders ([416b82e](https://github.com/hyperledger/cactus/commit/416b82e971607129fbdfa9e1270644d0c2f5c706)), closes [#469](https://github.com/hyperledger/cactus/issues/469) + + +### Features + +* **consortium-manual:** add prometheus exporter ([853bdc4](https://github.com/hyperledger/cactus/commit/853bdc42aca59dabe2910c5dd4ddec646e80ab5a)), closes [#538](https://github.com/hyperledger/cactus/issues/538) +* **core-api:** plugin import types: LOCAL & REMOTE ([f4d51da](https://github.com/hyperledger/cactus/commit/f4d51dae5b28367e714a2b9aa35dd84a2cb4cb37)) + + + + + +# [0.3.0](https://github.com/hyperledger/cactus/compare/v0.1.0...v0.3.0) (2021-01-06) + + +### Bug Fixes + +* open API generator config - protected keyword ([57e52f4](https://github.com/hyperledger/cactus/commit/57e52f42c3aaab653acb8838ba93518a5a097af8)), closes [#436](https://github.com/hyperledger/cactus/issues/436) + + +### Features + +* **core-api:** add instanceId getter to ICactusPlugin ([e50d9ce](https://github.com/hyperledger/cactus/commit/e50d9cef081708d7d6b92701f7f941c36ef6f920)) +* **plugin-consortium-manual:** JSON Web Signatures for Nodes, Consortium ([caf60b3](https://github.com/hyperledger/cactus/commit/caf60b3f69c81617787afe73ca12165baa2dce50)) + + + + + +# [0.2.0](https://github.com/hyperledger/cactus/compare/v0.1.0...v0.2.0) (2020-12-01) + + +### Features + +* **core-api:** add instanceId getter to ICactusPlugin ([e50d9ce](https://github.com/hyperledger/cactus/commit/e50d9cef081708d7d6b92701f7f941c36ef6f920)) +* **plugin-consortium-manual:** JSON Web Signatures for Nodes, Consortium ([caf60b3](https://github.com/hyperledger/cactus/commit/caf60b3f69c81617787afe73ca12165baa2dce50)) diff --git a/packages/cactus-plugin-cc-tx-visualization/README.md b/packages/cactus-plugin-cc-tx-visualization/README.md new file mode 100644 index 00000000000..6e00b204fd4 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/README.md @@ -0,0 +1,39 @@ +# `@hyperledger/cactus-plugin-consortium-manual` + +## Prometheus Exporter +This class creates a prometheus exporter, which scrapes the total Cactus node count. + +### Usage Prometheus +The prometheus exporter object is initialized in the `PluginConsortiumManual` class constructor itself, so instantiating the object of the `PluginConsortiumManual` class, gives access to the exporter object. +You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginConsortiumManualOptions` interface for `PluginConsortiumManual` constructor. + +`getPrometheusMetricsV1` function returns the prometheus exporter metrics, currently displaying the total cactus node count, which currently refreshes to match the node count in the consortium, everytime `updateMetricNodeCount` method of the `PluginConsortiumManual` class is called. + +### Prometheus Integration +To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). +Once Prometheus is setup, the corresponding scrape_config needs to be added to the prometheus.yml + +```(yaml) +- job_name: 'consortium_manual_exporter' + metrics_path: api/v1/plugins/@hyperledger/cactus-plugin-consortium-manual/get-prometheus-exporter-metrics + scrape_interval: 5s + static_configs: + - targets: ['{host}:{port}'] +``` + +Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-consortium-manual/src/test/typescript/unit/consortium/get-node-jws-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) +`Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-consortium-manual/get-prometheus-exporter-metrics` + +Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. +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 **cactus_consortium_manual_total_node_count** and click **execute** + +### Helper code + +###### response.type.ts +This file contains the various responses of the metrics. + +###### data-fetcher.ts +This file contains functions encasing the logic to process the data points. + +###### metrics.ts +This file lists all the prometheus metrics and what they are used for. \ No newline at end of file diff --git a/packages/cactus-plugin-cc-tx-visualization/openapitools.json b/packages/cactus-plugin-cc-tx-visualization/openapitools.json new file mode 100644 index 00000000000..d2fdbae832d --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/openapitools.json @@ -0,0 +1,7 @@ +{ + "$schema": "node_modules/@openapitools/openapi-generator-cli/config.schema.json", + "spaces": 2, + "generator-cli": { + "version": "5.1.1" + } +} diff --git a/packages/cactus-plugin-cc-tx-visualization/package.json b/packages/cactus-plugin-cc-tx-visualization/package.json new file mode 100644 index 00000000000..db37ec7c264 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/package.json @@ -0,0 +1,96 @@ +{ + "name": "@hyperledger/cactus-plugin-cc-tx-visualization", + "version": "0.6.0", + "description": "A web service plugin that provides management capabilities on cross-chain transactions visualization.", + "main": "dist/lib/main/typescript/index.js", + "mainMinified": "dist/cactus-plugin-cc-tx-visualization.node.umd.min.js", + "browser": "dist/cactus-plugin-cc-tx-visualization.web.umd.js", + "browserMinified": "dist/cactus-plugin-cc-tx-visualization.web.umd.min.js", + "module": "dist/lib/main/typescript/index.js", + "types": "dist/types/main/typescript/index.d.ts", + "files": [ + "dist/*" + ], + "scripts": { + "generate-sdk": "openapi-generator-cli generate -i ./src/main/json/openapi.json -g typescript-axios -o ./src/main/typescript/generated/openapi/typescript-axios/ --reserved-words-mappings protected=protected", + "codegen:openapi": "npm run generate-sdk", + "codegen": "run-p 'codegen:*'", + "watch": "npm-watch", + "webpack": "npm-run-all webpack:dev webpack:prod", + "webpack:dev": "npm-run-all webpack:dev:node webpack:dev:web", + "webpack:dev:web": "webpack --env=dev --target=web --config ../../webpack.config.js", + "webpack:dev:node": "webpack --env=dev --target=node --config ../../webpack.config.js", + "webpack:prod": "npm-run-all webpack:prod:node webpack:prod:web", + "webpack:prod:web": "webpack --env=prod --target=web --config ../../webpack.config.js", + "webpack:prod:node": "webpack --env=prod --target=node --config ../../webpack.config.js" + }, + "watch": { + "codegen:openapi": { + "patterns": [ + "./src/main/json/openapi.json" + ] + } + }, + "publishConfig": { + "access": "public" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/hyperledger/cactus.git" + }, + "keywords": [ + "Hyperledger", + "Cactus", + "Integration", + "Blockchain", + "Distributed Ledger Technology" + ], + "author": { + "name": "Hyperledger Cactus Contributors", + "email": "cactus@lists.hyperledger.org", + "url": "https://www.hyperledger.org/use/cactus" + }, + "contributors": [ + { + "name": "Please add yourself to the list of contributors", + "email": "your.name@example.com", + "url": "https://example.com" + }, + { + "name": "Iulia Mihaiu" + }, + { + "name": "Sabrina Scuri" + }, + { + "name": "Rafael Belchior" + } + ], + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/hyperledger/cactus/issues" + }, + "homepage": "https://github.com/hyperledger/cactus#readme", + "dependencies": { + "@hyperledger/cactus-common": "0.6.0", + "@hyperledger/cactus-core": "0.6.0", + "@hyperledger/cactus-core-api": "0.6.0", + "axios": "0.21.1", + "body-parser": "1.19.0", + "express": "4.17.1", + "jose": "1.28.1", + "json-stable-stringify": "1.0.1", + "prom-client": "13.0.0", + "typescript-optional": "2.0.1", + "uuid": "8.3.2" + }, + "devDependencies": { + "@types/express": "4.17.8", + "@types/json-stable-stringify": "1.0.32", + "@types/uuid": "8.3.0" + } +} diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES new file mode 100644 index 00000000000..d5e35beea15 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES @@ -0,0 +1,6 @@ +.gitignore +api.ts +base.ts +common.ts +configuration.ts +index.ts diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION new file mode 100644 index 00000000000..3bff059174b --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION @@ -0,0 +1 @@ +5.1.1 \ No newline at end of file diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/api.ts new file mode 100644 index 00000000000..468ec379637 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/api.ts @@ -0,0 +1,326 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Consortium Web Service + * Manage a Cactus consortium through the APIs. Needs administrative privileges. + * + * The version of the OpenAPI document: 0.0.1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import { Configuration } from './configuration'; +import globalAxios, { AxiosPromise, AxiosInstance } from 'axios'; +// Some imports not used depending on template conditions +// @ts-ignore +import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from './common'; +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from './base'; + +/** + * + * @export + * @interface GetConsortiumJwsResponse + */ +export interface GetConsortiumJwsResponse { + /** + * + * @type {JWSGeneral} + * @memberof GetConsortiumJwsResponse + */ + jws: JWSGeneral; +} +/** + * + * @export + * @interface GetNodeJwsResponse + */ +export interface GetNodeJwsResponse { + /** + * + * @type {JWSGeneral} + * @memberof GetNodeJwsResponse + */ + jws: JWSGeneral; +} +/** + * + * @export + * @interface JWSGeneral + */ +export interface JWSGeneral { + /** + * + * @type {string} + * @memberof JWSGeneral + */ + payload: string; + /** + * + * @type {Array} + * @memberof JWSGeneral + */ + signatures: Array; +} +/** + * A JSON Web Signature. See: https://tools.ietf.org/html/rfc7515 for info about standard. + * @export + * @interface JWSRecipient + */ +export interface JWSRecipient { + /** + * + * @type {string} + * @memberof JWSRecipient + */ + signature: string; + /** + * + * @type {string} + * @memberof JWSRecipient + */ + protected?: string; + /** + * + * @type {{ [key: string]: object; }} + * @memberof JWSRecipient + */ + header?: { [key: string]: object; }; +} + +/** + * DefaultApi - axios parameter creator + * @export + */ +export const DefaultApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * The JWS asserting the consortium metadata (pub keys and hosts of nodes) + * @summary Retrieves a consortium JWS + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getConsortiumJwsV1: async (body?: object, options: any = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-consortium-manual/consortium/jws`; + // 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: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(body, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Retrieves the JWT of a Cactus Node + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getNodeJwsV1: async (body?: object, options: any = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-consortium-manual/node/jws`; + // 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: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(body, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPrometheusMetricsV1: async (options: any = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-consortium-manual/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, options.query); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * DefaultApi - functional programming interface + * @export + */ +export const DefaultApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = DefaultApiAxiosParamCreator(configuration) + return { + /** + * The JWS asserting the consortium metadata (pub keys and hosts of nodes) + * @summary Retrieves a consortium JWS + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getConsortiumJwsV1(body?: object, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getConsortiumJwsV1(body, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @summary Retrieves the JWT of a Cactus Node + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getNodeJwsV1(body?: object, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getNodeJwsV1(body, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getPrometheusMetricsV1(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getPrometheusMetricsV1(options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + } +}; + +/** + * DefaultApi - factory interface + * @export + */ +export const DefaultApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = DefaultApiFp(configuration) + return { + /** + * The JWS asserting the consortium metadata (pub keys and hosts of nodes) + * @summary Retrieves a consortium JWS + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getConsortiumJwsV1(body?: object, options?: any): AxiosPromise { + return localVarFp.getConsortiumJwsV1(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Retrieves the JWT of a Cactus Node + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getNodeJwsV1(body?: object, options?: any): AxiosPromise { + return localVarFp.getNodeJwsV1(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPrometheusMetricsV1(options?: any): AxiosPromise { + return localVarFp.getPrometheusMetricsV1(options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * DefaultApi - object-oriented interface + * @export + * @class DefaultApi + * @extends {BaseAPI} + */ +export class DefaultApi extends BaseAPI { + /** + * The JWS asserting the consortium metadata (pub keys and hosts of nodes) + * @summary Retrieves a consortium JWS + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public getConsortiumJwsV1(body?: object, options?: any) { + return DefaultApiFp(this.configuration).getConsortiumJwsV1(body, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Retrieves the JWT of a Cactus Node + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public getNodeJwsV1(body?: object, options?: any) { + return DefaultApiFp(this.configuration).getNodeJwsV1(body, 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?: any) { + return DefaultApiFp(this.configuration).getPrometheusMetricsV1(options).then((request) => request(this.axios, this.basePath)); + } +} + + diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/base.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/base.ts new file mode 100644 index 00000000000..a4e481ed14c --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/base.ts @@ -0,0 +1,71 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Consortium Web Service + * Manage a Cactus consortium through the APIs. Needs administrative privileges. + * + * The version of the OpenAPI document: 0.0.1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import { Configuration } from "./configuration"; +// Some imports not used depending on template conditions +// @ts-ignore +import globalAxios, { AxiosPromise, AxiosInstance } from 'axios'; + +export const BASE_PATH = "https://www.cactus.stream".replace(/\/+$/, ""); + +/** + * + * @export + */ +export const COLLECTION_FORMATS = { + csv: ",", + ssv: " ", + tsv: "\t", + pipes: "|", +}; + +/** + * + * @export + * @interface RequestArgs + */ +export interface RequestArgs { + url: string; + options: any; +} + +/** + * + * @export + * @class BaseAPI + */ +export class BaseAPI { + protected configuration: Configuration | undefined; + + constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) { + if (configuration) { + this.configuration = configuration; + this.basePath = configuration.basePath || this.basePath; + } + } +}; + +/** + * + * @export + * @class RequiredError + * @extends {Error} + */ +export class RequiredError extends Error { + name: "RequiredError" = "RequiredError"; + constructor(public field: string, msg?: string) { + super(msg); + } +} diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/common.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/common.ts new file mode 100644 index 00000000000..a44fb71d29a --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/common.ts @@ -0,0 +1,138 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Consortium Web Service + * Manage a Cactus consortium through the APIs. Needs administrative privileges. + * + * The version of the OpenAPI document: 0.0.1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import { Configuration } from "./configuration"; +import { RequiredError, RequestArgs } from "./base"; +import { AxiosInstance } from 'axios'; + +/** + * + * @export + */ +export const DUMMY_BASE_URL = 'https://example.com' + +/** + * + * @throws {RequiredError} + * @export + */ +export const assertParamExists = function (functionName: string, paramName: string, paramValue: unknown) { + if (paramValue === null || paramValue === undefined) { + throw new RequiredError(paramName, `Required parameter ${paramName} was null or undefined when calling ${functionName}.`); + } +} + +/** + * + * @export + */ +export const setApiKeyToObject = async function (object: any, keyParamName: string, configuration?: Configuration) { + if (configuration && configuration.apiKey) { + const localVarApiKeyValue = typeof configuration.apiKey === 'function' + ? await configuration.apiKey(keyParamName) + : await configuration.apiKey; + object[keyParamName] = localVarApiKeyValue; + } +} + +/** + * + * @export + */ +export const setBasicAuthToObject = function (object: any, configuration?: Configuration) { + if (configuration && (configuration.username || configuration.password)) { + object["auth"] = { username: configuration.username, password: configuration.password }; + } +} + +/** + * + * @export + */ +export const setBearerAuthToObject = async function (object: any, configuration?: Configuration) { + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + object["Authorization"] = "Bearer " + accessToken; + } +} + +/** + * + * @export + */ +export const setOAuthToObject = async function (object: any, name: string, scopes: string[], configuration?: Configuration) { + if (configuration && configuration.accessToken) { + const localVarAccessTokenValue = typeof configuration.accessToken === 'function' + ? await configuration.accessToken(name, scopes) + : await configuration.accessToken; + object["Authorization"] = "Bearer " + localVarAccessTokenValue; + } +} + +/** + * + * @export + */ +export const setSearchParams = function (url: URL, ...objects: any[]) { + const searchParams = new URLSearchParams(url.search); + for (const object of objects) { + for (const key in object) { + if (Array.isArray(object[key])) { + searchParams.delete(key); + for (const item of object[key]) { + searchParams.append(key, item); + } + } else { + searchParams.set(key, object[key]); + } + } + } + url.search = searchParams.toString(); +} + +/** + * + * @export + */ +export const serializeDataIfNeeded = function (value: any, requestOptions: any, configuration?: Configuration) { + const nonString = typeof value !== 'string'; + const needsSerialization = nonString && configuration && configuration.isJsonMime + ? configuration.isJsonMime(requestOptions.headers['Content-Type']) + : nonString; + return needsSerialization + ? JSON.stringify(value !== undefined ? value : {}) + : (value || ""); +} + +/** + * + * @export + */ +export const toPathString = function (url: URL) { + return url.pathname + url.search + url.hash +} + +/** + * + * @export + */ +export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) { + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...axiosArgs.options, url: (configuration?.basePath || basePath) + axiosArgs.url}; + return axios.request(axiosRequestArgs); + }; +} diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/configuration.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/configuration.ts new file mode 100644 index 00000000000..fc7ebd25655 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/configuration.ts @@ -0,0 +1,101 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Consortium Web Service + * Manage a Cactus consortium through the APIs. Needs administrative privileges. + * + * The version of the OpenAPI document: 0.0.1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface ConfigurationParameters { + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + username?: string; + password?: string; + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + basePath?: string; + baseOptions?: any; + formDataCtor?: new () => any; +} + +export class Configuration { + /** + * parameter for apiKey security + * @param name security name + * @memberof Configuration + */ + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + username?: string; + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + password?: string; + /** + * parameter for oauth2 security + * @param name security name + * @param scopes oauth2 scope + * @memberof Configuration + */ + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + /** + * override base path + * + * @type {string} + * @memberof Configuration + */ + basePath?: string; + /** + * base options for axios calls + * + * @type {any} + * @memberof Configuration + */ + baseOptions?: any; + /** + * The FormData constructor that will be used to create multipart form data + * requests. You can inject this here so that execution environments that + * do not support the FormData class can still run the generated client. + * + * @type {new () => FormData} + */ + formDataCtor?: new () => any; + + constructor(param: ConfigurationParameters = {}) { + this.apiKey = param.apiKey; + this.username = param.username; + this.password = param.password; + this.accessToken = param.accessToken; + this.basePath = param.basePath; + this.baseOptions = param.baseOptions; + this.formDataCtor = param.formDataCtor; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime - MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public isJsonMime(mime: string): boolean { + const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i'); + return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json'); + } +} diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/index.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/index.ts new file mode 100644 index 00000000000..15276d73566 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/generated/openapi/typescript-axios/index.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Consortium Web Service + * Manage a Cactus consortium through the APIs. Needs administrative privileges. + * + * The version of the OpenAPI document: 0.0.1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export * from "./api"; +export * from "./configuration"; + diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/index.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/index.ts new file mode 100755 index 00000000000..87cb558397c --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/index.ts @@ -0,0 +1 @@ +export * from "./public-api"; diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/index.web.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/index.web.ts new file mode 100755 index 00000000000..bdf54028d23 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/index.web.ts @@ -0,0 +1 @@ +export * from "./generated/openapi/typescript-axios/index"; diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/plugin-cc-tx-visualization.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/plugin-cc-tx-visualization.ts new file mode 100644 index 00000000000..9596730ee22 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/plugin-cc-tx-visualization.ts @@ -0,0 +1,213 @@ +import { Server } from "http"; +import { Server as SecureServer } from "https"; +import { Optional } from "typescript-optional"; +import { promisify } from "util"; +import express, { Express } from "express"; +import bodyParser from "body-parser"; + +import { + IPluginWebService, + IWebServiceEndpoint, + ICactusPlugin, + ICactusPluginOptions, +} from "@hyperledger/cactus-core-api"; + +import { PluginRegistry } from "@hyperledger/cactus-core"; + +import { + Checks, + Logger, + LoggerProvider, + LogLevelDesc, +} from "@hyperledger/cactus-common"; + +import { PrometheusExporter } from "./prometheus-exporter/prometheus-exporter"; + +export interface IWebAppOptions { + port: number; + hostname: string; +} + +export interface IPluginCcTxVisualizationOptions extends ICactusPluginOptions { + prometheusExporter?: PrometheusExporter; + connectorRegistry?: PluginRegistry; + logLevel?: LogLevelDesc; + webAppOptions?: IWebAppOptions; +} + +export class PluginCcTxVisualization + implements ICactusPlugin, IPluginWebService { + public prometheusExporter: PrometheusExporter; + private readonly log: Logger; + private readonly instanceId: string; + private endpoints: IWebServiceEndpoint[] | undefined; + private httpServer: Server | SecureServer | null = null; + private connectorRegistry: PluginRegistry; + + constructor(public readonly options: IPluginCcTxVisualizationOptions) { + const fnTag = `PluginCcTxVisualization#constructor()`; + if (!options) { + throw new Error(`${fnTag} options falsy.`); + } + Checks.truthy(options.instanceId, `${fnTag} options.instanceId`); + this.log = LoggerProvider.getOrCreate({ + label: "plugin-cc-tx-visualization", + }); + this.instanceId = this.options.instanceId; + this.prometheusExporter = + options.prometheusExporter || + new PrometheusExporter({ pollingIntervalInMin: 1 }); + Checks.truthy( + this.prometheusExporter, + `${fnTag} options.prometheusExporter`, + ); + Checks.truthy( + options.connectorRegistry, + `${fnTag} options.connectorRegistry`, + ); + if (options.connectorRegistry) + this.connectorRegistry = options.connectorRegistry; + else this.connectorRegistry = new PluginRegistry(); + // this.prometheusExporter.setNodeCount(this.getNodeCount()); + } + + public getInstanceId(): string { + return this.instanceId; + } + + public async onPluginInit(): Promise { + return; + } + + public getPrometheusExporter(): PrometheusExporter { + return this.prometheusExporter; + } + + public async getPrometheusExporterMetrics(): Promise { + const res: string = await this.prometheusExporter.getPrometheusMetrics(); + this.log.debug(`getPrometheusExporterMetrics() response: %o`, res); + return res; + } + + // public getNodeCount(): number { + // const consortiumDatabase: ConsortiumDatabase = this.options + // .consortiumDatabase; + // const consortiumRepo: ConsortiumRepository = new ConsortiumRepository({ + // db: consortiumDatabase, + // }); + // return consortiumRepo.allNodes.length; + // } + + /** + * Updates the Node count Prometheus metric of the plugin. + * Note: This does not change the underlying consortium database at all, + * only affects **the metrics**. + */ + // public updateMetricNodeCount(): void { + // const consortiumDatabase: ConsortiumDatabase = this.options + // .consortiumDatabase; + // const consortiumRepo: ConsortiumRepository = new ConsortiumRepository({ + // db: consortiumDatabase, + // }); + // this.prometheusExporter.setNodeCount(consortiumRepo.allNodes.length); + // } + + public async shutdown(): Promise { + this.log.info(`Shutting down...`); + const serverMaybe = this.getHttpServer(); + if (serverMaybe.isPresent()) { + this.log.info(`Awaiting server.close() ...`); + const server = serverMaybe.get(); + await promisify(server.close.bind(server))(); + this.log.info(`server.close() OK`); + } else { + this.log.info(`No HTTP server found, skipping...`); + } + } + + public async registerWebServices( + app: Express, + ): Promise { + const webApp: Express = this.options.webAppOptions ? express() : app; + + if (this.options.webAppOptions) { + this.log.info(`Creating dedicated HTTP server...`); + const { port, hostname } = this.options.webAppOptions; + + webApp.use(bodyParser.json({ limit: "50mb" })); + + const address = await new Promise((resolve, reject) => { + const httpServer = webApp.listen(port, hostname, (err?: any) => { + if (err) { + reject(err); + this.log.error(`Failed to create dedicated HTTP server`, err); + } else { + this.httpServer = httpServer; + const theAddress = this.httpServer.address(); + resolve(theAddress); + } + }); + }); + this.log.info(`Creation of HTTP server OK`, { address }); + } + + const webServices = await this.getOrCreateWebServices(); + webServices.forEach((ws) => ws.registerExpress(webApp)); + return webServices; + } + + public async getOrCreateWebServices(): Promise { + const { log } = this; + const pkgName = this.getPackageName(); + + if (this.endpoints) { + return this.endpoints; + } + // log.info(`Creating web services for plugin ${pkgName}...`); + // // presence of webAppOptions implies that caller wants the plugin to configure it's own express instance on a custom + // // host/port to listen on + + // const { consortiumDatabase, keyPairPem } = this.options; + // const consortiumRepo = new ConsortiumRepository({ + // db: consortiumDatabase, + // }); + + const endpoints: IWebServiceEndpoint[] = []; + // { + // const options = { keyPairPem, consortiumRepo, plugin: this }; + // const endpoint = new GetConsortiumEndpointV1(options); + // endpoints.push(endpoint); + // const path = endpoint.getPath(); + // this.log.info(`Instantiated GetConsortiumEndpointV1 at ${path}`); + // } + // { + // const options = { keyPairPem, consortiumRepo, plugin: this }; + // const endpoint = new GetNodeJwsEndpoint(options); + // const path = endpoint.getPath(); + // endpoints.push(endpoint); + // this.log.info(`Instantiated GetNodeJwsEndpoint at ${path}`); + // } + // { + // const opts: IGetPrometheusExporterMetricsEndpointV1Options = { + // plugin: this, + // logLevel: this.options.logLevel, + // }; + // const endpoint = new GetPrometheusExporterMetricsEndpointV1(opts); + // const path = endpoint.getPath(); + // endpoints.push(endpoint); + // this.log.info(`Instantiated GetNodeJwsEndpoint at ${path}`); + // } + this.endpoints = endpoints; + + log.info(`Instantiated web svcs for plugin ${pkgName} OK`, { endpoints }); + return this.endpoints; + } + + public getHttpServer(): Optional { + return Optional.ofNullable(this.httpServer); + } + + public getPackageName(): string { + return `@hyperledger/cactus-plugin-cc-tx-visualization`; + } +} diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/plugin-factory-cc-tx-visualization.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/plugin-factory-cc-tx-visualization.ts new file mode 100644 index 00000000000..2d55b2f8c58 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/plugin-factory-cc-tx-visualization.ts @@ -0,0 +1,20 @@ +import { + IPluginFactoryOptions, + PluginFactory, +} from "@hyperledger/cactus-core-api"; +import { + IPluginCcTxVisualizationOptions, + PluginCcTxVisualization, +} from "./plugin-cc-tx-visualization"; + +export class PluginFactoryWebService extends PluginFactory< + PluginCcTxVisualization, + IPluginCcTxVisualizationOptions, + IPluginFactoryOptions +> { + async create( + pluginOptions: IPluginCcTxVisualizationOptions, + ): Promise { + return new PluginCcTxVisualization(pluginOptions); + } +} diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/data-fetcher.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/data-fetcher.ts new file mode 100644 index 00000000000..55869bf1cfe --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/data-fetcher.ts @@ -0,0 +1,12 @@ +import { NodeCount } from "./response.type"; + +import { + totalTxCount, + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT, +} from "./metrics"; + +export async function collectMetrics(nodeCount: NodeCount): Promise { + totalTxCount + .labels(K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT) + .set(nodeCount.counter); +} diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/metrics.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/metrics.ts new file mode 100644 index 00000000000..55d35149ed6 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/metrics.ts @@ -0,0 +1,10 @@ +import { Gauge } from "prom-client"; + +export const K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT = + "cactus_consortium_manual_total_node_count"; + +export const totalTxCount = new Gauge({ + name: K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT, + help: "Total cactus node count", + labelNames: ["type"], +}); diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/prometheus-exporter.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/prometheus-exporter.ts new file mode 100644 index 00000000000..4208c863598 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/prometheus-exporter.ts @@ -0,0 +1,42 @@ +import promClient from "prom-client"; +import { NodeCount } from "./response.type"; +import { + totalTxCount, + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT, +} from "./metrics"; + +export interface IPrometheusExporterOptions { + pollingIntervalInMin?: number; +} + +export class PrometheusExporter { + public readonly metricsPollingIntervalInMin: number; + public readonly nodeCount: NodeCount = { counter: 0 }; + + constructor( + public readonly prometheusExporterOptions: IPrometheusExporterOptions, + ) { + this.metricsPollingIntervalInMin = + prometheusExporterOptions.pollingIntervalInMin || 1; + } + + public setNodeCount(nodeCount: number): void { + this.nodeCount.counter = nodeCount; + totalTxCount + .labels(K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT) + .set(this.nodeCount.counter); + } + + public async getPrometheusMetrics(): Promise { + const result = await promClient.register.getSingleMetricAsString( + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT, + ); + return result; + } + + public startMetricsCollection(): void { + const Registry = promClient.Registry; + const register = new Registry(); + promClient.collectDefaultMetrics({ register }); + } +} diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/response.type.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/response.type.ts new file mode 100644 index 00000000000..4f2cf2ac0c9 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/prometheus-exporter/response.type.ts @@ -0,0 +1,3 @@ +export type NodeCount = { + counter: number; +}; diff --git a/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/public-api.ts b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/public-api.ts new file mode 100755 index 00000000000..495ae58ed4e --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/main/typescript/public-api.ts @@ -0,0 +1,18 @@ +export { + PluginCcTxVisualization, + IPluginCcTxVisualizationOptions, + IWebAppOptions, +} from "./plugin-cc-tx-visualization"; + +export * from "./generated/openapi/typescript-axios/index"; + +export { PluginFactoryWebService } from "./plugin-factory-cc-tx-visualization"; + +import { IPluginFactoryOptions } from "@hyperledger/cactus-core-api"; +import { PluginFactoryWebService } from "./plugin-factory-cc-tx-visualization"; + +export async function createPluginFactory( + pluginFactoryOptions: IPluginFactoryOptions, +): Promise { + return new PluginFactoryWebService(pluginFactoryOptions); +} diff --git a/packages/cactus-plugin-cc-tx-visualization/src/test/typescript/integration/api-surface.test.ts b/packages/cactus-plugin-cc-tx-visualization/src/test/typescript/integration/api-surface.test.ts new file mode 100644 index 00000000000..a77b09a8292 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/test/typescript/integration/api-surface.test.ts @@ -0,0 +1,8 @@ +import test, { Test } from "tape-promise/tape"; + +import * as apiSurface from "../../../main/typescript/public-api"; + +test("Library can be loaded", (t: Test) => { + t.ok(apiSurface, "apiSurface truthy OK"); + t.end(); +}); diff --git a/packages/cactus-plugin-cc-tx-visualization/src/test/typescript/unit/api-surface.test.ts b/packages/cactus-plugin-cc-tx-visualization/src/test/typescript/unit/api-surface.test.ts new file mode 100644 index 00000000000..a77b09a8292 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/test/typescript/unit/api-surface.test.ts @@ -0,0 +1,8 @@ +import test, { Test } from "tape-promise/tape"; + +import * as apiSurface from "../../../main/typescript/public-api"; + +test("Library can be loaded", (t: Test) => { + t.ok(apiSurface, "apiSurface truthy OK"); + t.end(); +}); diff --git a/packages/cactus-plugin-cc-tx-visualization/src/test/typescript/unit/instantiation.test.ts b/packages/cactus-plugin-cc-tx-visualization/src/test/typescript/unit/instantiation.test.ts new file mode 100644 index 00000000000..3a0170594ed --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/src/test/typescript/unit/instantiation.test.ts @@ -0,0 +1,18 @@ +import test, { Test } from "tape"; +import { v4 as uuidv4 } from "uuid"; +import { + IPluginCcTxVisualizationOptions, + PluginCcTxVisualization, +} from "../../../main/typescript/plugin-cc-tx-visualization"; + +test("Instantiation", (t: Test) => { + const options: IPluginCcTxVisualizationOptions = { + instanceId: uuidv4(), + }; + + const pluginCcTxVisualization: PluginCcTxVisualization = new PluginCcTxVisualization( + options, + ); + + t.ok(pluginCcTxVisualization, "Instantiated"); +}); diff --git a/packages/cactus-plugin-cc-tx-visualization/tsconfig.json b/packages/cactus-plugin-cc-tx-visualization/tsconfig.json new file mode 100644 index 00000000000..1c303ca3370 --- /dev/null +++ b/packages/cactus-plugin-cc-tx-visualization/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./dist/lib/", + "declarationDir": "dist/types", + "rootDir": "./src", + "tsBuildInfoFile": "../../.build-cache/cactus-plugin-cc-tx-visualization.tsbuildinfo" + }, + "include": [ + "./src", + "**/openapi.json" + ], + "references": [ + { + "path": "../cactus-common/tsconfig.json" + }, + { + "path": "../cactus-core/tsconfig.json" + }, + { + "path": "../cactus-core-api/tsconfig.json" + } + ] +} \ No newline at end of file