diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/metric/HandleWorkflowMetrics.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/OpWorkflowMetrics.java similarity index 90% rename from hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/metric/HandleWorkflowMetrics.java rename to hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/OpWorkflowMetrics.java index 4aa66a649795..62ee0377066a 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/metric/HandleWorkflowMetrics.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/OpWorkflowMetrics.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.hedera.node.app.workflows.handle.metric; +package com.hedera.node.app.workflows; import static java.util.Objects.requireNonNull; @@ -34,10 +34,10 @@ import javax.inject.Singleton; /** - * A class to handle the metrics for the handle-workflow + * A class to handle the metrics for all operations (transactions and queries) */ @Singleton -public class HandleWorkflowMetrics { +public class OpWorkflowMetrics { private static final BinaryOperator AVERAGE = (sum, count) -> count == 0 ? 0 : sum / count; @@ -53,12 +53,12 @@ public class HandleWorkflowMetrics { private long gasUsedThisConsensusSecond = 0L; /** - * Constructor for the HandleWorkflowMetrics + * Constructor for the OpWorkflowMetrics * * @param metrics the {@link Metrics} object where all metrics will be registered */ @Inject - public HandleWorkflowMetrics(@NonNull final Metrics metrics, @NonNull final ConfigProvider configProvider) { + public OpWorkflowMetrics(@NonNull final Metrics metrics, @NonNull final ConfigProvider configProvider) { requireNonNull(metrics, "metrics must not be null"); requireNonNull(configProvider, "configProvider must not be null"); @@ -88,9 +88,9 @@ public HandleWorkflowMetrics(@NonNull final Metrics metrics, @NonNull final Conf * Update the metrics for the given functionality * * @param functionality the {@link HederaFunctionality} for which the metrics will be updated - * @param duration the duration of the transaction in {@code ns} + * @param duration the duration of the operation in {@code ns} */ - public void updateTransactionDuration(@NonNull final HederaFunctionality functionality, final int duration) { + public void updateDuration(@NonNull final HederaFunctionality functionality, final int duration) { requireNonNull(functionality, "functionality must not be null"); if (functionality == HederaFunctionality.NONE) { return; diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/HandleWorkflow.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/HandleWorkflow.java index cd0a7009833a..d64317ec0778 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/HandleWorkflow.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/HandleWorkflow.java @@ -63,11 +63,11 @@ import com.hedera.node.app.store.WritableStoreFactory; import com.hedera.node.app.throttle.NetworkUtilizationManager; import com.hedera.node.app.throttle.ThrottleServiceManager; +import com.hedera.node.app.workflows.OpWorkflowMetrics; import com.hedera.node.app.workflows.TransactionInfo; import com.hedera.node.app.workflows.dispatcher.TransactionDispatcher; import com.hedera.node.app.workflows.handle.cache.CacheWarmer; import com.hedera.node.app.workflows.handle.dispatch.ChildDispatchFactory; -import com.hedera.node.app.workflows.handle.metric.HandleWorkflowMetrics; import com.hedera.node.app.workflows.handle.record.RecordStreamBuilder; import com.hedera.node.app.workflows.handle.record.SystemSetup; import com.hedera.node.app.workflows.handle.steps.HollowAccountCompletions; @@ -117,7 +117,7 @@ public class HandleWorkflow { private final BlockRecordManager blockRecordManager; private final BlockStreamManager blockStreamManager; private final CacheWarmer cacheWarmer; - private final HandleWorkflowMetrics handleWorkflowMetrics; + private final OpWorkflowMetrics opWorkflowMetrics; private final ThrottleServiceManager throttleServiceManager; private final SemanticVersion version; private final InitTrigger initTrigger; @@ -148,7 +148,7 @@ public HandleWorkflow( @NonNull final BlockRecordManager blockRecordManager, @NonNull final BlockStreamManager blockStreamManager, @NonNull final CacheWarmer cacheWarmer, - @NonNull final HandleWorkflowMetrics handleWorkflowMetrics, + @NonNull final OpWorkflowMetrics opWorkflowMetrics, @NonNull final ThrottleServiceManager throttleServiceManager, @NonNull final SemanticVersion version, @NonNull final InitTrigger initTrigger, @@ -176,7 +176,7 @@ public HandleWorkflow( this.blockRecordManager = requireNonNull(blockRecordManager); this.blockStreamManager = requireNonNull(blockStreamManager); this.cacheWarmer = requireNonNull(cacheWarmer); - this.handleWorkflowMetrics = requireNonNull(handleWorkflowMetrics); + this.opWorkflowMetrics = requireNonNull(opWorkflowMetrics); this.throttleServiceManager = requireNonNull(throttleServiceManager); this.version = requireNonNull(version); this.initTrigger = requireNonNull(initTrigger); @@ -323,8 +323,7 @@ private void handlePlatformTransaction( if (blockStreamConfig.streamBlocks()) { handleOutput.blocksItemsOrThrow().forEach(blockStreamManager::writeItem); } - handleWorkflowMetrics.updateTransactionDuration( - userTxn.functionality(), (int) (System.nanoTime() - handleStart)); + opWorkflowMetrics.updateDuration(userTxn.functionality(), (int) (System.nanoTime() - handleStart)); } /** @@ -450,7 +449,7 @@ private void updateWorkflowMetrics(@NonNull final UserTxn userTxn) { if (userTxn.type() == GENESIS_TRANSACTION || userTxn.consensusNow().getEpochSecond() > userTxn.lastHandledConsensusTime().getEpochSecond()) { - handleWorkflowMetrics.switchConsensusSecond(); + opWorkflowMetrics.switchConsensusSecond(); } } diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/throttle/DispatchUsageManager.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/throttle/DispatchUsageManager.java index 70760b0ba452..3199c13a9bef 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/throttle/DispatchUsageManager.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/throttle/DispatchUsageManager.java @@ -38,8 +38,8 @@ import com.hedera.node.app.throttle.CongestionThrottleService; import com.hedera.node.app.throttle.NetworkUtilizationManager; import com.hedera.node.app.throttle.ThrottleServiceManager; +import com.hedera.node.app.workflows.OpWorkflowMetrics; import com.hedera.node.app.workflows.handle.Dispatch; -import com.hedera.node.app.workflows.handle.metric.HandleWorkflowMetrics; import com.hedera.node.config.data.ContractsConfig; import com.swirlds.state.spi.info.NetworkInfo; import edu.umd.cs.findbugs.annotations.NonNull; @@ -54,18 +54,18 @@ public class DispatchUsageManager { EnumSet.of(HederaFunctionality.CONTRACT_CREATE, HederaFunctionality.CONTRACT_CALL, ETHEREUM_TRANSACTION); private final NetworkInfo networkInfo; - private final HandleWorkflowMetrics handleWorkflowMetrics; + private final OpWorkflowMetrics opWorkflowMetrics; private final ThrottleServiceManager throttleServiceManager; private final NetworkUtilizationManager networkUtilizationManager; @Inject public DispatchUsageManager( @NonNull final NetworkInfo networkInfo, - @NonNull final HandleWorkflowMetrics handleWorkflowMetrics, + @NonNull final OpWorkflowMetrics opWorkflowMetrics, @NonNull final ThrottleServiceManager throttleServiceManager, @NonNull final NetworkUtilizationManager networkUtilizationManager) { this.networkInfo = requireNonNull(networkInfo); - this.handleWorkflowMetrics = requireNonNull(handleWorkflowMetrics); + this.opWorkflowMetrics = requireNonNull(opWorkflowMetrics); this.throttleServiceManager = requireNonNull(throttleServiceManager); this.networkUtilizationManager = requireNonNull(networkUtilizationManager); } @@ -134,7 +134,7 @@ private void leakUnusedGas(@NonNull final Dispatch dispatch) { // EVM action tracer to get a better estimate of the actual gas used and the gas limit. if (builder.hasContractResult()) { final var gasUsed = builder.getGasUsedForContractTxn(); - handleWorkflowMetrics.addGasUsed(gasUsed); + opWorkflowMetrics.addGasUsed(gasUsed); final var contractsConfig = dispatch.config().getConfigData(ContractsConfig.class); if (contractsConfig.throttleThrottleByGas()) { final var txnInfo = dispatch.txnInfo(); diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/query/QueryWorkflowImpl.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/query/QueryWorkflowImpl.java index ec7f7ea62367..5dc39a81c945 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/query/QueryWorkflowImpl.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/query/QueryWorkflowImpl.java @@ -52,6 +52,7 @@ import com.hedera.node.app.spi.workflows.QueryHandler; import com.hedera.node.app.store.ReadableStoreFactory; import com.hedera.node.app.throttle.SynchronizedThrottleAccumulator; +import com.hedera.node.app.workflows.OpWorkflowMetrics; import com.hedera.node.app.workflows.ingest.IngestChecker; import com.hedera.node.app.workflows.ingest.SubmissionManager; import com.hedera.node.config.ConfigProvider; @@ -101,6 +102,7 @@ public final class QueryWorkflowImpl implements QueryWorkflow { private final FeeManager feeManager; private final SynchronizedThrottleAccumulator synchronizedThrottleAccumulator; private final InstantSource instantSource; + private final OpWorkflowMetrics workflowMetrics; /** * Constructor of {@code QueryWorkflowImpl} @@ -135,7 +137,8 @@ public QueryWorkflowImpl( @NonNull final ExchangeRateManager exchangeRateManager, @NonNull final FeeManager feeManager, @NonNull final SynchronizedThrottleAccumulator synchronizedThrottleAccumulator, - @NonNull final InstantSource instantSource) { + @NonNull final InstantSource instantSource, + @NonNull final OpWorkflowMetrics workflowMetrics) { this.stateAccessor = requireNonNull(stateAccessor, "stateAccessor must not be null"); this.submissionManager = requireNonNull(submissionManager, "submissionManager must not be null"); this.ingestChecker = requireNonNull(ingestChecker, "ingestChecker must not be null"); @@ -150,10 +153,13 @@ public QueryWorkflowImpl( this.synchronizedThrottleAccumulator = requireNonNull(synchronizedThrottleAccumulator, "hapiThrottling must not be null"); this.instantSource = requireNonNull(instantSource); + this.workflowMetrics = requireNonNull(workflowMetrics); } @Override public void handleQuery(@NonNull final Bytes requestBuffer, @NonNull final BufferedData responseBuffer) { + final long queryStart = System.nanoTime(); + requireNonNull(requestBuffer); requireNonNull(responseBuffer); @@ -295,6 +301,8 @@ public void handleQuery(@NonNull final Bytes requestBuffer, @NonNull final Buffe logger.warn("Unexpected IO exception while writing protobuf", e); throw new StatusRuntimeException(Status.INTERNAL); } + + workflowMetrics.updateDuration(function, (int) (System.nanoTime() - queryStart)); } private Query parseQuery(Bytes requestBuffer) { diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/HandleWorkflowTest.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/HandleWorkflowTest.java index df0b83117024..20314933cfb9 100644 --- a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/HandleWorkflowTest.java +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/HandleWorkflowTest.java @@ -37,10 +37,10 @@ import com.hedera.node.app.state.HederaRecordCache; import com.hedera.node.app.throttle.NetworkUtilizationManager; import com.hedera.node.app.throttle.ThrottleServiceManager; +import com.hedera.node.app.workflows.OpWorkflowMetrics; import com.hedera.node.app.workflows.dispatcher.TransactionDispatcher; import com.hedera.node.app.workflows.handle.cache.CacheWarmer; import com.hedera.node.app.workflows.handle.dispatch.ChildDispatchFactory; -import com.hedera.node.app.workflows.handle.metric.HandleWorkflowMetrics; import com.hedera.node.app.workflows.handle.record.SystemSetup; import com.hedera.node.app.workflows.handle.steps.HollowAccountCompletions; import com.hedera.node.app.workflows.handle.steps.NodeStakeUpdates; @@ -112,7 +112,7 @@ class HandleWorkflowTest { private CacheWarmer cacheWarmer; @Mock - private HandleWorkflowMetrics handleWorkflowMetrics; + private OpWorkflowMetrics opWorkflowMetrics; @Mock private ThrottleServiceManager throttleServiceManager; @@ -173,7 +173,7 @@ void setUp() { blockRecordManager, blockStreamManager, cacheWarmer, - handleWorkflowMetrics, + opWorkflowMetrics, throttleServiceManager, version, initTrigger, diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/metrics/HandleWorkflowMetricsTest.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/metrics/OpWorkflowMetricsTest.java similarity index 68% rename from hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/metrics/HandleWorkflowMetricsTest.java rename to hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/metrics/OpWorkflowMetricsTest.java index 0334210da05d..6ceadc9e6a31 100644 --- a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/metrics/HandleWorkflowMetricsTest.java +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/metrics/OpWorkflowMetricsTest.java @@ -23,7 +23,7 @@ import com.hedera.hapi.node.base.HederaFunctionality; import com.hedera.node.app.utils.TestUtils; -import com.hedera.node.app.workflows.handle.metric.HandleWorkflowMetrics; +import com.hedera.node.app.workflows.OpWorkflowMetrics; import com.hedera.node.config.ConfigProvider; import com.hedera.node.config.VersionedConfigImpl; import com.hedera.node.config.testfixtures.HederaTestConfigBuilder; @@ -31,7 +31,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -class HandleWorkflowMetricsTest { +class OpWorkflowMetricsTest { private final Metrics metrics = TestUtils.metrics(); private ConfigProvider configProvider; @@ -44,15 +44,14 @@ void setUp() { @SuppressWarnings("DataFlowIssue") @Test void testConstructorWithInvalidArguments() { - assertThatThrownBy(() -> new HandleWorkflowMetrics(null, configProvider)) - .isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> new HandleWorkflowMetrics(metrics, null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> new OpWorkflowMetrics(null, configProvider)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> new OpWorkflowMetrics(metrics, null)).isInstanceOf(NullPointerException.class); } @Test void testConstructorInitializesMetrics() { // when - new HandleWorkflowMetrics(metrics, configProvider); + new OpWorkflowMetrics(metrics, configProvider); // then final int transactionMetricsCount = (HederaFunctionality.values().length - 1) * 2; @@ -62,7 +61,7 @@ void testConstructorInitializesMetrics() { @Test void testInitialValue() { // given - new HandleWorkflowMetrics(metrics, configProvider); + new OpWorkflowMetrics(metrics, configProvider); // then assertThat(metrics.getMetric("app", "cryptoCreateDurationMax").get(VALUE)) @@ -73,22 +72,22 @@ void testInitialValue() { @SuppressWarnings("DataFlowIssue") @Test - void testUpdateTransactionDurationWithInvalidArguments() { + void testUpdateDurationWithInvalidArguments() { // given - final var handleWorkflowMetrics = new HandleWorkflowMetrics(metrics, configProvider); + final var handleWorkflowMetrics = new OpWorkflowMetrics(metrics, configProvider); // when - assertThatThrownBy(() -> handleWorkflowMetrics.updateTransactionDuration(null, 0)) + assertThatThrownBy(() -> handleWorkflowMetrics.updateDuration(null, 0)) .isInstanceOf(NullPointerException.class); } @Test void testUpdateTransactionDurationSingleUpdate() { // given - final var handleWorkflowMetrics = new HandleWorkflowMetrics(metrics, configProvider); + final var handleWorkflowMetrics = new OpWorkflowMetrics(metrics, configProvider); // when - handleWorkflowMetrics.updateTransactionDuration(HederaFunctionality.CRYPTO_CREATE, 42); + handleWorkflowMetrics.updateDuration(HederaFunctionality.CRYPTO_CREATE, 42); // then assertThat(metrics.getMetric("app", "cryptoCreateDurationMax").get(VALUE)) @@ -98,13 +97,13 @@ void testUpdateTransactionDurationSingleUpdate() { } @Test - void testUpdateTransactionDurationTwoUpdates() { + void testUpdateDurationTwoUpdates() { // given - final var handleWorkflowMetrics = new HandleWorkflowMetrics(metrics, configProvider); + final var handleWorkflowMetrics = new OpWorkflowMetrics(metrics, configProvider); // when - handleWorkflowMetrics.updateTransactionDuration(HederaFunctionality.CRYPTO_CREATE, 11); - handleWorkflowMetrics.updateTransactionDuration(HederaFunctionality.CRYPTO_CREATE, 22); + handleWorkflowMetrics.updateDuration(HederaFunctionality.CRYPTO_CREATE, 11); + handleWorkflowMetrics.updateDuration(HederaFunctionality.CRYPTO_CREATE, 22); // then assertThat(metrics.getMetric("app", "cryptoCreateDurationMax").get(VALUE)) @@ -114,14 +113,14 @@ void testUpdateTransactionDurationTwoUpdates() { } @Test - void testUpdateTransactionDurationThreeUpdates() { + void testUpdateDurationThreeUpdates() { // given - final var handleWorkflowMetrics = new HandleWorkflowMetrics(metrics, configProvider); + final var handleWorkflowMetrics = new OpWorkflowMetrics(metrics, configProvider); // when - handleWorkflowMetrics.updateTransactionDuration(HederaFunctionality.CRYPTO_CREATE, 13); - handleWorkflowMetrics.updateTransactionDuration(HederaFunctionality.CRYPTO_CREATE, 5); - handleWorkflowMetrics.updateTransactionDuration(HederaFunctionality.CRYPTO_CREATE, 3); + handleWorkflowMetrics.updateDuration(HederaFunctionality.CRYPTO_CREATE, 13); + handleWorkflowMetrics.updateDuration(HederaFunctionality.CRYPTO_CREATE, 5); + handleWorkflowMetrics.updateDuration(HederaFunctionality.CRYPTO_CREATE, 3); // then assertThat(metrics.getMetric("app", "cryptoCreateDurationMax").get(VALUE)) @@ -133,7 +132,7 @@ void testUpdateTransactionDurationThreeUpdates() { @Test void testInitialStartConsensusRound() { // given - final var handleWorkflowMetrics = new HandleWorkflowMetrics(metrics, configProvider); + final var handleWorkflowMetrics = new OpWorkflowMetrics(metrics, configProvider); // when handleWorkflowMetrics.switchConsensusSecond(); @@ -146,7 +145,7 @@ void testInitialStartConsensusRound() { @Test void testUpdateGasZero() { // given - final var handleWorkflowMetrics = new HandleWorkflowMetrics(metrics, configProvider); + final var handleWorkflowMetrics = new OpWorkflowMetrics(metrics, configProvider); // when handleWorkflowMetrics.addGasUsed(0L); @@ -160,7 +159,7 @@ void testUpdateGasZero() { @Test void testUpdateGas() { // given - final var handleWorkflowMetrics = new HandleWorkflowMetrics(metrics, configProvider); + final var handleWorkflowMetrics = new OpWorkflowMetrics(metrics, configProvider); // when handleWorkflowMetrics.addGasUsed(1_000_000L); diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/throttle/DispatchUsageManagerTest.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/throttle/DispatchUsageManagerTest.java index 2472fd3ae76b..a961d88d28cb 100644 --- a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/throttle/DispatchUsageManagerTest.java +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/throttle/DispatchUsageManagerTest.java @@ -53,9 +53,9 @@ import com.hedera.node.app.throttle.CongestionThrottleService; import com.hedera.node.app.throttle.NetworkUtilizationManager; import com.hedera.node.app.throttle.ThrottleServiceManager; +import com.hedera.node.app.workflows.OpWorkflowMetrics; import com.hedera.node.app.workflows.TransactionInfo; import com.hedera.node.app.workflows.handle.Dispatch; -import com.hedera.node.app.workflows.handle.metric.HandleWorkflowMetrics; import com.hedera.node.app.workflows.handle.record.RecordStreamBuilder; import com.hedera.node.app.workflows.handle.stack.SavepointStackImpl; import com.hedera.node.config.testfixtures.HederaTestConfigBuilder; @@ -147,7 +147,7 @@ class DispatchUsageManagerTest { private RecordStreamBuilder recordBuilder; @Mock - private HandleWorkflowMetrics handleWorkflowMetrics; + private OpWorkflowMetrics opWorkflowMetrics; @Mock private ThrottleServiceManager throttleServiceManager; @@ -166,7 +166,7 @@ class DispatchUsageManagerTest { @BeforeEach void setUp() { subject = new DispatchUsageManager( - networkInfo, handleWorkflowMetrics, throttleServiceManager, networkUtilizationManager); + networkInfo, opWorkflowMetrics, throttleServiceManager, networkUtilizationManager); } @Test @@ -245,7 +245,7 @@ void onlySnapshotsForNonAutoCreatingOperations() { subject.finalizeAndSaveUsage(dispatch); verify(throttleServiceManager).saveThrottleSnapshotsAndCongestionLevelStartsTo(stack); - verifyNoInteractions(handleWorkflowMetrics); + verifyNoInteractions(opWorkflowMetrics); } @Test @@ -260,7 +260,7 @@ void leaksUnusedGasForContractCall() { subject.finalizeAndSaveUsage(dispatch); - verify(handleWorkflowMetrics).addGasUsed(GAS_USED); + verify(opWorkflowMetrics).addGasUsed(GAS_USED); verify(networkUtilizationManager).leakUnusedGasPreviouslyReserved(CONTRACT_CALL_TXN_INFO, GAS_LIMIT - GAS_USED); verify(throttleServiceManager).saveThrottleSnapshotsAndCongestionLevelStartsTo(stack); } @@ -277,7 +277,7 @@ void leaksUnusedGasForContractCreate() { subject.finalizeAndSaveUsage(dispatch); - verify(handleWorkflowMetrics).addGasUsed(GAS_USED); + verify(opWorkflowMetrics).addGasUsed(GAS_USED); verify(networkUtilizationManager) .leakUnusedGasPreviouslyReserved(CONTRACT_CREATE_TXN_INFO, GAS_LIMIT - GAS_USED); verify(throttleServiceManager).saveThrottleSnapshotsAndCongestionLevelStartsTo(stack); @@ -297,7 +297,7 @@ void leaksUnusedGasForEthTx() { subject.finalizeAndSaveUsage(dispatch); - verify(handleWorkflowMetrics).addGasUsed(GAS_USED); + verify(opWorkflowMetrics).addGasUsed(GAS_USED); verify(networkUtilizationManager) .leakUnusedGasPreviouslyReserved(ETH_TXN_INFO, ETH_DATA_WITH_TO_ADDRESS.gasLimit() - GAS_USED); verify(throttleServiceManager).saveThrottleSnapshotsAndCongestionLevelStartsTo(stack); @@ -312,7 +312,7 @@ void doesNotLeakUnusedGasForContractOperationWithoutResult() { subject.finalizeAndSaveUsage(dispatch); - verify(handleWorkflowMetrics, never()).addGasUsed(GAS_USED); + verify(opWorkflowMetrics, never()).addGasUsed(GAS_USED); verify(networkUtilizationManager, never()).leakUnusedGasPreviouslyReserved(any(), anyLong()); verify(throttleServiceManager).saveThrottleSnapshotsAndCongestionLevelStartsTo(stack); } diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/query/QueryWorkflowImplTest.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/query/QueryWorkflowImplTest.java index 9693407501a2..cdebdc507949 100644 --- a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/query/QueryWorkflowImplTest.java +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/query/QueryWorkflowImplTest.java @@ -18,6 +18,7 @@ import static com.hedera.hapi.node.base.HederaFunctionality.CRYPTO_TRANSFER; import static com.hedera.hapi.node.base.HederaFunctionality.FILE_GET_INFO; +import static com.hedera.hapi.node.base.HederaFunctionality.NETWORK_GET_EXECUTION_TIME; import static com.hedera.hapi.node.base.ResponseCodeEnum.BUSY; import static com.hedera.hapi.node.base.ResponseCodeEnum.INSUFFICIENT_TX_FEE; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_NODE_ACCOUNT; @@ -32,6 +33,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.BDDMockito.given; @@ -70,6 +72,7 @@ import com.hedera.node.app.spi.workflows.PreCheckException; import com.hedera.node.app.spi.workflows.QueryContext; import com.hedera.node.app.throttle.SynchronizedThrottleAccumulator; +import com.hedera.node.app.workflows.OpWorkflowMetrics; import com.hedera.node.app.workflows.TransactionInfo; import com.hedera.node.app.workflows.ingest.IngestChecker; import com.hedera.node.app.workflows.ingest.SubmissionManager; @@ -144,6 +147,9 @@ class QueryWorkflowImplTest extends AppTestBase { @Mock(strictness = LENIENT) private SynchronizedThrottleAccumulator synchronizedThrottleAccumulator; + @Mock + private OpWorkflowMetrics opWorkflowMetrics; + private VersionedConfiguration configuration; private Transaction payment; private TransactionBody txBody; @@ -211,7 +217,8 @@ void setup(@Mock FeeCalculator feeCalculator) throws ParseException, PreCheckExc exchangeRateManager, feeManager, synchronizedThrottleAccumulator, - instantSource); + instantSource, + opWorkflowMetrics); } @SuppressWarnings("ConstantConditions") @@ -230,7 +237,8 @@ void testConstructorWithIllegalParameters() { exchangeRateManager, feeManager, synchronizedThrottleAccumulator, - instantSource)) + instantSource, + opWorkflowMetrics)) .isInstanceOf(NullPointerException.class); assertThatThrownBy(() -> new QueryWorkflowImpl( stateAccessor, @@ -245,7 +253,8 @@ void testConstructorWithIllegalParameters() { exchangeRateManager, feeManager, synchronizedThrottleAccumulator, - instantSource)) + instantSource, + opWorkflowMetrics)) .isInstanceOf(NullPointerException.class); assertThatThrownBy(() -> new QueryWorkflowImpl( stateAccessor, @@ -260,7 +269,8 @@ void testConstructorWithIllegalParameters() { exchangeRateManager, feeManager, synchronizedThrottleAccumulator, - instantSource)) + instantSource, + opWorkflowMetrics)) .isInstanceOf(NullPointerException.class); assertThatThrownBy(() -> new QueryWorkflowImpl( stateAccessor, @@ -275,7 +285,8 @@ void testConstructorWithIllegalParameters() { exchangeRateManager, feeManager, synchronizedThrottleAccumulator, - instantSource)) + instantSource, + opWorkflowMetrics)) .isInstanceOf(NullPointerException.class); assertThatThrownBy(() -> new QueryWorkflowImpl( stateAccessor, @@ -290,7 +301,8 @@ void testConstructorWithIllegalParameters() { exchangeRateManager, feeManager, synchronizedThrottleAccumulator, - instantSource)) + instantSource, + opWorkflowMetrics)) .isInstanceOf(NullPointerException.class); assertThatThrownBy(() -> new QueryWorkflowImpl( stateAccessor, @@ -305,7 +317,8 @@ void testConstructorWithIllegalParameters() { exchangeRateManager, feeManager, synchronizedThrottleAccumulator, - instantSource)) + instantSource, + opWorkflowMetrics)) .isInstanceOf(NullPointerException.class); assertThatThrownBy(() -> new QueryWorkflowImpl( stateAccessor, @@ -320,7 +333,8 @@ void testConstructorWithIllegalParameters() { exchangeRateManager, feeManager, synchronizedThrottleAccumulator, - instantSource)) + instantSource, + opWorkflowMetrics)) .isInstanceOf(NullPointerException.class); assertThatThrownBy(() -> new QueryWorkflowImpl( stateAccessor, @@ -335,7 +349,8 @@ void testConstructorWithIllegalParameters() { exchangeRateManager, feeManager, synchronizedThrottleAccumulator, - instantSource)) + instantSource, + opWorkflowMetrics)) .isInstanceOf(NullPointerException.class); assertThatThrownBy(() -> new QueryWorkflowImpl( stateAccessor, @@ -350,7 +365,8 @@ void testConstructorWithIllegalParameters() { exchangeRateManager, feeManager, synchronizedThrottleAccumulator, - instantSource)) + instantSource, + opWorkflowMetrics)) .isInstanceOf(NullPointerException.class); assertThatThrownBy(() -> new QueryWorkflowImpl( stateAccessor, @@ -365,7 +381,8 @@ void testConstructorWithIllegalParameters() { exchangeRateManager, feeManager, synchronizedThrottleAccumulator, - instantSource)) + instantSource, + opWorkflowMetrics)) .isInstanceOf(NullPointerException.class); assertThatThrownBy(() -> new QueryWorkflowImpl( stateAccessor, @@ -380,7 +397,8 @@ void testConstructorWithIllegalParameters() { null, feeManager, synchronizedThrottleAccumulator, - instantSource)) + instantSource, + opWorkflowMetrics)) .isInstanceOf(NullPointerException.class); assertThatThrownBy(() -> new QueryWorkflowImpl( stateAccessor, @@ -395,7 +413,24 @@ void testConstructorWithIllegalParameters() { exchangeRateManager, feeManager, null, - instantSource)) + instantSource, + opWorkflowMetrics)) + .isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> new QueryWorkflowImpl( + stateAccessor, + submissionManager, + queryChecker, + ingestChecker, + dispatcher, + queryParser, + configProvider, + recordCache, + authorizer, + exchangeRateManager, + feeManager, + synchronizedThrottleAccumulator, + instantSource, + null)) .isInstanceOf(NullPointerException.class); } @@ -424,6 +459,7 @@ void testSuccessIfPaymentNotRequired() throws ParseException { assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(OK); assertThat(header.responseType()).isEqualTo(ANSWER_ONLY); assertThat(header.cost()).isZero(); + verifyMetricsSent(); } @Test @@ -448,6 +484,7 @@ void testSuccessIfPaymentRequired() throws ParseException { assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(OK); assertThat(header.responseType()).isEqualTo(ANSWER_ONLY); assertThat(header.cost()).isZero(); + verifyMetricsSent(); } @Test @@ -480,6 +517,7 @@ void testSuccessIfPaymentRequiredAndNotProvided() throws ParseException, PreChec assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(INSUFFICIENT_TX_FEE); assertThat(header.responseType()).isEqualTo(ANSWER_ONLY); assertThat(header.cost()).isZero(); + verifyMetricsSent(); } @Test @@ -516,6 +554,7 @@ void testSuccessIfCostOnly() throws ParseException { assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(OK); assertThat(header.responseType()).isEqualTo(COST_ANSWER); assertThat(header.cost()).isEqualTo(fees.totalFee()); + verifyMetricsSent(); } @Test @@ -570,6 +609,7 @@ void testInvalidNodeFails() throws PreCheckException, ParseException { assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(INVALID_NODE_ACCOUNT); assertThat(header.responseType()).isEqualTo(ANSWER_ONLY); assertThat(header.cost()).isZero(); + verifyMetricsSent(); } @Test @@ -597,6 +637,7 @@ void testUnsupportedResponseTypeFails() throws ParseException { assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(NOT_SUPPORTED); assertThat(header.responseType()).isEqualTo(ANSWER_STATE_PROOF); assertThat(header.cost()).isZero(); + verifyMetricsSent(); } @Test @@ -615,6 +656,7 @@ void testThrottleFails() throws ParseException { assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(BUSY); assertThat(header.responseType()).isEqualTo(ANSWER_ONLY); assertThat(header.cost()).isZero(); + verifyMetricsSent(); } @Test @@ -635,6 +677,7 @@ void testPaidQueryWithInvalidTransactionFails() throws PreCheckException, ParseE assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(INVALID_TRANSACTION_BODY); assertThat(header.responseType()).isEqualTo(ANSWER_ONLY); assertThat(header.cost()).isZero(); + verifyMetricsSent(); } @Test @@ -653,6 +696,7 @@ void testPaidQueryWithInvalidCryptoTransferFails() throws PreCheckException, Par assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(INSUFFICIENT_TX_FEE); assertThat(header.responseType()).isEqualTo(ANSWER_ONLY); assertThat(header.cost()).isZero(); + verifyMetricsSent(); } @Test @@ -680,6 +724,7 @@ void testPaidQueryForSuperUserDoesNotSubmitCryptoTransfer() throws PreCheckExcep assertThat(header.cost()).isZero(); verify(submissionManager, never()).submit(any(), any()); + verifyMetricsSent(); } @Test @@ -700,6 +745,7 @@ void testPaidQueryWithInsufficientPermissionFails() throws PreCheckException, Pa assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(NOT_SUPPORTED); assertThat(header.responseType()).isEqualTo(ANSWER_ONLY); assertThat(header.cost()).isZero(); + verifyMetricsSent(); } @Test @@ -724,6 +770,7 @@ void testPaidQueryWithInsufficientBalanceFails() throws PreCheckException, Parse assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(INSUFFICIENT_TX_FEE); assertThat(header.responseType()).isEqualTo(ANSWER_ONLY); assertThat(header.cost()).isEqualTo(12345L); + verifyMetricsSent(); } @Test @@ -763,6 +810,7 @@ void testUnpaidQueryWithRestrictedFunctionalityFails(@Mock NetworkGetExecutionTi assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(NOT_SUPPORTED); assertThat(header.responseType()).isEqualTo(COST_ANSWER); assertThat(header.cost()).isZero(); + verify(opWorkflowMetrics).updateDuration(eq(NETWORK_GET_EXECUTION_TIME), anyInt()); } @Test @@ -785,6 +833,7 @@ void testQuerySpecificValidationFails() throws PreCheckException, ParseException assertThat(header.cost()).isZero(); final var queryContext = captor.getValue(); assertThat(queryContext.payer()).isNull(); + verifyMetricsSent(); } @Test @@ -806,6 +855,11 @@ void testPaidQueryWithFailingSubmissionFails() throws PreCheckException, ParseEx assertThat(header.nodeTransactionPrecheckCode()).isEqualTo(PLATFORM_TRANSACTION_NOT_CREATED); assertThat(header.responseType()).isEqualTo(ANSWER_ONLY); assertThat(header.cost()).isZero(); + verifyMetricsSent(); + } + + private void verifyMetricsSent() { + verify(opWorkflowMetrics).updateDuration(eq(FILE_GET_INFO), anyInt()); } private static Response parseResponse(BufferedData responseBuffer) throws ParseException {