From 5c4d6dfe44131aa73e1195679ffa8a9596ca148e Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Mon, 8 Apr 2024 17:29:01 +0200 Subject: [PATCH] Expose transaction count by type metrics for the layered txpool (#6903) Signed-off-by: Fabio Di Fabio Signed-off-by: amsmota --- CHANGELOG.md | 1 + .../transactions/TransactionPoolMetrics.java | 27 +++++++++++++++++++ .../layered/AbstractTransactionsLayer.java | 24 ++++++++++++----- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 506de63a077..bb145bebff6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ - Update Web3j dependencies [#6811](https://github.com/hyperledger/besu/pull/6811) - Add `tx-pool-blob-price-bump` option to configure the price bump percentage required to replace blob transactions (by default 100%) [#6874](https://github.com/hyperledger/besu/pull/6874) - Log detailed timing of block creation steps [#6880](https://github.com/hyperledger/besu/pull/6880) +- Expose transaction count by type metrics for the layered txpool [#6903](https://github.com/hyperledger/besu/pull/6903) ### Bug fixes - Fix txpool dump/restore race condition [#6665](https://github.com/hyperledger/besu/pull/6665) diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolMetrics.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolMetrics.java index 20657304f0f..5848296ce3c 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolMetrics.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolMetrics.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.ethereum.eth.transactions; +import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import org.hyperledger.besu.metrics.BesuMetricCategory; import org.hyperledger.besu.metrics.ReplaceableDoubleSupplier; @@ -27,6 +28,7 @@ import java.util.Map; import java.util.function.DoubleSupplier; +import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,12 +45,15 @@ public class TransactionPoolMetrics { private final LabelledMetric rejectedCounter; private final LabelledGauge spaceUsed; private final LabelledGauge transactionCount; + private final LabelledGauge transactionCountByType; private final LabelledGauge uniqueSenderCount; private final LabelledMetric expiredMessagesCounter; private final Map expiredMessagesRunnableCounters = new HashMap<>(); private final LabelledMetric alreadySeenTransactionsCounter; private final Map spaceUsedSuppliers = new HashMap<>(); private final Map transactionCountSuppliers = new HashMap<>(); + private final Map, ReplaceableDoubleSupplier> + transactionCountByTypeSuppliers = new HashMap<>(); private final Map uniqueSendersSuppliers = new HashMap<>(); public TransactionPoolMetrics(final MetricsSystem metricsSystem) { @@ -97,6 +102,14 @@ public TransactionPoolMetrics(final MetricsSystem metricsSystem) { "The number of transactions currently present in the layer", "layer"); + transactionCountByType = + metricsSystem.createLabelledGauge( + BesuMetricCategory.TRANSACTION_POOL, + "number_of_transactions_by_type", + "The number of transactions, of a specified type, currently present in the layer", + "layer", + "type"); + uniqueSenderCount = metricsSystem.createLabelledGauge( BesuMetricCategory.TRANSACTION_POOL, @@ -136,6 +149,20 @@ public void initSpaceUsed(final DoubleSupplier spaceUsedSupplier, final String l }); } + public void initTransactionCountByType( + final DoubleSupplier spaceUsedSupplier, final String layer, final TransactionType type) { + transactionCountByTypeSuppliers.compute( + Pair.of(layer, type), + (unused, existingSupplier) -> { + if (existingSupplier == null) { + final var newSupplier = new ReplaceableDoubleSupplier(spaceUsedSupplier); + transactionCountByType.labels(newSupplier, layer, type.name()); + return newSupplier; + } + return existingSupplier.replaceDoubleSupplier(spaceUsedSupplier); + }); + } + public void initTransactionCount( final DoubleSupplier transactionCountSupplier, final String layer) { transactionCountSuppliers.compute( diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java index e32eb0e2291..68ecb99c5c7 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java @@ -26,6 +26,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; @@ -39,6 +40,7 @@ import org.hyperledger.besu.util.Subscribers; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -74,7 +76,7 @@ public abstract class AbstractTransactionsLayer implements TransactionsLayer { private OptionalLong nextLayerOnAddedListenerId = OptionalLong.empty(); private OptionalLong nextLayerOnDroppedListenerId = OptionalLong.empty(); protected long spaceUsed = 0; - + protected final int[] txCountByType = new int[TransactionType.values().length]; private final BlobCache blobCache; protected AbstractTransactionsLayer( @@ -91,6 +93,11 @@ protected AbstractTransactionsLayer( metrics.initSpaceUsed(this::getLayerSpaceUsed, name()); metrics.initTransactionCount(pendingTransactions::size, name()); metrics.initUniqueSenderCount(txsBySender::size, name()); + Arrays.stream(TransactionType.values()) + .forEach( + type -> + metrics.initTransactionCountByType( + () -> txCountByType[type.ordinal()], name(), type)); this.blobCache = blobCache; } @@ -101,6 +108,7 @@ public void reset() { pendingTransactions.clear(); txsBySender.clear(); spaceUsed = 0; + Arrays.fill(txCountByType, 0); nextLayer.reset(); } @@ -286,7 +294,7 @@ private void processAdded(final PendingTransaction addedTx) { pendingTransactions.put(addedTx.getHash(), addedTx); final var senderTxs = txsBySender.computeIfAbsent(addedTx.getSender(), s -> new TreeMap<>()); senderTxs.put(addedTx.getNonce(), addedTx); - increaseSpaceUsed(addedTx); + increaseCounters(addedTx); metrics.incrementAdded(addedTx, name()); internalAdd(senderTxs, addedTx); } @@ -332,7 +340,7 @@ private void evict(final long spaceToFree, final int txsToEvict) { protected void replaced(final PendingTransaction replacedTx) { pendingTransactions.remove(replacedTx.getHash()); - decreaseSpaceUsed(replacedTx); + decreaseCounters(replacedTx); metrics.incrementRemoved(replacedTx, REPLACED.label(), name()); internalReplaced(replacedTx); notifyTransactionDropped(replacedTx); @@ -368,7 +376,7 @@ protected PendingTransaction processRemove( final PendingTransaction removedTx = pendingTransactions.remove(transaction.getHash()); if (removedTx != null) { - decreaseSpaceUsed(removedTx); + decreaseCounters(removedTx); metrics.incrementRemoved(removedTx, removalReason.label(), name()); internalRemove(senderTxs, removedTx, removalReason); } @@ -381,7 +389,7 @@ protected PendingTransaction processEvict( final RemovalReason reason) { final PendingTransaction removedTx = pendingTransactions.remove(evictedTx.getHash()); if (removedTx != null) { - decreaseSpaceUsed(evictedTx); + decreaseCounters(evictedTx); metrics.incrementRemoved(evictedTx, reason.label(), name()); internalEvict(senderTxs, removedTx); } @@ -467,12 +475,14 @@ protected abstract void internalRemove( protected abstract PendingTransaction getEvictable(); - protected void increaseSpaceUsed(final PendingTransaction pendingTransaction) { + protected void increaseCounters(final PendingTransaction pendingTransaction) { spaceUsed += pendingTransaction.memorySize(); + ++txCountByType[pendingTransaction.getTransaction().getType().ordinal()]; } - protected void decreaseSpaceUsed(final PendingTransaction pendingTransaction) { + protected void decreaseCounters(final PendingTransaction pendingTransaction) { spaceUsed -= pendingTransaction.memorySize(); + --txCountByType[pendingTransaction.getTransaction().getType().ordinal()]; } protected abstract long cacheFreeSpace();