@chainlink/external-adapter-framework 0.0.20 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/background-executor.d.ts +1 -3
  2. package/background-executor.js +9 -4
  3. package/cache/factory.js +0 -27
  4. package/cache/index.js +1 -16
  5. package/cache/local.js +0 -26
  6. package/cache/redis.js +0 -45
  7. package/config/index.d.ts +1 -1
  8. package/examples/coingecko/src/config/index.d.ts +2 -0
  9. package/examples/coingecko/src/config/index.js +1 -9
  10. package/examples/coingecko/src/config/overrides.json +0 -1
  11. package/examples/coingecko/src/cryptoUtils.d.ts +31 -0
  12. package/examples/coingecko/src/cryptoUtils.js +20 -1
  13. package/examples/coingecko/src/endpoint/coins.d.ts +9 -0
  14. package/examples/coingecko/src/endpoint/coins.js +3 -2
  15. package/examples/coingecko/src/endpoint/crypto-marketcap.d.ts +3 -0
  16. package/examples/coingecko/src/endpoint/crypto-marketcap.js +5 -22
  17. package/examples/coingecko/src/endpoint/crypto-volume.d.ts +3 -0
  18. package/examples/coingecko/src/endpoint/crypto-volume.js +5 -22
  19. package/examples/coingecko/src/endpoint/crypto.d.ts +3 -0
  20. package/examples/coingecko/src/endpoint/crypto.js +5 -25
  21. package/examples/coingecko/src/endpoint/dominance.d.ts +3 -0
  22. package/examples/coingecko/src/endpoint/dominance.js +4 -3
  23. package/examples/coingecko/src/endpoint/global-marketcap.d.ts +3 -0
  24. package/examples/coingecko/src/endpoint/global-marketcap.js +4 -3
  25. package/examples/coingecko/src/endpoint/index.d.ts +6 -0
  26. package/examples/coingecko/src/globalUtils.d.ts +27 -0
  27. package/examples/coingecko/src/globalUtils.js +6 -8
  28. package/examples/coingecko/src/index.d.ts +4 -0
  29. package/examples/coingecko/src/index.js +7 -3
  30. package/examples/coingecko-old/batch-warming.d.ts +7 -0
  31. package/examples/coingecko-old/index.d.ts +2 -0
  32. package/examples/coingecko-old/rest.d.ts +12 -0
  33. package/index.d.ts +2 -2
  34. package/index.js +24 -7
  35. package/metrics/index.d.ts +1 -1
  36. package/metrics/index.js +7 -3
  37. package/package.json +11 -5
  38. package/rate-limiting/index.d.ts +2 -2
  39. package/test.js +2 -2
  40. package/transports/batch-warming.d.ts +1 -1
  41. package/transports/batch-warming.js +1 -37
  42. package/transports/index.d.ts +3 -1
  43. package/transports/index.js +3 -1
  44. package/transports/metrics.d.ts +1 -1
  45. package/transports/rest.js +0 -32
  46. package/transports/util.js +0 -33
  47. package/transports/websocket.js +0 -31
  48. package/util/request.d.ts +0 -1
  49. package/validation/index.js +4 -2
@@ -11,15 +11,14 @@ exports.inputParameters = {
11
11
  required: true,
12
12
  },
13
13
  };
