From a5affc526123769cafa878d6a29312596511688e Mon Sep 17 00:00:00 2001 From: Jagpreet Singh Sasan Date: Mon, 29 Mar 2021 16:11:59 -0700 Subject: [PATCH] feat(keychain-memory): add prometheus exporter Primary Change -------------- 1. The keychain-memory 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. GetPrometheusMetricsV1 class is created to handle the corresponding api endpoint 4. IPluginKeychainMemoryOptions interface in PluginKeychainMemory class now has a prometheusExporter optional field 5. The PluginKeychainMemory class has relevant functions and codes to incorporate prometheus exporter 6. deploy-contract-from-json.test.ts is changed to incorporate the prometheus exporter 7. Added Readme.md on the prometheus exporter usage Fixes #537 Signed-off-by: Jagpreet Singh Sasan --- .../cactus-plugin-keychain-memory/README.md | 40 +- .../package-lock.json | 476 ++++++++++++++++++ .../package.json | 12 +- .../src/main/json/openapi.json | 210 ++++++++ .../.openapi-generator-ignore | 27 + .../typescript-axios/.openapi-generator/FILES | 4 + .../.openapi-generator/VERSION | 1 + .../generated/openapi/typescript-axios/api.ts | 191 +++++++ .../openapi/typescript-axios/base.ts | 71 +++ .../openapi/typescript-axios/configuration.ts | 76 +++ .../openapi/typescript-axios/index.ts | 18 + ...prometheus-exporter-metrics-endpoint-v1.ts | 81 +++ .../main/typescript/plugin-keychain-memory.ts | 54 ++ .../prometheus-exporter/data-fetcher.ts | 12 + .../typescript/prometheus-exporter/metrics.ts | 10 + .../prometheus-exporter.ts | 37 ++ .../prometheus-exporter/response.type.ts | 3 + .../src/main/typescript/public-api.ts | 1 + .../unit/plugin-keychain-memory.test.ts | 113 ++++- 19 files changed, 1418 insertions(+), 19 deletions(-) create mode 100644 packages/cactus-plugin-keychain-memory/src/main/json/openapi.json create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator-ignore create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/api.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/base.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/configuration.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/index.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/get-prometheus-exporter-metrics/get-prometheus-exporter-metrics-endpoint-v1.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/data-fetcher.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/metrics.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/prometheus-exporter.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/response.type.ts diff --git a/packages/cactus-plugin-keychain-memory/README.md b/packages/cactus-plugin-keychain-memory/README.md index fa4a2c57af..8a9a930bd1 100644 --- a/packages/cactus-plugin-keychain-memory/README.md +++ b/packages/cactus-plugin-keychain-memory/README.md @@ -1,9 +1,41 @@ # `@hyperledger/cactus-plugin-keychain-memory` -> TODO: description +## Prometheus Exporter -## Usage +This class creates a prometheus exporter, which scrapes the transactions (total transaction count) for the use cases incorporating the use of Keychain memory plugin. + +### Usage +The prometheus exporter object is initialized in the `PluginKeychainMemory` class constructor itself, so instantiating the object of the `PluginKeychainMemory` class, gives access to the exporter object. +You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginKeychainMemoryOptions` interface for `PluginKeychainMemory` constructor. + +`getPrometheusExporterMetricsV1` function returns the prometheus exporter metrics, currently displaying the total key count, which currently updates everytime a new key is added/removed from the list of total keys. + +### 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: 'keychain_memory_exporter' + metrics_path: api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics + scrape_interval: 5s + static_configs: + - targets: ['{host}:{port}'] ``` -// TODO: DEMONSTRATE API -``` + +Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-keychain-memory/src/test/typescript/unit/plugin-keychain-memory.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-keychain-plugin/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_keychain_memory_total_key_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. diff --git a/packages/cactus-plugin-keychain-memory/package-lock.json b/packages/cactus-plugin-keychain-memory/package-lock.json index b9dc24ea1c..61c6c2eda6 100644 --- a/packages/cactus-plugin-keychain-memory/package-lock.json +++ b/packages/cactus-plugin-keychain-memory/package-lock.json @@ -4,23 +4,305 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", + "integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.8", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz", + "integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.18", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz", + "integrity": "sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, "@types/joi": { "version": "14.3.4", "resolved": "https://registry.npmjs.org/@types/joi/-/joi-14.3.4.tgz", "integrity": "sha512-1TQNDJvIKlgYXGNIABfgFp9y0FziDpuGrd799Q5RcnsDu+krD+eeW/0Fs5PHARvWWFelOhIG2OPCo6KbadBM4A==", "dev": true }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "@types/node": { + "version": "14.14.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", + "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", + "dev": true + }, + "@types/qs": { + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", + "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.9", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz", + "integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "@types/uuid": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz", "integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==", "dev": true }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "requires": { + "follow-redirects": "^1.10.0" + } + }, + "bintrees": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", + "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "follow-redirects": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", + "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==" + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, "hoek": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==" }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, "isemail": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", @@ -39,11 +321,181 @@ "topo": "3.x.x" } }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" + }, + "mime-types": { + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "requires": { + "mime-db": "1.46.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "prom-client": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-13.1.0.tgz", + "integrity": "sha512-jT9VccZCWrJWXdyEtQddCDszYsiuWj5T0ekrPszi/WEegj3IZy6Mm09iOOVM86A4IKMWq8hZkT2dD9MaSe+sng==", + "requires": { + "tdigest": "^0.1.1" + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "tdigest": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", + "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", + "requires": { + "bintrees": "1.0.1" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, "topo": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz", @@ -52,15 +504,39 @@ "hoek": "6.x.x" } }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, "typescript-optional": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/typescript-optional/-/typescript-optional-2.0.1.tgz", "integrity": "sha512-xuwmqsCjE4OeeMKxbNX3jjNcISGzYh5Q9R1rM5OyxEVNIr94CB5llCkfKW+1nZTKbbUV0axN3QAUuX2fus/DhQ==" }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" } } } diff --git a/packages/cactus-plugin-keychain-memory/package.json b/packages/cactus-plugin-keychain-memory/package.json index 316e2c218a..0cd7c3cdc9 100644 --- a/packages/cactus-plugin-keychain-memory/package.json +++ b/packages/cactus-plugin-keychain-memory/package.json @@ -12,6 +12,8 @@ "dist/*" ], "scripts": { + "generate-sdk": "openapi-generator generate --input-spec src/main/json/openapi.json -g typescript-axios -o ./src/main/typescript/generated/openapi/typescript-axios/ --reserved-words-mappings protected=protected", + "pretsc": "npm run generate-sdk", "tsc": "tsc --project ./tsconfig.json", "watch": "npm-watch", "webpack": "npm-run-all webpack:dev webpack:prod", @@ -31,7 +33,10 @@ "ignore": [ "src/**/generated/*" ], - "extensions": ["ts", "json"], + "extensions": [ + "ts", + "json" + ], "quiet": true, "verbose": false, "runOnChangeOnly": true @@ -79,12 +84,17 @@ "homepage": "https://github.com/hyperledger/cactus#readme", "dependencies": { "@hyperledger/cactus-common": "0.3.0", + "@hyperledger/cactus-core": "0.3.0", "@hyperledger/cactus-core-api": "0.3.0", + "axios": "0.21.1", + "express": "4.17.1", "joi": "14.3.1", + "prom-client": "13.1.0", "typescript-optional": "2.0.1", "uuid": "8.3.2" }, "devDependencies": { + "@types/express": "4.17.8", "@types/joi": "14.3.4", "@types/uuid": "8.3.0" } diff --git a/packages/cactus-plugin-keychain-memory/src/main/json/openapi.json b/packages/cactus-plugin-keychain-memory/src/main/json/openapi.json new file mode 100644 index 0000000000..9732fa4e78 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/json/openapi.json @@ -0,0 +1,210 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Hyperledger Cactus Plugin - Keychain Memory ", + "description": "Contains/describes the Hyperledger Cactus Keychain Memory plugin.", + "version": "0.2.0", + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "servers": [ + { + "url": "https://www.cactus.stream/{basePath}", + "description": "Public test instance", + "variables": { + "basePath": { + "default": "" + } + } + }, + { + "url": "http://localhost:4000/{basePath}", + "description": "Local test instance", + "variables": { + "basePath": { + "default": "" + } + } + } + ], + "components": { + "schemas": { + "GetKeychainEntryRequest": { + "type": "object", + "required": [ + "key" + ], + "properties": { + "key": { + "type": "string", + "description": "The key for the entry to get from the keychain.", + "minLength": 1, + "maxLength": 1024, + "nullable": false + } + } + }, + "GetKeychainEntryResponse": { + "type": "object", + "required": [ + "key", + "value" + ], + "properties": { + "key": { + "type": "string", + "description": "The key that was used to retrieve the value from the keychain.", + "minLength": 1, + "maxLength": 1024, + "nullable": false + }, + "value": { + "type": "string", + "description": "The value associated with the requested key on the keychain.", + "minLength": 0, + "maxLength": 10485760, + "nullable": false + } + } + }, + "SetKeychainEntryRequest": { + "type": "object", + "required": [ + "key", + "value" + ], + "properties": { + "key": { + "type": "string", + "description": "The key for the entry to set on the keychain.", + "minLength": 1, + "maxLength": 1024, + "nullable": false + }, + "value": { + "type": "string", + "description": "The value that will be associated with the key on the keychain.", + "minLength": 0, + "maxLength": 10485760, + "nullable": false + } + } + }, + "SetKeychainEntryResponse": { + "type": "object", + "required": [ + "key" + ], + "properties": { + "key": { + "type": "string", + "description": "The key that was used to set the value on the keychain.", + "minLength": 1, + "maxLength": 1024, + "nullable": false + } + } + }, + "PrometheusExporterMetricsResponse": { + "type": "string", + "nullable": false + } + }, + "requestBodies": { + "keychain_get_entry_request_body": { + "description": "Requst body to obtain a keychain entry via its key", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetKeychainEntryRequest" + } + } + } + }, + "keychain_set_entry_request_body": { + "description": "Requst body to write/update a keychain entry via its key", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetKeychainEntryRequest" + } + } + } + } + }, + "responses": { + "keychain_get_entry_200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetKeychainEntryResponse" + } + } + } + }, + "keychain_get_entry_400": { + "description": "Bad request. Key must be a string and longer than 0, shorter than 1024 characters." + }, + "keychain_get_entry_401": { + "description": "Authorization information is missing or invalid." + }, + "keychain_get_entry_404": { + "description": "A keychain item with the specified key was not found." + }, + "keychain_get_entry_500": { + "description": "Unexpected error." + }, + "keychain_set_entry_200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetKeychainEntryResponse" + } + } + } + }, + "keychain_set_entry_400": { + "description": "Bad request. Key must be a string and longer than 0, shorter than 1024 characters." + }, + "keychain_set_entry_401": { + "description": "Authorization information is missing or invalid." + }, + "keychain_set_entry_500": { + "description": "Unexpected error." + } + } + }, + "paths": { + "/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics": { + "get": { + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "get", + "path": "/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics" + } + }, + "operationId": "getPrometheusExporterMetricsV1", + "summary": "Get the Prometheus Metrics", + "parameters": [], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/PrometheusExporterMetricsResponse" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator-ignore b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator-ignore new file mode 100644 index 0000000000..9548c6c685 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator-ignore @@ -0,0 +1,27 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md + +.gitignore +.npmignore +git_push.sh \ No newline at end of file diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES new file mode 100644 index 0000000000..c123dd7d45 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES @@ -0,0 +1,4 @@ +api.ts +base.ts +configuration.ts +index.ts diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION new file mode 100644 index 0000000000..1a487e1a2e --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION @@ -0,0 +1 @@ +5.0.0-beta2 \ No newline at end of file diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/api.ts new file mode 100644 index 0000000000..f63294c91a --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/api.ts @@ -0,0 +1,191 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Keychain Memory + * Contains/describes the Hyperledger Cactus Keychain Memory plugin. + * + * The version of the OpenAPI document: 0.2.0 + * + * + * 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 { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from './base'; + +/** + * + * @export + * @interface GetKeychainEntryRequest + */ +export interface GetKeychainEntryRequest { + /** + * The key for the entry to get from the keychain. + * @type {string} + * @memberof GetKeychainEntryRequest + */ + key: string; +} +/** + * + * @export + * @interface GetKeychainEntryResponse + */ +export interface GetKeychainEntryResponse { + /** + * The key that was used to retrieve the value from the keychain. + * @type {string} + * @memberof GetKeychainEntryResponse + */ + key: string; + /** + * The value associated with the requested key on the keychain. + * @type {string} + * @memberof GetKeychainEntryResponse + */ + value: string; +} +/** + * + * @export + * @interface SetKeychainEntryRequest + */ +export interface SetKeychainEntryRequest { + /** + * The key for the entry to set on the keychain. + * @type {string} + * @memberof SetKeychainEntryRequest + */ + key: string; + /** + * The value that will be associated with the key on the keychain. + * @type {string} + * @memberof SetKeychainEntryRequest + */ + value: string; +} +/** + * + * @export + * @interface SetKeychainEntryResponse + */ +export interface SetKeychainEntryResponse { + /** + * The key that was used to set the value on the keychain. + * @type {string} + * @memberof SetKeychainEntryResponse + */ + key: string; +} + +/** + * DefaultApi - axios parameter creator + * @export + */ +export const DefaultApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPrometheusExporterMetricsV1: async (options: any = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.query) { + query.set(key, options.query[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * DefaultApi - functional programming interface + * @export + */ +export const DefaultApiFp = function(configuration?: Configuration) { + return { + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getPrometheusExporterMetricsV1(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await DefaultApiAxiosParamCreator(configuration).getPrometheusExporterMetricsV1(options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + } +}; + +/** + * DefaultApi - factory interface + * @export + */ +export const DefaultApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + return { + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPrometheusExporterMetricsV1(options?: any): AxiosPromise { + return DefaultApiFp(configuration).getPrometheusExporterMetricsV1(options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * DefaultApi - object-oriented interface + * @export + * @class DefaultApi + * @extends {BaseAPI} + */ +export class DefaultApi extends BaseAPI { + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public getPrometheusExporterMetricsV1(options?: any) { + return DefaultApiFp(this.configuration).getPrometheusExporterMetricsV1(options).then((request) => request(this.axios, this.basePath)); + } +} + + diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/base.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/base.ts new file mode 100644 index 0000000000..85dd928e53 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/base.ts @@ -0,0 +1,71 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Keychain Memory + * Contains/describes the Hyperledger Cactus Keychain Memory plugin. + * + * The version of the OpenAPI document: 0.2.0 + * + * + * 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-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/configuration.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/configuration.ts new file mode 100644 index 0000000000..00e20b6221 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/configuration.ts @@ -0,0 +1,76 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Keychain Memory + * Contains/describes the Hyperledger Cactus Keychain Memory plugin. + * + * The version of the OpenAPI document: 0.2.0 + * + * + * 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; +} + +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; + + 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; + } +} diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/index.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/index.ts new file mode 100644 index 0000000000..81e16776d6 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/index.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Keychain Memory + * Contains/describes the Hyperledger Cactus Keychain Memory plugin. + * + * The version of the OpenAPI document: 0.2.0 + * + * + * 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-keychain-memory/src/main/typescript/get-prometheus-exporter-metrics/get-prometheus-exporter-metrics-endpoint-v1.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/get-prometheus-exporter-metrics/get-prometheus-exporter-metrics-endpoint-v1.ts new file mode 100644 index 0000000000..c1bff16ad5 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/get-prometheus-exporter-metrics/get-prometheus-exporter-metrics-endpoint-v1.ts @@ -0,0 +1,81 @@ +import { Express, Request, Response } from "express"; + +import { + Logger, + LoggerProvider, + LogLevelDesc, + Checks, +} from "@hyperledger/cactus-common"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, +} from "@hyperledger/cactus-core-api/"; + +import OAS from "../../json/openapi.json"; + +import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; + +import { PluginKeychainMemory } from "../plugin-keychain-memory"; + +export interface IGetPrometheusExporterMetricsEndpointV1Options { + logLevel?: LogLevelDesc; + plugin: PluginKeychainMemory; +} + +export class GetPrometheusExporterMetricsEndpointV1 + implements IWebServiceEndpoint { + private readonly log: Logger; + + constructor( + public readonly opts: IGetPrometheusExporterMetricsEndpointV1Options, + ) { + const fnTag = "GetPrometheusExporterMetricsEndpointV1#constructor()"; + + Checks.truthy(opts, `${fnTag} options`); + Checks.truthy(opts.plugin, `${fnTag} options.plugin`); + + this.log = LoggerProvider.getOrCreate({ + label: "get-prometheus-exporter-metrics-v1", + level: opts.logLevel || "INFO", + }); + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public getPath(): string { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics" + ].get["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics" + ].get["x-hyperledger-cactus"].http.verbLowerCase; + } + + public registerExpress(app: Express): IWebServiceEndpoint { + registerWebServiceEndpoint(app, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = "GetPrometheusExporterMetrics#handleRequest()"; + const verbUpper = this.getVerbLowerCase().toUpperCase(); + this.log.debug(`${verbUpper} ${this.getPath()}`); + + try { + const resBody = await this.opts.plugin.getPrometheusExporterMetrics(); + res.status(200); + res.send(resBody); + } catch (ex) { + this.log.error(`${fnTag} failed to serve request`, ex); + res.status(500); + res.statusMessage = ex.message; + res.json({ error: ex.stack }); + } + } +} diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/plugin-keychain-memory.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/plugin-keychain-memory.ts index 1751771ae1..9ee54f69be 100644 --- a/packages/cactus-plugin-keychain-memory/src/main/typescript/plugin-keychain-memory.ts +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/plugin-keychain-memory.ts @@ -7,12 +7,22 @@ import { import { ICactusPluginOptions, PluginAspect, + IWebServiceEndpoint, } from "@hyperledger/cactus-core-api"; +import { PrometheusExporter } from "./prometheus-exporter/prometheus-exporter"; +import { Express } from "express"; + +import { + IGetPrometheusExporterMetricsEndpointV1Options, + GetPrometheusExporterMetricsEndpointV1, +} from "./get-prometheus-exporter-metrics/get-prometheus-exporter-metrics-endpoint-v1"; + export interface IPluginKeychainMemoryOptions extends ICactusPluginOptions { logLevel?: LogLevelDesc; backend?: Map; keychainId: string; + prometheusExporter?: PrometheusExporter; } export class PluginKeychainMemory { @@ -21,6 +31,7 @@ export class PluginKeychainMemory { private readonly backend: Map; private readonly log: Logger; private readonly instanceId: string; + public prometheusExporter: PrometheusExporter; public get className(): string { return PluginKeychainMemory.CLASS_NAME; @@ -41,6 +52,13 @@ export class PluginKeychainMemory { this.log = LoggerProvider.getOrCreate({ level, label }); this.instanceId = this.opts.instanceId; + this.prometheusExporter = + opts.prometheusExporter || + new PrometheusExporter({ pollingIntervalInMin: 1 }); + Checks.truthy( + this.prometheusExporter, + `${fnTag} options.prometheusExporter`, + ); this.log.info(`Created ${this.className}. KeychainID=${opts.keychainId}`); this.log.warn( @@ -49,6 +67,40 @@ export class PluginKeychainMemory { ); } + 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 async installWebServices( + expressApp: Express, + ): Promise { + const { log } = this; + + log.info(`Installing web services for plugin ${this.getPackageName()}...`); + + const endpoints: IWebServiceEndpoint[] = []; + { + const opts: IGetPrometheusExporterMetricsEndpointV1Options = { + plugin: this, + logLevel: this.opts.logLevel, + }; + const endpoint = new GetPrometheusExporterMetricsEndpointV1(opts); + endpoint.registerExpress(expressApp); + endpoints.push(endpoint); + } + + const pkg = this.getPackageName(); + log.info(`Installed web services for plugin ${pkg} OK`, { endpoints }); + + return endpoints; + } + public getInstanceId(): string { return this.instanceId; } @@ -75,9 +127,11 @@ export class PluginKeychainMemory { async set(key: string, value: T): Promise { this.backend.set(key, value); + this.prometheusExporter.setTotalKeyCounter(this.backend.size); } async delete(key: string): Promise { this.backend.delete(key); + this.prometheusExporter.setTotalKeyCounter(this.backend.size); } } diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/data-fetcher.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/data-fetcher.ts new file mode 100644 index 0000000000..7de725fc74 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/data-fetcher.ts @@ -0,0 +1,12 @@ +import { KeyCount } from "./response.type"; + +import { + totalKeyCount, + K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT, +} from "./metrics"; + +export async function collectMetrics(keyCount: KeyCount) { + totalKeyCount + .labels(`${K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT}`) + .set(keyCount.counter); +} diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/metrics.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/metrics.ts new file mode 100644 index 0000000000..cf20d28cc9 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/metrics.ts @@ -0,0 +1,10 @@ +import { Gauge } from "prom-client"; + +export const K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT = + "cactus_keychain_memory_total_key_count"; + +export const totalKeyCount = new Gauge({ + name: K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT, + help: "Total keys present in memory", + labelNames: ["type"], +}); diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/prometheus-exporter.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/prometheus-exporter.ts new file mode 100644 index 0000000000..4e3c22985b --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/prometheus-exporter.ts @@ -0,0 +1,37 @@ +import promClient from "prom-client"; +import { KeyCount } from "./response.type"; +import { collectMetrics } from "./data-fetcher"; +import { K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT } from "./metrics"; +export interface IPrometheusExporterOptions { + pollingIntervalInMin?: number; +} + +export class PrometheusExporter { + public readonly metricsPollingIntervalInMin: number; + public readonly keyCount: KeyCount = { counter: 0 }; + + constructor( + public readonly prometheusExporterOptions: IPrometheusExporterOptions, + ) { + this.metricsPollingIntervalInMin = + prometheusExporterOptions.pollingIntervalInMin || 1; + } + + public setTotalKeyCounter(keyCount: number): void { + this.keyCount.counter = keyCount; + collectMetrics(this.keyCount); + } + + public async getPrometheusMetrics(): Promise { + const result = await promClient.register.getSingleMetricAsString( + K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT, + ); + return result; + } + + public startMetricsCollection(): void { + const Registry = promClient.Registry; + const register = new Registry(); + promClient.collectDefaultMetrics({ register }); + } +} diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/response.type.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/response.type.ts new file mode 100644 index 0000000000..0c60f06d2e --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/response.type.ts @@ -0,0 +1,3 @@ +export type KeyCount = { + counter: number; +}; diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/public-api.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/public-api.ts index eb339c2fe5..1017146dca 100755 --- a/packages/cactus-plugin-keychain-memory/src/main/typescript/public-api.ts +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/public-api.ts @@ -1,3 +1,4 @@ +export * from "./generated/openapi/typescript-axios/index"; import { IPluginFactoryOptions } from "@hyperledger/cactus-core-api"; export { diff --git a/packages/cactus-plugin-keychain-memory/src/test/typescript/unit/plugin-keychain-memory.test.ts b/packages/cactus-plugin-keychain-memory/src/test/typescript/unit/plugin-keychain-memory.test.ts index c1ade2e9ec..6f091dfbce 100644 --- a/packages/cactus-plugin-keychain-memory/src/test/typescript/unit/plugin-keychain-memory.test.ts +++ b/packages/cactus-plugin-keychain-memory/src/test/typescript/unit/plugin-keychain-memory.test.ts @@ -1,11 +1,22 @@ import test, { Test } from "tape-promise/tape"; +import express from "express"; +import bodyParser from "body-parser"; +import http from "http"; +import { AddressInfo } from "net"; + +import { IListenOptions, Servers } from "@hyperledger/cactus-common"; + import { v4 as uuidv4 } from "uuid"; import { IPluginKeychainMemoryOptions, PluginKeychainMemory, } from "../../../main/typescript"; +import { K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT } from "../../../main/typescript/prometheus-exporter/metrics"; + +import { DefaultApi as KeychainMemoryApi } from "../../../main/typescript/public-api"; + test("PluginKeychainMemory", (t1: Test) => { t1.doesNotThrow( () => new PluginKeychainMemory({ instanceId: "a", keychainId: "a" }), @@ -53,31 +64,105 @@ test("PluginKeychainMemory", (t1: Test) => { keychainId: uuidv4(), }; const plugin = new PluginKeychainMemory(options); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + const server = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "0.0.0.0", + port: 0, + server, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + test.onFinish(async () => await Servers.shutdown(server)); + const { address, port } = addressInfo; + const apiHost = `http://${address}:${port}`; + t.comment( + `Metrics URL: ${apiHost}/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics`, + ); + const apiClient = new KeychainMemoryApi({ basePath: apiHost }); + + await plugin.installWebServices(expressApp); + t.equal(plugin.getKeychainId(), options.keychainId, "Keychain ID set OK"); t.equal(plugin.getInstanceId(), options.instanceId, "Instance ID set OK"); - const key = uuidv4(); - const value = uuidv4(); + const key1 = uuidv4(); + const value1 = uuidv4(); - const hasPrior = await plugin.has(key); + const hasPrior = await plugin.has(key1); t.false(hasPrior, "hasPrior === false OK"); - await plugin.set(key, value); + await plugin.set(key1, value1); - const hasAfter = await plugin.has(key); - t.true(hasAfter, "hasAfter === true OK"); + const hasAfter1 = await plugin.has(key1); + t.true(hasAfter1, "hasAfter === true OK"); + + const valueAfter1 = await plugin.get(key1); + t.ok(valueAfter1, "valueAfter truthy OK"); + t.equal(valueAfter1, value1, "valueAfter === value OK"); + + await plugin.delete(key1); - const valueAfter = await plugin.get(key); - t.ok(valueAfter, "valueAfter truthy OK"); - t.equal(valueAfter, value, "valueAfter === value OK"); + const hasAfterDelete1 = await plugin.has(key1); + t.false(hasAfterDelete1, "hasAfterDelete === false OK"); - await plugin.delete(key); + const valueAfterDelete1 = await plugin.get(key1); + t.notok(valueAfterDelete1, "valueAfterDelete falsy OK"); + { + const res = await apiClient.getPrometheusExporterMetricsV1(); + const promMetricsOutput = + "# HELP " + + K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT + + " Total keys present in memory\n" + + "# TYPE " + + K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT + + " gauge\n" + + K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT + + '{type="' + + K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT + + '"} 0'; + t.ok(res); + t.ok(res.data); + t.equal(res.status, 200); + t.true( + res.data.includes(promMetricsOutput), + "Total Key Count 0 recorded as expected. RESULT OK", + ); + } - const hasAfterDelete = await plugin.has(key); - t.false(hasAfterDelete, "hasAfterDelete === false OK"); + const key2 = uuidv4(); + const value2 = uuidv4(); + + await plugin.set(key2, value2); + + const hasAfter = await plugin.has(key2); + t.true(hasAfter, "hasAfter === true OK"); - const valueAfterDelete = await plugin.get(key); - t.notok(valueAfterDelete, "valueAfterDelete falsy OK"); + const valueAfter2 = await plugin.get(key2); + t.ok(valueAfter2, "valueAfter truthy OK"); + t.equal(valueAfter2, value2, "valueAfter === value OK"); + { + const res = await apiClient.getPrometheusExporterMetricsV1(); + const promMetricsOutput = + "# HELP " + + K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT + + " Total keys present in memory\n" + + "# TYPE " + + K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT + + " gauge\n" + + K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT + + '{type="' + + K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT + + '"} 1'; + t.ok(res); + t.ok(res.data); + t.equal(res.status, 200); + t.true( + res.data.includes(promMetricsOutput), + "Total Key Count 1 recorded as expected. RESULT OK", + ); + } t.end(); });