Skip to content

Commit 3dd36f6

Browse files
chore: add active users counter per rate limiter duration (#3150)
* chore: update executions counter to track daiy active users Signed-off-by: Nadezhda Popova <nadezhda.popova@limechain.tech> * test: update tests to include active users counter Signed-off-by: Nadezhda Popova <nadezhda.popova@limechain.tech> * fixup! test: update tests to include active users counter Signed-off-by: Nadezhda Popova <nadezhda.popova@limechain.tech> * fixup! fixup! test: update tests to include active users counter Signed-off-by: Nadezhda Popova <nadezhda.popova@limechain.tech> --------- Signed-off-by: Nadezhda Popova <nadezhda.popova@limechain.tech>
1 parent d635301 commit 3dd36f6

File tree

3 files changed

+95
-20
lines changed

3 files changed

+95
-20
lines changed

packages/relay/src/lib/eth.ts

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ export class EthImpl implements Eth {
227227
private readonly chain: string;
228228

229229
/**
230-
* The ethExecutionsCounter used to track the number of active contract execution requests.
230+
* The ethExecutionsCounter used to track the number of daily active users and active contract execution requests.
231231
* @private
232232
*/
233233
private readonly ethExecutionsCounter: Counter;
@@ -272,7 +272,11 @@ export class EthImpl implements Eth {
272272
this.cacheService = cacheService;
273273
this.mirrorNodeClient = mirrorNodeClient;
274274
this.precheck = new Precheck(mirrorNodeClient, logger, chain);
275-
this.ethExecutionsCounter = this.initEthExecutionCounter(registry);
275+
this.ethExecutionsCounter = this.initCounter(
276+
'rpc_relay_eth_executions',
277+
['method', 'function', 'from', 'to'],
278+
registry,
279+
);
276280
this.common = new CommonService(mirrorNodeClient, logger, cacheService);
277281
this.debugServiceImpl = new DebugService(mirrorNodeClient, logger, this.common);
278282
this.filterServiceImpl = new FilterService(mirrorNodeClient, logger, cacheService, this.common);
@@ -283,13 +287,12 @@ export class EthImpl implements Eth {
283287
return !CommonService.blockTagIsLatestOrPendingStrict(tag) && !CommonService.isDevMode;
284288
}
285289

286-
private initEthExecutionCounter(register: Registry): Counter {
287-
const metricCounterName = 'rpc_relay_eth_executions';
290+
private initCounter(metricCounterName: string, labelNames: string[], register: Registry): Counter {
288291
register.removeSingleMetric(metricCounterName);
289292
return new Counter({
290293
name: metricCounterName,
291294
help: `Relay ${metricCounterName} function`,
292-
labelNames: ['method', 'function'],
295+
labelNames: labelNames,
293296
registers: [register],
294297
});
295298
}
@@ -579,7 +582,12 @@ export class EthImpl implements Eth {
579582

580583
if (callDataSize >= constants.FUNCTION_SELECTOR_CHAR_LENGTH) {
581584
this.ethExecutionsCounter
582-
.labels(EthImpl.ethEstimateGas, callData!.substring(0, constants.FUNCTION_SELECTOR_CHAR_LENGTH))
585+
.labels(
586+
EthImpl.ethEstimateGas,
587+
callData!.substring(0, constants.FUNCTION_SELECTOR_CHAR_LENGTH),
588+
transaction.from || '',
589+
transaction.to || '',
590+
)
583591
.inc();
584592
}
585593

@@ -1643,17 +1651,22 @@ export class EthImpl implements Eth {
16431651
*/
16441652
async sendRawTransaction(transaction: string, requestDetails: RequestDetails): Promise<string | JsonRpcError> {
16451653
const requestIdPrefix = requestDetails.formattedRequestId;
1646-
if (transaction?.length >= constants.FUNCTION_SELECTOR_CHAR_LENGTH)
1647-
this.ethExecutionsCounter
1648-
.labels(EthImpl.ethSendRawTransaction, transaction.substring(0, constants.FUNCTION_SELECTOR_CHAR_LENGTH))
1649-
.inc();
1650-
16511654
const networkGasPriceInWeiBars = Utils.addPercentageBufferToGasPrice(
16521655
await this.getFeeWeibars(EthImpl.ethGasPrice, requestDetails),
16531656
);
1654-
16551657
const parsedTx = await this.parseRawTxAndPrecheck(transaction, requestDetails, networkGasPriceInWeiBars);
16561658
const originalCallerAddress = parsedTx.from?.toString() || '';
1659+
const toAddress = parsedTx.to?.toString() || '';
1660+
1661+
this.ethExecutionsCounter
1662+
.labels(
1663+
EthImpl.ethSendRawTransaction,
1664+
parsedTx.data.substring(0, constants.FUNCTION_SELECTOR_CHAR_LENGTH) || '',
1665+
originalCallerAddress,
1666+
toAddress,
1667+
)
1668+
.inc();
1669+
16571670
const transactionBuffer = Buffer.from(EthImpl.prune0x(transaction), 'hex');
16581671

16591672
let fileId: FileId | null = null;
@@ -1780,12 +1793,15 @@ export class EthImpl implements Eth {
17801793
if (this.logger.isLevelEnabled('trace')) {
17811794
this.logger.trace(`${requestIdPrefix} call data size: ${callDataSize}`);
17821795
}
1783-
// metrics for selector
1784-
if (callDataSize >= constants.FUNCTION_SELECTOR_CHAR_LENGTH) {
1785-
this.ethExecutionsCounter
1786-
.labels(EthImpl.ethCall, callData!.substring(0, constants.FUNCTION_SELECTOR_CHAR_LENGTH))
1787-
.inc();
1788-
}
1796+
1797+
this.ethExecutionsCounter
1798+
.labels(
1799+
EthImpl.ethCall,
1800+
callData?.substring(0, constants.FUNCTION_SELECTOR_CHAR_LENGTH) ?? '',
1801+
call.from || '',
1802+
call.to || '',
1803+
)
1804+
.inc();
17891805

17901806
const blockNumberOrTag = await this.extractBlockNumberOrTag(blockParam, requestDetails);
17911807
await this.performCallChecks(call);

packages/relay/tests/lib/eth/eth_call.spec.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import {
5858
import { generateEthTestEnv } from './eth-helpers';
5959
import { IContractCallRequest, IContractCallResponse, RequestDetails } from '../../../src/lib/types';
6060
import { ContractFunctionResult } from '@hashgraph/sdk';
61+
import { Counter } from 'prom-client';
6162

6263
use(chaiAsPromised);
6364

@@ -448,6 +449,20 @@ describe('@ethCall Eth Call spec', async function () {
448449
'Error invoking RPC: Invalid contractCallResponse from consensus-node: undefined',
449450
);
450451
});
452+
453+
it('should update execution counter and list the correct data when eth_call is executed', async function () {
454+
const labelsSpy = sinon.spy(ethImpl['ethExecutionsCounter'], 'labels');
455+
const expectedLabelsValue = ['eth_call', ETH_CALL_REQ_ARGS.data, ETH_CALL_REQ_ARGS.from, ETH_CALL_REQ_ARGS.to];
456+
457+
await ethImpl.call(ETH_CALL_REQ_ARGS, 'latest', requestDetails);
458+
459+
expect(ethImpl['ethExecutionsCounter']).to.be.instanceOf(Counter);
460+
labelsSpy.args[0].map((labelValue, index) => {
461+
expect(labelValue).to.equal(expectedLabelsValue[index]);
462+
});
463+
464+
sinon.restore();
465+
});
451466
});
452467

453468
describe('eth_call using mirror node', async function () {
@@ -778,6 +793,29 @@ describe('@ethCall Eth Call spec', async function () {
778793
expect(result).to.eq(EXAMPLE_CONTRACT_BYTECODE);
779794
});
780795

796+
it('should update execution counter and list the correct data when eth_call is executed', async function () {
797+
const labelsSpy = sinon.spy(ethImpl['ethExecutionsCounter'], 'labels');
798+
const expectedLabelsValue = ['eth_call', CONTRACT_CALL_DATA, ACCOUNT_ADDRESS_1, CONTRACT_ADDRESS_2];
799+
800+
const callData = {
801+
...defaultCallData,
802+
from: ACCOUNT_ADDRESS_1,
803+
to: CONTRACT_ADDRESS_2,
804+
data: CONTRACT_CALL_DATA,
805+
gas: MAX_GAS_LIMIT,
806+
};
807+
await mockContractCall({ ...callData, block: 'latest' }, false, 200, { result: '0x00' }, requestDetails);
808+
await ethImpl.call(callData, 'latest', requestDetails);
809+
810+
expect(ethImpl['ethExecutionsCounter']).to.be.instanceOf(Counter);
811+
812+
labelsSpy.args[0].map((labelValue, index) => {
813+
expect(labelValue).to.equal(expectedLabelsValue[index]);
814+
});
815+
816+
sinon.restore();
817+
});
818+
781819
async function mockContractCall(
782820
callData: IContractCallRequest,
783821
estimate: boolean,

packages/relay/tests/lib/eth/eth_sendRawTransaction.spec.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import { RequestDetails } from '../../../src/lib/types';
4646
import MockAdapter from 'axios-mock-adapter';
4747
import HAPIService from '../../../src/lib/services/hapiService/hapiService';
4848
import { CacheService } from '../../../src/lib/services/cacheService/cacheService';
49+
import { Counter } from 'prom-client';
4950

5051
use(chaiAsPromised);
5152

@@ -59,8 +60,12 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
5960
hapiServiceInstance,
6061
ethImpl,
6162
cacheService,
62-
}: { restMock: MockAdapter; hapiServiceInstance: HAPIService; ethImpl: Eth; cacheService: CacheService } =
63-
generateEthTestEnv();
63+
}: {
64+
restMock: MockAdapter;
65+
hapiServiceInstance: HAPIService;
66+
ethImpl: Eth;
67+
cacheService: CacheService;
68+
} = generateEthTestEnv();
6469

6570
const requestDetails = new RequestDetails({ requestId: 'eth_sendRawTransactionTest', ipAddress: '0.0.0.0' });
6671

@@ -344,5 +349,21 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
344349
expect(response.message).to.include(error);
345350
});
346351
});
352+
353+
it('should update execution counter and list the correct data when eth_sendRawTransation is executed', async function () {
354+
const labelsSpy = sinon.spy(ethImpl['ethExecutionsCounter'], 'labels');
355+
const expectedLabelsValue = ['eth_sendRawTransaction', '0x', transaction.from, transaction.to];
356+
357+
const signed = await signTransaction(transaction);
358+
359+
await ethImpl.sendRawTransaction(signed, requestDetails);
360+
361+
expect(ethImpl['ethExecutionsCounter']).to.be.instanceOf(Counter);
362+
labelsSpy.args[0].map((labelValue, index) => {
363+
expect(labelValue).to.equal(expectedLabelsValue[index]);
364+
});
365+
366+
sinon.restore();
367+
});
347368
});
348369
});

0 commit comments

Comments
 (0)