14
- const buildGlobalRequestBody = (config) => {
15
- const apiKey = {
16
- x_cg_pro_api_key: config.API_KEY,
17
- };
14
+ const buildGlobalRequestBody = (apiKey) => {
18
15
  return {
19
- baseURL: config.API_KEY ? config_1.PRO_API_ENDPOINT : config_1.DEFAULT_API_ENDPOINT,
16
+ baseURL: apiKey ? config_1.PRO_API_ENDPOINT : config_1.DEFAULT_API_ENDPOINT,
20
17
  url: '/global',
21
18
  method: 'GET',
22
- params: apiKey,
19
+ params: {
20
+ x_cg_pro_api_key: apiKey,
21
+ },
23
22
  };
24
23
  };
25
24
  exports.buildGlobalRequestBody = buildGlobalRequestBody;
@@ -39,10 +38,9 @@ const constructEntry = (res, requestPayload, resultPath) => {
39
38
  logger.warn(`Data for "${requestPayload.market}" not found".`);
40
39
  return;
41
40
  }
42
- const entry = {
41
+ return {
43
42
  params: requestPayload,
44
43
  value: result,
45
44
  };
46
- return entry;
47
45
  };
48
46
  exports.constructEntry = constructEntry;
@@ -0,0 +1,4 @@
1
+ /// <reference types="node" />
2
+ import { Adapter } from '../../../../src/adapter';
3
+ export declare const adapter: Adapter<import("../../../config").SettingsMap>;
4
+ export declare const server: () => Promise<import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault> | undefined>;
@@ -3,12 +3,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.adapter = void 0;
6
+ exports.server = exports.adapter = void 0;
7
+ const __1 = require("../../..");
8
+ const adapter_1 = require("../../../../src/adapter");
7
9
  const overrides_json_1 = __importDefault(require("./config/overrides.json"));
8
10
  const endpoint_1 = require("./endpoint");
9
- exports.adapter = {
11
+ exports.adapter = new adapter_1.Adapter({
10
12
  defaultEndpoint: 'crypto',
11
13
  name: 'coingecko',
12
14
  endpoints: [endpoint_1.crypto, endpoint_1.coins, endpoint_1.cryptoMarketcap, endpoint_1.cryptoVolume, endpoint_1.dominance, endpoint_1.globalMarketcap],
13
15
  overrides: overrides_json_1.default['coingecko'],
14
- };
16
+ });
17
+ const server = () => (0, __1.expose)(exports.adapter);
18
+ exports.server = server;
@@ -0,0 +1,7 @@
1
+ import { AdapterEndpoint } from '../../adapter';
2
+ interface AdapterRequestParams {
3
+ base: string;
4
+ quote: string;
5
+ }
6
+ export declare const batchEndpoint: AdapterEndpoint<AdapterRequestParams, unknown, import("../../config").SettingsMap>;
7
+ export {};
@@ -0,0 +1,2 @@
1
+ import { Adapter } from '../../adapter';
2
+ export declare const adapter: Adapter<import("../../config").SettingsMap>;
@@ -0,0 +1,12 @@
1
+ import { AdapterEndpoint } from '../../adapter';
2
+ interface AdapterRequestParams {
3
+ base: string;
4
+ quote: string;
5
+ }
6
+ interface ProviderResponseBody {
7
+ [base: string]: {
8
+ [quote: string]: number;
9
+ };
10
+ }
11
+ export declare const restEndpoint: AdapterEndpoint<AdapterRequestParams, ProviderResponseBody, import("../../config").SettingsMap>;
12
+ export {};
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Server } from 'http';
1
+ import { FastifyInstance } from 'fastify';
2
2
  import { Adapter, AdapterDependencies } from './adapter';
3
3
  /**
4
4
  * Main function for the framework.
@@ -8,4 +8,4 @@ import { Adapter, AdapterDependencies } from './adapter';
8
8
  * @param dependencies - an optional object with adapter dependencies to inject
9
9
  * @returns a Promise that resolves to the http.Server listening for connections
10
10
  */
11
- export declare const expose: (adapter: Adapter, dependencies?: Partial<AdapterDependencies> | undefined) => Promise<Server | undefined>;
11
+ export declare const expose: (adapter: Adapter, dependencies?: Partial<AdapterDependencies>) => Promise<FastifyInstance | undefined>;
package/index.js CHANGED
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.expose = void 0;
7
7
  const fastify_1 = __importDefault(require("fastify"));
8
8
  const path_1 = require("path");
9
+ const adapter_1 = require("./adapter");
9
10
  const background_executor_1 = require("./background-executor");
