Skip to content

Commit

Permalink
refactor: MetricsService refactor to use an interface (#142)
Browse files Browse the repository at this point in the history
Signed-off-by: Alfredo Gutierrez <[email protected]>
  • Loading branch information
AlfredoG87 authored Aug 27, 2024
1 parent 36992db commit 75ce0b3
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ private void singleBlock(
fromPbjSingleBlockSuccessResponse(blockOpt.get()));

final MetricsService metricsService = blockNodeContext.metricsService();
metricsService.singleBlocksRetrieved.increment();
metricsService.singleBlocksRetrieved().increment();
} else {
LOGGER.log(DEBUG, "Block number {0} not found", blockNumber);
singleBlockResponseStreamObserver.onNext(buildSingleBlockNotFoundResponse());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public void publish(@NonNull final BlockItem blockItem) throws IOException {
ringBuffer.publishEvent((event, sequence) -> event.set(subscribeStreamResponse));

// Increment the block item counter
metricsService.liveBlockItems.increment();
metricsService.liveBlockItems().increment();

try {
// Persist the BlockItem
Expand Down Expand Up @@ -211,7 +211,7 @@ private static SubscribeStreamResponse buildEndStreamResponse() {

private void updateSubscriberMetrics() {
@NonNull final MetricsService metricsService = blockNodeContext.metricsService();
@NonNull final LongGauge longGauge = metricsService.subscribers;
@NonNull final LongGauge longGauge = metricsService.subscribers();
longGauge.set(subscribers.size());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.swirlds.common.metrics.platform.DefaultMetricsProvider;
import com.swirlds.config.api.Configuration;
import com.swirlds.metrics.api.Metrics;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import javax.inject.Singleton;
Expand All @@ -30,14 +31,12 @@ public interface MetricsInjectionModule {
/**
* Provides the metrics service.
*
* @param metrics the metrics to be used by the service
* @param metricsService the metrics service to be used
* @return the metrics service
*/
@Singleton
@Provides
static MetricsService provideMetricsService(Metrics metrics) {
return new MetricsService(metrics);
}
@Binds
MetricsService bindMetricsService(MetricsServiceImpl metricsService);

/**
* Provides the metrics.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,57 +18,39 @@

import com.swirlds.metrics.api.Counter;
import com.swirlds.metrics.api.LongGauge;
import com.swirlds.metrics.api.Metrics;
import edu.umd.cs.findbugs.annotations.NonNull;

/**
* Use member variables of this class to update metric data for the Hedera Block Node.
*
* <p>Metrics are updated by calling the appropriate method on the metric object instance. For
* example, to increment a counter, call {@link Counter#increment()}.
*/
public class MetricsService {

private static final String CATEGORY = "hedera_block_node";

// Live BlockItem Counter
private static final Counter.Config LIVE_BLOCK_ITEM_COUNTER =
new Counter.Config(CATEGORY, "live_block_items").withDescription("Live BlockItems");

// Block Persistence Counter
private static final Counter.Config BLOCK_PERSISTENCE_COUNTER =
new Counter.Config(CATEGORY, "blocks_persisted").withDescription("Blocks Persisted");

// Subscriber Gauge
private static final LongGauge.Config SUBSCRIBER_GAUGE =
new LongGauge.Config(CATEGORY, "subscribers").withDescription("Subscribers");

// Single Block Retrieved Counter
private static final Counter.Config SINGLE_BLOCK_RETRIEVED_COUNTER =
new Counter.Config(CATEGORY, "single_blocks_retrieved")
.withDescription("Single Blocks Retrieved");

/** Update the counter of live block items transiting via the live stream. */
public final Counter liveBlockItems;

/** Update the counter of blocks persisted to storage. */
public final Counter blocksPersisted;
/** Use member variables of this class to update metric data for the Hedera Block Node. */
public interface MetricsService {
/**
* Update the counter of live block items transiting via the live stream.
*
* @return use this metric to increase the counter of block items received
*/
@NonNull
Counter liveBlockItems();

/** Update the counter of single blocks retrieved from storage. */
public final Counter singleBlocksRetrieved;
/**
* Update the counter of blocks persisted to storage.
*
* @return use this counter to increase the amount of blocks persisted to disk
*/
@NonNull
Counter blocksPersisted();

/** Update the gauge of subscribers currently consuming to the live stream. */
public final LongGauge subscribers;
/**
* Update the counter of single blocks retrieved from storage.
*
* @return use this metric to increase the counter of single blocks retrieved
*/
@NonNull
Counter singleBlocksRetrieved();

/**
* Create singleton instance of metrics service to be used throughout the application.
* Update the gauge of subscribers currently consuming to the live stream.
*
* @param metrics the metrics instance
* @return Use this to increase or decrease the amount of current subscribers to the live stream
*/
public MetricsService(@NonNull final Metrics metrics) {
this.liveBlockItems = metrics.getOrCreate(LIVE_BLOCK_ITEM_COUNTER);
this.blocksPersisted = metrics.getOrCreate(BLOCK_PERSISTENCE_COUNTER);
this.singleBlocksRetrieved = metrics.getOrCreate(SINGLE_BLOCK_RETRIEVED_COUNTER);
this.subscribers = metrics.getOrCreate(SUBSCRIBER_GAUGE);
}
@NonNull
LongGauge subscribers();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.hedera.block.server.metrics;

import com.swirlds.metrics.api.Counter;
import com.swirlds.metrics.api.LongGauge;
import com.swirlds.metrics.api.Metrics;
import edu.umd.cs.findbugs.annotations.NonNull;
import javax.inject.Inject;

/**
* Use member variables of this class to update metric data for the Hedera Block Node.
*
* <p>Metrics are updated by calling the appropriate method on the metric object instance. For
* example, to increment a counter, call {@link Counter#increment()}.
*/
public class MetricsServiceImpl implements MetricsService {

private static final String CATEGORY = "hedera_block_node";

// Live BlockItem Counter
private static final Counter.Config LIVE_BLOCK_ITEM_COUNTER =
new Counter.Config(CATEGORY, "live_block_items").withDescription("Live BlockItems");

// Block Persistence Counter
private static final Counter.Config BLOCK_PERSISTENCE_COUNTER =
new Counter.Config(CATEGORY, "blocks_persisted").withDescription("Blocks Persisted");

// Subscriber Gauge
private static final LongGauge.Config SUBSCRIBER_GAUGE =
new LongGauge.Config(CATEGORY, "subscribers").withDescription("Subscribers");

// Single Block Retrieved Counter
private static final Counter.Config SINGLE_BLOCK_RETRIEVED_COUNTER =
new Counter.Config(CATEGORY, "single_blocks_retrieved")
.withDescription("Single Blocks Retrieved");

private final Counter liveBlockItems;

private final Counter blocksPersisted;

private final Counter singleBlocksRetrieved;

private final LongGauge subscribers;

/** Update the counter of live block items transiting via the live stream. */
@Override
@NonNull
public final Counter liveBlockItems() {
return liveBlockItems;
}

/** Update the counter of blocks persisted to storage. */
@Override
@NonNull
public final Counter blocksPersisted() {
return blocksPersisted;
}

/** Update the counter of single blocks retrieved from storage. */
@Override
@NonNull
public final Counter singleBlocksRetrieved() {
return singleBlocksRetrieved;
}

/** Update the gauge of subscribers currently consuming to the live stream. */
@Override
@NonNull
public final LongGauge subscribers() {
return subscribers;
}

/**
* Create singleton instance of metrics service to be used throughout the application.
*
* @param metrics the metrics instance
*/
@Inject
public MetricsServiceImpl(@NonNull final Metrics metrics) {
this.liveBlockItems = metrics.getOrCreate(LIVE_BLOCK_ITEM_COUNTER);
this.blocksPersisted = metrics.getOrCreate(BLOCK_PERSISTENCE_COUNTER);
this.singleBlocksRetrieved = metrics.getOrCreate(SINGLE_BLOCK_RETRIEVED_COUNTER);
this.subscribers = metrics.getOrCreate(SUBSCRIBER_GAUGE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private void resetState(@NonNull final BlockItem blockItem) throws IOException {

// Increment the block counter
final MetricsService metricsService = blockNodeContext.metricsService();
metricsService.blocksPersisted.increment();
metricsService.blocksPersisted().increment();
}

private void repairPermissions(@NonNull final Path path) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ public void testSubscribeBlockStream() throws IOException {
streamObserver.onNext(fromPbj(publishStreamRequest));

// Verify the counter was incremented
assertEquals(1, blockNodeContext.metricsService().liveBlockItems.get());
assertEquals(1, blockNodeContext.metricsService().liveBlockItems().get());

verify(blockWriter, timeout(testTimeout).times(1)).write(blockItems.getFirst());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static org.mockito.Mockito.*;

import com.hedera.block.server.metrics.MetricsService;
import com.hedera.block.server.metrics.MetricsServiceImpl;
import com.swirlds.config.api.Configuration;
import org.junit.jupiter.api.Test;

Expand All @@ -28,7 +29,7 @@ class BlockNodeContextTest {
@Test
void BlockNodeContext_initializesWithMetricsAndConfiguration() {
Configuration configuration = mock(Configuration.class);
MetricsService metricsService = mock(MetricsService.class);
MetricsService metricsService = mock(MetricsServiceImpl.class);

BlockNodeContext context = new BlockNodeContext(metricsService, configuration);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ public TestConfigBuilder withValue(
* @return the created configuration
*/
@NonNull
@SuppressWarnings({"removal"})
public Configuration getOrCreateConfig() {
try (final Locked ignore = configLock.lock()) {
if (configuration == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public void testUnsubscribeEach() throws InterruptedException, IOException {
"Expected the mediator to have unsubscribed observer3");

// Confirm the counter was never incremented
assertEquals(0, blockNodeContext.metricsService().liveBlockItems.get());
assertEquals(0, blockNodeContext.metricsService().liveBlockItems().get());
}

@Test
Expand All @@ -148,7 +148,7 @@ blockWriter, blockNodeContext, new ServiceStatusImpl())
streamMediator.publish(blockItem);

// Verify the counter was incremented
assertEquals(1, blockNodeContext.metricsService().liveBlockItems.get());
assertEquals(1, blockNodeContext.metricsService().liveBlockItems().get());

// Confirm the BlockStorage write method was
// called despite the absence of subscribers
Expand Down Expand Up @@ -201,7 +201,7 @@ blockWriter, blockNodeContext, new ServiceStatusImpl())
// Acting as a producer, notify the mediator of a new block
streamMediator.publish(blockItem);

assertEquals(1, blockNodeContext.metricsService().liveBlockItems.get());
assertEquals(1, blockNodeContext.metricsService().liveBlockItems().get());

// Confirm each subscriber was notified of the new block
verify(streamObserver1, timeout(testTimeout).times(1))
Expand Down Expand Up @@ -248,7 +248,7 @@ blockWriter, blockNodeContext, new ServiceStatusImpl())
streamMediator.unsubscribe(concreteObserver3);

// Confirm the counter was never incremented
assertEquals(0, blockNodeContext.metricsService().liveBlockItems.get());
assertEquals(0, blockNodeContext.metricsService().liveBlockItems().get());
}

@Test
Expand Down Expand Up @@ -277,7 +277,7 @@ blockWriter, blockNodeContext, new ServiceStatusImpl())
testConsumerBlockItemObserver.getOnCancel().run();

// Verify the block item incremented the counter
assertEquals(1, blockNodeContext.metricsService().liveBlockItems.get());
assertEquals(1, blockNodeContext.metricsService().liveBlockItems().get());

// Verify the event made it to the consumer
verify(serverCallStreamObserver, timeout(testTimeout).times(1)).setOnCancelHandler(any());
Expand Down Expand Up @@ -313,7 +313,7 @@ blockWriter, blockNodeContext, new ServiceStatusImpl())
testConsumerBlockItemObserver.getOnClose().run();

// Verify the block item incremented the counter
assertEquals(1, blockNodeContext.metricsService().liveBlockItems.get());
assertEquals(1, blockNodeContext.metricsService().liveBlockItems().get());

// Verify the event made it to the consumer
verify(serverCallStreamObserver, timeout(testTimeout).times(1)).setOnCancelHandler(any());
Expand Down Expand Up @@ -348,7 +348,7 @@ blockWriter, blockNodeContext, new ServiceStatusImpl())
streamMediator.publish(secondBlockItem);

// Confirm the counter was incremented only once
assertEquals(1, blockNodeContext.metricsService().liveBlockItems.get());
assertEquals(1, blockNodeContext.metricsService().liveBlockItems().get());

// Confirm the BlockPersistenceHandler write method was only called
// once despite the second block being published.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,11 @@
import java.io.IOException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class MetricsInjectionModuleTest {

@Mock private Metrics metrics;

@Test
void testProvideMetricsService() {
// Call the method under test
MetricsService metricsService = MetricsInjectionModule.provideMetricsService(metrics);

// Verify that the metricsService is correctly instantiated
assertNotNull(metricsService);
}

@Test
void testProvideMetrics() throws IOException {
BlockNodeContext context = TestConfigUtil.getTestBlockNodeContext();
Expand Down
Loading

0 comments on commit 75ce0b3

Please sign in to comment.