Skip to content

Commit a722597

Browse files
georgereubenmatktmacfarla
authored andcommitted
Feat: add gas usage metric on eth_call (besu-eth#9019)
* WIP: update EthCall.java to capture gas usage metric * update EthJsonRpcMethods.java and JsonRpcMethodsFactory.java constructors to include metricsSystem * Update EthCallTest.java to mock gas usage metric * Update transactionSimulator error label to internal_error * Update CHANGELOG.md Signed-off-by: Reuben George <reubengeorge101@gmail.com> --------- Signed-off-by: Reuben George <reubengeorge101@gmail.com> Signed-off-by: Reuben George <69674713+georgereuben@users.noreply.github.com> Co-authored-by: Karim Taam <karim.t2am@gmail.com> Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com> Signed-off-by: jflo <justin+github@florentine.us>
1 parent 3cf9ad0 commit a722597

File tree

5 files changed

+56
-20
lines changed

5 files changed

+56
-20
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
- Improve the sync performance by not RLP decoding bodies during sync. This means we are using less memory and CPU, allowing us to increase the parallelism of the download pipeline, which has been increased from 4 to 8. Can be reduced again with `--Xsynchronizer-downloader-parallelism=4` [#8959](https://github.com/hyperledger/besu/pull/8959)
3333
- Enable decoding for large RPC requests [#8877](https://github.com/hyperledger/besu/pull/8877)
3434
- Add `--attempt-cache-bust` to evmtool benchmark subcommand [#8985](https://github.com/hyperledger/besu/pull/8985)
35+
- Add gas usage metric to eth_call [#9019](https://github.com/hyperledger/besu/pull/9019)
3536

3637
#### Fusaka devnets
3738
- EIP-7910 - `eth_config` JSON-RPC Method [#8417](https://github.com/hyperledger/besu/pull/8417), [#8946](https://github.com/hyperledger/besu/pull/8946), [#9015](https://github.com/hyperledger/besu/pull/9015)

ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,31 @@
4141
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
4242
import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult;
4343
import org.hyperledger.besu.evm.tracing.OperationTracer;
44+
import org.hyperledger.besu.metrics.BesuMetricCategory;
45+
import org.hyperledger.besu.plugin.services.MetricsSystem;
46+
import org.hyperledger.besu.plugin.services.metrics.Counter;
47+
import org.hyperledger.besu.plugin.services.metrics.LabelledMetric;
4448

4549
import java.util.Optional;
4650

4751
import com.google.common.annotations.VisibleForTesting;
4852

4953
public class EthCall extends AbstractBlockParameterOrBlockHashMethod {
5054
private final TransactionSimulator transactionSimulator;
55+
private final LabelledMetric<Counter> gasUsedCounter;
5156

5257
public EthCall(
53-
final BlockchainQueries blockchainQueries, final TransactionSimulator transactionSimulator) {
58+
final BlockchainQueries blockchainQueries,
59+
final TransactionSimulator transactionSimulator,
60+
final MetricsSystem metricsSystem) {
5461
super(blockchainQueries);
5562
this.transactionSimulator = transactionSimulator;
63+
this.gasUsedCounter =
64+
metricsSystem.createLabelledCounter(
65+
BesuMetricCategory.RPC,
66+
"eth_call_gas_used_total",
67+
"Total gas used by eth_call requests",
68+
"status");
5669
}
5770

5871
@Override
@@ -94,22 +107,25 @@ protected Object resultByBlockHeader(
94107
maybeStateOverrides,
95108
buildTransactionValidationParams(header, callParams),
96109
OperationTracer.NO_TRACING,
97-
(mutableWorldState, transactionSimulatorResult) -> {
98-
return transactionSimulatorResult.map(
99-
result ->
100-
result
101-
.getValidationResult()
102-
.either(
103-
(() ->
104-
result.isSuccessful()
105-
? new JsonRpcSuccessResponse(
106-
request.getRequest().getId(),
107-
result.getOutput().toString())
108-
: errorResponse(request, result)),
109-
reason -> errorResponse(request, result)));
110-
},
110+
(mutableWorldState, transactionSimulatorResult) ->
111+
transactionSimulatorResult.map(
112+
result -> {
113+
long gasUsed = result.getGasEstimate();
114+
if (result.isSuccessful()) {
115+
gasUsedCounter.labels("success").inc(gasUsed);
116+
return new JsonRpcSuccessResponse(
117+
request.getRequest().getId(), result.getOutput().toString());
118+
} else {
119+
gasUsedCounter.labels("error").inc(gasUsed);
120+
return errorResponse(request, result);
121+
}
122+
}),
111123
header)
112-
.orElse(errorResponse(request, INTERNAL_ERROR));
124+
.orElseGet(
125+
() -> {
126+
gasUsedCounter.labels("internal_error").inc(0);
127+
return errorResponse(request, INTERNAL_ERROR);
128+
});
113129
}
114130

115131
@VisibleForTesting

ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
7474
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability;
7575
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
76+
import org.hyperledger.besu.plugin.services.MetricsSystem;
7677

7778
import java.util.Map;
7879
import java.util.Set;
@@ -93,6 +94,7 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods {
9394
private final ApiConfiguration apiConfiguration;
9495
private final GenesisConfigOptions genesisConfigOptions;
9596
private final TransactionSimulator transactionSimulator;
97+
private final MetricsSystem metricsSystem;
9698

9799
public EthJsonRpcMethods(
98100
final BlockchainQueries blockchainQueries,
@@ -105,7 +107,8 @@ public EthJsonRpcMethods(
105107
final Set<Capability> supportedCapabilities,
106108
final ApiConfiguration apiConfiguration,
107109
final GenesisConfigOptions genesisConfigOptions,
108-
final TransactionSimulator transactionSimulator) {
110+
final TransactionSimulator transactionSimulator,
111+
final MetricsSystem metricsSystem) {
109112
this.blockchainQueries = blockchainQueries;
110113
this.synchronizer = synchronizer;
111114
this.protocolSchedule = protocolSchedule;
@@ -117,6 +120,7 @@ public EthJsonRpcMethods(
117120
this.apiConfiguration = apiConfiguration;
118121
this.genesisConfigOptions = genesisConfigOptions;
119122
this.transactionSimulator = transactionSimulator;
123+
this.metricsSystem = metricsSystem;
120124
}
121125

122126
@Override
@@ -135,7 +139,7 @@ protected Map<String, JsonRpcMethod> create() {
135139
new EthGetBlockReceipts(blockchainQueries, protocolSchedule),
136140
new EthGetBlockTransactionCountByNumber(blockchainQueries),
137141
new EthGetBlockTransactionCountByHash(blockchainQueries),
138-
new EthCall(blockchainQueries, transactionSimulator),
142+
new EthCall(blockchainQueries, transactionSimulator, metricsSystem),
139143
new EthFeeHistory(protocolSchedule, blockchainQueries, miningCoordinator, apiConfiguration),
140144
new EthGetCode(blockchainQueries),
141145
new EthGetLogs(blockchainQueries, apiConfiguration.getMaxLogsRange()),

ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ public Map<String, JsonRpcMethod> methods(
136136
supportedCapabilities,
137137
apiConfiguration,
138138
genesisConfigOptions,
139-
transactionSimulator),
139+
transactionSimulator,
140+
metricsSystem),
140141
new NetJsonRpcMethods(
141142
p2pNetwork,
142143
networkId,

ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@
5454
import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler;
5555
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
5656
import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult;
57+
import org.hyperledger.besu.metrics.BesuMetricCategory;
58+
import org.hyperledger.besu.plugin.services.MetricsSystem;
59+
import org.hyperledger.besu.plugin.services.metrics.Counter;
60+
import org.hyperledger.besu.plugin.services.metrics.LabelledMetric;
5761

5862
import java.util.Map;
5963
import java.util.Optional;
@@ -81,13 +85,23 @@ public class EthCallTest {
8185
@Mock private BlockchainQueries blockchainQueries;
8286
@Mock private TransactionSimulator transactionSimulator;
8387
@Mock private BlockHeader blockHeader;
88+
@Mock private MetricsSystem metricsSystem;
8489

8590
@Captor ArgumentCaptor<PreCloseStateHandler<Optional<JsonRpcResponse>>> mapperCaptor;
8691
@Captor ArgumentCaptor<CallParameter> callParameterCaptor;
8792

8893
@BeforeEach
8994
public void setUp() {
90-
method = new EthCall(blockchainQueries, transactionSimulator);
95+
@SuppressWarnings("unchecked")
96+
LabelledMetric<Counter> mockGasUsedCounter = mock(LabelledMetric.class);
97+
Counter mockCounter = mock(Counter.class);
98+
when(mockGasUsedCounter.labels(any(String[].class))).thenReturn(mockCounter);
99+
100+
when(metricsSystem.createLabelledCounter(
101+
any(BesuMetricCategory.class), any(String.class), any(String.class), any(String.class)))
102+
.thenReturn(mockGasUsedCounter);
103+
104+
method = new EthCall(blockchainQueries, transactionSimulator, metricsSystem);
91105
blockHeader = mock(BlockHeader.class);
92106
when(blockHeader.getBlockHash()).thenReturn(Hash.ZERO);
93107
}

0 commit comments

Comments
 (0)