10
11
  const cache_1 = require("./cache");
11
12
  const metrics_1 = require("./metrics");
@@ -24,25 +25,36 @@ const VERSION = process.env['npm_package_version'];
24
25
  * @returns a Promise that resolves to the http.Server listening for connections
25
26
  */
26
27
  const expose = async (adapter, dependencies) => {
28
+ if (!(adapter instanceof adapter_1.Adapter)) {
29
+ throw new Error('The adapter has not been initialized as an instance of the Adapter class, exiting.');
30
+ }
27
31
  // Initialize adapter (create dependencies, inject them, build endpoint map, etc.)
28
32
  await adapter.initialize(dependencies);
29
- let server = undefined;
33
+ let api = undefined;
30
34
  if (adapter.config.METRICS_ENABLED && adapter.config.EXPERIMENTAL_METRICS_ENABLED) {
31
35
  (0, metrics_1.setupMetricsServer)(adapter.name, adapter.config);
32
36
  }
37
+ // Optional Promise to indicate that the API is shutting down (for us to close background executors)
38
+ let apiShutdownPromise;
33
39
  if (adapter.config.EA_MODE === 'reader' || adapter.config.EA_MODE === 'reader-writer') {
34
40
  // Main REST API server to handle incoming requests
35
- const app = await buildRestApi(adapter);
41
+ api = await buildRestApi(adapter);
42
+ // Add a hook on close to use on the background execution loop to stop it
43
+ apiShutdownPromise = new Promise((resolve) => {
44
+ api?.addHook('onClose', async () => resolve());
45
+ });
36
46
  // Start listening for incoming requests
37
47
  try {
38
- await app.listen(adapter.config.EA_PORT, adapter.config.EA_HOST);
48
+ await api.listen({
49
+ port: adapter.config.EA_PORT,
50
+ host: adapter.config.EA_HOST,
51
+ });
39
52
  }
40
53
  catch (err) {
41
54
  logger.fatal(`There was an error when starting the EA server: ${err}`);
42
55
  process.exit();
43
56
  }
44
- logger.info(`Listening on port ${app.server.address().port}`);
45
- server = app.server;
57
+ logger.info(`Listening on port ${api.server.address().port}`);
46
58
  }
47
59
  else {
48
60
  logger.info('REST API is disabled; this instance will not process incoming requests.');
@@ -50,12 +62,12 @@ const expose = async (adapter, dependencies) => {
50
62
  if (adapter.config.EA_MODE === 'writer' || adapter.config.EA_MODE === 'reader-writer') {
51
63
  // Start background loop that will take care of calling any async Transports
52
64
  logger.info('Starting background execution loop');
53
- (0, background_executor_1.callBackgroundExecutes)(adapter, server);
65
+ (0, background_executor_1.callBackgroundExecutes)(adapter, apiShutdownPromise);
54
66
  }
55
67
  else {
56
68
  logger.info('Background executor is disabled; this instance will not perform async background executes.');
57
69
  }
58
- return server;
70
+ return api;
59
71
  };
60
72
  exports.expose = expose;
61
73
  async function buildRestApi(adapter) {
@@ -66,6 +78,11 @@ async function buildRestApi(adapter) {
66
78
  });
67
79
  // Use global error handling
68
80
  app.setErrorHandler(validation_1.errorCatchingMiddleware);
81
+ // Always reply with json content
82
+ app.addHook('preHandler', (_, reply, done) => {
83
+ reply.headers({ 'content-type': 'application/json; charset=utf-8' });
84
+ done();
85
+ });
69
86
  const transportHandler = await (0, transports_1.buildTransportHandler)(adapter);
70
87
  app.register(async (router) => {
71
88
  // Set up "middlewares" (hooks in fastify)
@@ -11,5 +11,5 @@ export declare const setupMetrics: (name: string, config: AdapterConfig) => void
11
11
  * @returns the cache middleware function
12
12
  */
13
13
  export declare const buildMetricsMiddleware: (req: AdapterRequest, res: FastifyReply, done: HookHandlerDoneFunction) => void;
14
- export declare const httpRequestsTotal: client.Counter<"type" | "method" | "feed_id" | "status_code" | "provider_status_code" | "retry" | "is_cache_warming">;
14
+ export declare const httpRequestsTotal: client.Counter<"type" | "method" | "status_code" | "retry" | "is_cache_warming" | "feed_id" | "provider_status_code">;
15
15
  export declare const httpRequestDurationSeconds: client.Histogram<string>;
package/metrics/index.js CHANGED
@@ -46,7 +46,10 @@ function setupMetricsServer(name, config) {
46
46
  res.type('txt');
47
47
  res.send(await client.register.metrics());
48
48
  });
49
- metricsApp.listen(metricsPort, eaHost, () => logger.info(`Monitoring listening on port ${metricsPort}!`));
49
+ metricsApp.listen({
50
+ port: metricsPort,
51
+ host: eaHost,
52
+ }, () => logger.info(`Monitoring listening on port ${metricsPort}!`));
50
53
  }
51
54
  exports.setupMetricsServer = setupMetricsServer;
52
55
  const setupMetrics = (name, config) => {
@@ -64,8 +67,9 @@ exports.setupMetrics = setupMetrics;
64
67
  * @returns the cache middleware function
65
68
  */
66
69
  const buildMetricsMiddleware = (req, res, done) => {
67
- const feedId = req.requestContext.meta?.metrics?.feedId || 'N/A';
68
- const labels = buildHttpRequestMetricsLabel(feedId, req.requestContext.meta?.error, req.requestContext.meta?.metrics?.cacheHit);
70
+ // The request context can technically be empty if the input validation failed
71
+ const feedId = req.requestContext?.meta?.metrics?.feedId || 'N/A';
72
+ const labels = buildHttpRequestMetricsLabel(feedId, req.requestContext?.meta?.error, req.requestContext?.meta?.metrics?.cacheHit);
69
73
  // Record number of requests sent to EA
70
74
  exports.httpRequestsTotal.labels(labels).inc();
71
75
  // Record response time of request through entire EA
package/package.json CHANGED
@@ -1,31 +1,36 @@
1
1
  {
2
2
  "name": "@chainlink/external-adapter-framework",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "main": "dist/index.js",
5
5
  "license": "MIT",
6
6
  "dependencies": {
7
7
  "axios": "^0.27.2",
8
- "fastify": "^3.29.0",
8
+ "fastify": "^4.5.3",
9
9
  "ioredis": "^5.0.4",
10
10
  "pino": "^7.9.2",
11
11
  "prom-client": "13.2.0",
12
+ "supertest": "^6.2.4",
13
+ "ts-jest": "^28.0.7",
12
14
  "ts-node": "^10.9.1",
13
15
  "typescript": "^4.6.3",
14
16
  "ws": "^8.5.0"
15
17
  },
16
18
  "scripts": {
17
- "start": "ts-node src/test.ts",
18
19
  "generate-docs": "typedoc src/**/*.ts",
19
20
  "test": "LOG_LEVEL=error EA_PORT=0 c8 ava",
20
21
  "test-debug": "LOG_LEVEL=trace DEBUG=true EA_PORT=0 c8 ava --verbose",
21
22
  "build": "tsc",
22
23
  "lint": "eslint ./src && prettier --check ./src/**/*.ts",
23
- "dev": "NODE_ENV=develop tsnd --respawn --transpile-only --project tsconfig.json './src/test.ts'"
24
+ "lint-fix": "eslint --fix ./src && prettier --write ./src/**/*.ts",
25
+ "dev": "NODE_ENV=develop tsnd --respawn --transpile-only --project tsconfig.json './src/test.ts'",
26
+ "verify": "yarn lint && yarn build && yarn build -p ./test/tsconfig.json && yarn test"
24
27
  },
25
28
  "devDependencies": {
26
29
  "@sinonjs/fake-timers": "^9.1.2",
30
+ "@types/jest": "^28.1.7",
27
31
  "@types/node": "^18.6.5",
28
32
  "@types/sinonjs__fake-timers": "^8.1.2",
33
+ "@types/supertest": "^2.0.12",
29
34
  "@types/ws": "^8.5.3",
30
35
  "@typescript-eslint/eslint-plugin": "^5.17.0",
31
36
  "@typescript-eslint/parser": "^5.17.0",
@@ -34,11 +39,12 @@
34
39
  "eslint": "^8.14.0",
35
40
  "eslint-config-prettier": "^8.5.0",
36
41
  "eslint-plugin-tsdoc": "^0.2.16",
42
+ "jest": "^29.0.3",
37
43
  "mock-socket": "^9.1.3",
38
44
  "nock": "^13.2.4",
39
45
  "pino-pretty": "^7.6.0",
40
46
  "prettier": "^2.6.1",
41
- "ts-node-dev": "2.0.0",
47
+ "ts-node-dev": "^2.0.0",
42
48
  "typedoc": "^0.22.15"
43
49
  },
44
50
  "prettier": {
@@ -44,7 +44,7 @@ export interface BackgroundExecuteRateLimiter extends RateLimiter {
44
44
  * @param limits - the rate limit tier set for the adapter
45
45
  * @returns the most restrictive of the set options, in requests per second
46
46
  */
47
- export declare const consolidateTierLimits: (limits?: AdapterRateLimitTier | undefined) => number;
47
+ export declare const consolidateTierLimits: (limits?: AdapterRateLimitTier) => number;
48
48
  /**
49
49
  * Validates rate limiting tiers specified for the adapter, and returns the one to use.
50
50
  *
@@ -52,4 +52,4 @@ export declare const consolidateTierLimits: (limits?: AdapterRateLimitTier | und
52
52
  * @param tiers - the adapter config listing the different available API tiers
53
53
  * @returns the specified API tier, or a default one if none are specified
54
54
  */
55
- export declare const getRateLimitingTier: (config: AdapterConfig, tiers?: Record<string, AdapterRateLimitTier> | undefined) => AdapterRateLimitTier | undefined;
55
+ export declare const getRateLimitingTier: (config: AdapterConfig, tiers?: Record<string, AdapterRateLimitTier>) => AdapterRateLimitTier | undefined;
package/test.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const _1 = require(".");
4
- const bank_frick_1 = require("./examples/bank-frick");
4
+ const src_1 = require("./examples/coingecko/src");
5
5
  // Start sample adapter
6
- (0, _1.expose)(bank_frick_1.adapter);
6
+ (0, _1.expose)(src_1.adapter);
@@ -26,7 +26,7 @@ export declare class BatchWarmingTransport<AdapterParams, ProviderRequestBody, P
26
26
  WARMER_ACTIVE: boolean;
27
27
  constructor(config: {
28
28
  prepareRequest: (params: AdapterParams[], context: AdapterContext<CustomSettings>) => AxiosRequestConfig<ProviderRequestBody>;
29
- parseResponse: (res: AxiosResponse<ProviderResponseBody>, context: AdapterContext<CustomSettings>) => ProviderResult<AdapterParams>[];
29
+ parseResponse: (params: AdapterParams[], res: AxiosResponse<ProviderResponseBody>, context: AdapterContext<CustomSettings>) => ProviderResult<AdapterParams>[];
30
30
  });
31
31
  initialize(dependencies: AdapterDependencies): Promise<void>;
32
32
  hasBeenSetUp(req: AdapterRequest<AdapterParams>): Promise<boolean>;
@@ -1,35 +1,9 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  Object.defineProperty(exports, "__esModule", { value: true });
26
3
  exports.BatchWarmingTransport = void 0;
27
4
  const util_1 = require("../util");
28
5
  const _1 = require("./");
29
6
  const util_2 = require("./util");
30
- const rateLimitMetrics = __importStar(require("../rate-limiting/metrics"));
31
- const cacheMetrics = __importStar(require("../cache/metrics"));
32
- const WARMUP_BATCH_REQUEST_ID = '9002';
33
7
  const logger = (0, util_1.makeLogger)('BatchWarmingTransport');
34
8
  /**
35
9
  * Transport implementation that takes incoming batches requests and keeps a warm cache of values.
@@ -69,32 +43,22 @@ class BatchWarmingTransport {
69
43
  logger.debug('No entries in batch warming set, skipping');
70
44
  if (this.WARMER_ACTIVE) {
71
45
  // Decrement count when warmer changed from having entries to having none
72
- cacheMetrics.cacheWarmerCount.labels({ isBatched: 'true' }).dec();
73
46
  this.WARMER_ACTIVE = false;
74
47
  }
75
48
  return this.rateLimiter.msUntilNextExecution(context.adapterEndpoint.name);
76
49
  }
77
50
  else if (this.WARMER_ACTIVE === false) {
78
51
  // Increment count when warmer changed from having no entries to having some
79
- cacheMetrics.cacheWarmerCount.labels({ isBatched: 'true' }).inc();
80
52
  this.WARMER_ACTIVE = true;
81
53
  }
82
54
  const request = this.config.prepareRequest(entries, context);
83
55
  logger.trace('Sending request to data provider...');
84
56
  const providerResponse = await (0, util_2.axiosRequest)(request, context.adapterConfig);
85
57
  logger.debug(`Got response from provider, parsing (raw body: ${providerResponse.data})`);
86
- const results = this.config.parseResponse(providerResponse, context);
58
+ const results = this.config.parseResponse(entries, providerResponse, context);
87
59
  const adapterResponses = (0, _1.buildCacheEntriesFromResults)(results, context);
88
60
  logger.debug('Setting adapter responses in cache');
89
61
  await this.cache.setMany(adapterResponses, context.adapterConfig.CACHE_MAX_AGE);
90
- // Record cost of data provider call
91
- const cost = rateLimitMetrics.retrieveCost(providerResponse.data);
92
- rateLimitMetrics.rateLimitCreditsSpentTotal
93
- .labels({
94
- feed_id: 'N/A',
95
- participant_id: WARMUP_BATCH_REQUEST_ID,
96
- })
97
- .inc(cost);
98
62
  return this.rateLimiter.msUntilNextExecution(context.adapterEndpoint.name);
99
63
  }
100
64
  }
@@ -60,7 +60,9 @@ export interface Transport<Params, Result, CustomSettings extends SettingsMap> {
60
60
  * @param context - context for the Adapter
61
61
  * @returns a list of CacheEntries of AdapterResponses
62
62
  */
63
- export declare const buildCacheEntriesFromResults: <Params, CustomSettings extends SettingsMap>(results: ProviderResult<Params>[], context: AdapterContext<CustomSettings>) => CacheEntry<AdapterResponse<null>>[];
63
+ export declare const buildCacheEntriesFromResults: <Params, CustomSettings extends SettingsMap>(results: ProviderResult<Params>[], context: AdapterContext<CustomSettings>) => CacheEntry<AdapterResponse<{
64
+ result: unknown;
65
+ }>>[];
64
66
  /**
65
67
  * Takes an Adapter, its configuration, and its dependencies, and it creates an express middleware
66
68
  * that will pass along the AdapterRequest to the appropriate Transport (acc. to the endpoint in the req.)
@@ -34,7 +34,9 @@ const buildCacheEntriesFromResults = (results, context) => results.map((r) => {
34
34
  value: {
35
35
  result: r.value,
36
36
  statusCode: 200,
37
- data: null, // TODO: Maybe add data as well?
37
+ data: {
38
+ result: r.value,
39
+ },
38
40
  },
39
41
  };
40
42
  if (context.adapterConfig.METRICS_ENABLED &&
@@ -1,7 +1,7 @@
1
1
  import * as client from 'prom-client';
2
2
  import { AdapterContext } from '../adapter';
3
3
  import { SettingsMap } from '../config';
4
- export declare const dataProviderMetricsLabel: (providerStatusCode?: number | undefined, method?: string) => {
4
+ export declare const dataProviderMetricsLabel: (providerStatusCode?: number, method?: string) => {
5
5
  provider_status_code: number | undefined;
6
6
  method: string;
7
7
  };
@@ -1,33 +1,9 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  Object.defineProperty(exports, "__esModule", { value: true });
26
3
  exports.RestTransport = void 0;
27
4
  const util_1 = require("../util");
28
5
  const error_1 = require("../validation/error");
29
6
  const util_2 = require("./util");
30
- const rateLimitMetrics = __importStar(require("../rate-limiting/metrics"));
31
7
  const IN_FLIGHT_PREFIX = 'InFlight';
32
8
  const logger = (0, util_1.makeLogger)('RestTransport');
33
9
  /**
@@ -114,14 +90,6 @@ class RestTransport {
114
90
  }
115
91
  logger.debug('Setting provider response in cache');
116
92
  await this.cache.set(req.requestContext.cacheKey, parsedResponse, config.CACHE_MAX_AGE);
117
- // Record cost of data provider call
118
- const cost = rateLimitMetrics.retrieveCost(providerResponse.data);
119
- rateLimitMetrics.rateLimitCreditsSpentTotal
120
- .labels({
121
- feed_id: req.requestContext.meta?.metrics?.feedId || 'N/A',
122
- participant_id: req.requestContext.cacheKey,
123
- })
124
- .inc(cost);
125
93
  // Update cacheHit flag in request meta for metrics use
126
94
  req.requestContext.meta = {
127
95
  ...req.requestContext.meta,
@@ -1,27 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
@@ -29,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
29
6
  exports.axiosRequest = void 0;
30
7
  const axios_1 = __importDefault(require("axios"));
31
8
  const error_1 = require("../validation/error");
32
- const transportMetrics = __importStar(require("./metrics"));
33
9
  /**
34
10
  * Performs axios request along with metrics recording and error handling
35
11
  *
@@ -37,7 +13,6 @@ const transportMetrics = __importStar(require("./metrics"));
37
13
  * @returns axios response for the request
38
14
  */
39
15
  async function axiosRequest(request, config) {
40
- const responseTimer = transportMetrics.dataProviderRequestDurationSeconds.startTimer();
41
16
  let providerResponse;
42
17
  try {
43
18
  request.timeout = config.API_TIMEOUT;
@@ -62,9 +37,6 @@ async function axiosRequest(request, config) {
62
37
  providerStatusCode = 0; // 0 -> connection error
63
38
  }
64
39
  // Record count of failed data provider request
65
- transportMetrics.dataProviderRequests
66
- .labels(transportMetrics.dataProviderMetricsLabel(providerStatusCode, request.method))
67
- .inc();
68
40
  adapterError.statusCode = 200;
69
41
  adapterError.providerStatusCode = providerStatusCode;
70
42
  adapterError.message = error?.message;
@@ -75,12 +47,7 @@ async function axiosRequest(request, config) {
75
47
  }
76
48
  finally {
77
49
  // Record time taken for data provider request for success or failure
78
- responseTimer();
79
50
  }
80
- // Record count of successful data provider requests
81
- transportMetrics.dataProviderRequests
82
- .labels(transportMetrics.dataProviderMetricsLabel(providerResponse.status, request.method))
83
- .inc();
84
51
  return providerResponse;
85
52
  }
86
53
  exports.axiosRequest = axiosRequest;
@@ -1,27 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
@@ -30,7 +7,6 @@ exports.WebSocketTransport = exports.WebSocketClassProvider = void 0;
30
7
  const ws_1 = __importDefault(require("ws"));
31
8
  const util_1 = require("../util");
32
9
  const _1 = require("./");
33
- const transportMetrics = __importStar(require("./metrics"));
34
10
  const logger = (0, util_1.makeLogger)('WebSocketTransport');
35
11
  class WebSocketClassProvider {
36
12
  static set(ctor) {
@@ -87,7 +63,6 @@ class WebSocketTransport {
87
63
  logger.debug('Successfully executed connection opened handler');
88
64
  // Record active ws connections by incrementing count on open
89
65
  // Using URL in label since connection_key is removed from v3
90
- transportMetrics.wsConnectionActive.inc();
91
66
  resolve(true);
92
67
  });
93
68
  this.wsConnection.addEventListener('message', async (event) => {
@@ -103,15 +78,11 @@ class WebSocketTransport {
103
78
  });
104
79
  this.wsConnection.addEventListener('error', async (event) => {
105
80
  // Record connection error count
106
- transportMetrics.wsConnectionErrors
107
- .labels(transportMetrics.connectionErrorLabels(event.message))
108
- .inc();
109
81
  });
110
82
  this.wsConnection.addEventListener('close', (event) => {
111
83
  logger.debug(`Closed websocket connection. Code: ${event.code} ; reason: ${event.reason?.toString()}`);
112
84
  // Record active ws connections by decrementing count on close
113
85
  // Using URL in label since connection_key is removed from v3
114
- transportMetrics.wsConnectionActive.dec();
115
86
  });
116
87
  });
117
88
  }
@@ -155,8 +126,6 @@ class WebSocketTransport {
155
126
  logger.trace(`Sending message: ${JSON.stringify(message)}`);
156
127
  this.wsConnection.send(message);
157
128
  }
158
- // Record WS message and subscription metrics
159
- transportMetrics.recordWsMessageMetrics(context, subscribeParams, unsubscribeParams);
160
129
  logger.debug('Setting local state to cache value');
161
130
  this.localSubscriptions = desiredSubs;
162
131
  logger.debug('Background execute complete');
package/util/request.d.ts CHANGED
@@ -51,7 +51,6 @@ export declare type AdapterResponse<T = unknown> = {
51
51
  result: unknown;
52
52
  maxAge?: number;
53
53
  meta?: AdapterRequestMeta;
54
- providerStatusCode?: number;
55
54
  };
56
55
  export declare type Middleware = ((req: AdapterRequest, reply: FastifyReply, done: HookHandlerDoneFunction) => FastifyReply | void) | ((req: AdapterRequest, reply: FastifyReply) => Promise<FastifyReply | void>);
57
56
  export declare type AdapterMiddlewareBuilder = (adapter: Adapter) => Middleware;
@@ -39,7 +39,6 @@ const validatorMiddleware = (adapter) => (req, reply, done) => {
39
39
  });
40
40
  }
41
41
  // Validate data using validator from v2
42
- // TODO: See if we want to change this whole thing
43
42
  const validator = new validator_1.Validator(req.body, endpoint.inputParameters);
44
43
  req.requestContext = {
45
44
  id: req.body.id || '1',
@@ -76,7 +75,10 @@ const validatorMiddleware = (adapter) => (req, reply, done) => {
76
75
  exports.validatorMiddleware = validatorMiddleware;
77
76
  const errorCatchingMiddleware = (err, req, res) => {
78
77
  // Add adapter or generic error to request meta for metrics use
79
- req.requestContext.meta = { ...req.requestContext.meta, error: err };
78
+ // There's a chance we have no request context if there was an error during input validation
79
+ if (req.requestContext) {
80
+ req.requestContext.meta = { ...req.requestContext?.meta, error: err };
81
+ }
80
82
  if (err instanceof error_1.AdapterError) {
81
83
  // We want to log these as warn, because although they are to be expected, NOPs should
82
84
  // Only use "correct" job specs and therefore not hit adapters with invalid requests.