Add basic provider stats (#4662)

* Add basic provider stats

* Add timeout counter

* Make stats() optional for providers (don't break what is out there)

* Update packages/rpc-provider/src/types.ts
This commit is contained in:
Jaco
2022-03-17 17:33:40 +02:00
committed by GitHub
parent 5898ac335e
commit d63108a4b4
4 changed files with 84 additions and 15 deletions
+42 -14
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2022 @polkadot/rpc-provider authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { JsonRpcResponse, ProviderInterface, ProviderInterfaceCallback, ProviderInterfaceEmitCb, ProviderInterfaceEmitted } from '../types';
import type { JsonRpcResponse, ProviderInterface, ProviderInterfaceCallback, ProviderInterfaceEmitCb, ProviderInterfaceEmitted, ProviderStats } from '../types';
import { assert, logger } from '@polkadot/util';
import { fetch } from '@polkadot/x-fetch';
@@ -43,6 +43,8 @@ export class HttpProvider implements ProviderInterface {
readonly #headers: Record<string, string>;
readonly #stats: ProviderStats;
/**
* @param {string} endpoint The endpoint url starting with http://
*/
@@ -52,6 +54,10 @@ export class HttpProvider implements ProviderInterface {
this.#coder = new RpcCoder();
this.#endpoint = endpoint;
this.#headers = headers;
this.#stats = {
active: { requests: 0, subscriptions: 0 },
total: { cached: 0, requests: 0, subscriptions: 0, timeout: 0 }
};
}
/**
@@ -82,6 +88,13 @@ export class HttpProvider implements ProviderInterface {
// noop
}
/**
* @description Returns the connection stats
*/
public stats (): ProviderStats {
return this.#stats;
}
/**
* @summary Whether the node is connected or not.
* @return {boolean} true if connected
@@ -107,6 +120,8 @@ export class HttpProvider implements ProviderInterface {
* @summary Send HTTP POST Request with Body to configured HTTP Endpoint.
*/
public async send <T> (method: string, params: unknown[], isCacheable?: boolean): Promise<T> {
this.#stats.total.requests++;
const body = this.#coder.encodeJson(method, params);
let resultPromise: Promise<T> | null = isCacheable
? this.#callCache.get(body) as Promise<T>
@@ -118,28 +133,41 @@ export class HttpProvider implements ProviderInterface {
if (isCacheable) {
this.#callCache.set(body, resultPromise);
}
} else {
this.#stats.total.cached++;
}
return resultPromise;
}
async #send <T> (body: string): Promise<T> {
const response = await fetch(this.#endpoint, {
body,
headers: {
Accept: 'application/json',
'Content-Length': `${body.length}`,
'Content-Type': 'application/json',
...this.#headers
},
method: 'POST'
});
this.#stats.active.requests++;
assert(response.ok, () => `[${response.status}]: ${response.statusText}`);
try {
const response = await fetch(this.#endpoint, {
body,
headers: {
Accept: 'application/json',
'Content-Length': `${body.length}`,
'Content-Type': 'application/json',
...this.#headers
},
method: 'POST'
});
const result = (await response.json()) as JsonRpcResponse;
assert(response.ok, () => `[${response.status}]: ${response.statusText}`);
return this.#coder.decodeResponse(result) as T;
const result = (await response.json()) as JsonRpcResponse;
const decoded = this.#coder.decodeResponse(result) as T;
this.#stats.active.requests--;
return decoded;
} catch (e) {
this.#stats.active.requests--;
throw e;
}
}
/**