Skip to content

Commit 9962cae

Browse files
authored
Add metrics for inbound and outbound peer counts (Consensys#8162)
1 parent 4ddd20c commit 9962cae

File tree

3 files changed

+73
-9
lines changed

3 files changed

+73
-9
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ the [releases page](https://github.com/Consensys/teku/releases).
1313

1414
### Additions and Improvements
1515
- Increased the executor queue default maximum size to 40_000 (previously 20_000), and other queues to 10_000 (previously 5_000). If you have custom settings for these queues, check to ensure they're still required.
16+
- Added `peers_direction_current` LIBP2P metric for the number of peers by direction including inbound and outbound.
1617

1718
### Bug Fixes

Diff for: networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/PeerManager.java

+17-3
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,29 @@ public PeerManager(
7070
this.peerScoreFunction = peerScoreFunction;
7171
metricsSystem.createGauge(
7272
TekuMetricCategory.LIBP2P, "peers", "Tracks number of libp2p peers", this::getPeerCount);
73-
final LabelledGauge peersLabelledGauge =
73+
final LabelledGauge peerClientLabelledGauge =
7474
metricsSystem.createLabelledGauge(
7575
TekuMetricCategory.LIBP2P,
7676
"connected_peers_current",
7777
"The number of clients connected by client type",
7878
"client");
7979

8080
for (PeerClientType type : PeerClientType.values()) {
81-
peersLabelledGauge.labels(() -> countConnectedPeersOfType(type), type.getDisplayName());
81+
peerClientLabelledGauge.labels(() -> countConnectedPeersOfType(type), type.getDisplayName());
8282
}
83+
84+
final LabelledGauge peerDirectionLabelledGauge =
85+
metricsSystem.createLabelledGauge(
86+
TekuMetricCategory.LIBP2P,
87+
"peers_direction_current",
88+
"The number of peers by direction including inbound and outbound",
89+
"direction");
90+
peerDirectionLabelledGauge.labels(
91+
() -> connectedPeerMap.values().stream().filter(Peer::connectionInitiatedRemotely).count(),
92+
"inbound");
93+
peerDirectionLabelledGauge.labels(
94+
() -> connectedPeerMap.values().stream().filter(Peer::connectionInitiatedLocally).count(),
95+
"outbound");
8396
}
8497

8598
@Override
@@ -164,7 +177,8 @@ void onConnectedPeer(Peer peer) {
164177
}
165178
}
166179

167-
private void onDisconnectedPeer(
180+
@VisibleForTesting
181+
void onDisconnectedPeer(
168182
final Peer peer, final Optional<DisconnectReason> reason, final boolean locallyInitiated) {
169183
if (connectedPeerMap.remove(peer.getId()) != null) {
170184
LOG.debug("Peer disconnected: {}", peer.getId());

Diff for: networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/PeerManagerTest.java

+55-6
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@
3030
import java.util.ArrayList;
3131
import java.util.Collections;
3232
import java.util.List;
33+
import java.util.Optional;
3334
import java.util.concurrent.CompletableFuture;
34-
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
3535
import org.hyperledger.besu.plugin.services.MetricsSystem;
3636
import org.hyperledger.besu.plugin.services.metrics.LabelledGauge;
3737
import org.junit.jupiter.api.Assertions;
3838
import org.junit.jupiter.api.Test;
3939
import tech.pegasys.teku.infrastructure.async.SafeFuture;
40+
import tech.pegasys.teku.infrastructure.metrics.StubLabelledGauge;
41+
import tech.pegasys.teku.infrastructure.metrics.StubMetricsSystem;
4042
import tech.pegasys.teku.infrastructure.metrics.TekuMetricCategory;
4143
import tech.pegasys.teku.networking.p2p.mock.MockNodeId;
4244
import tech.pegasys.teku.networking.p2p.peer.Peer;
@@ -46,10 +48,11 @@ public class PeerManagerTest {
4648

4749
private final ReputationManager reputationManager = mock(ReputationManager.class);
4850
private final Network network = mock(Network.class);
51+
final StubMetricsSystem metricsSystem = new StubMetricsSystem();
4952

5053
private final PeerManager peerManager =
5154
new PeerManager(
52-
new NoOpMetricsSystem(),
55+
metricsSystem,
5356
reputationManager,
5457
Collections.emptyList(),
5558
Collections.emptyList(),
@@ -78,11 +81,15 @@ public void subscribeConnect_singleListener() {
7881
@Test
7982
public void shouldCreatePeerTypeMetrics() {
8083
final MetricsSystem metricsSystem = mock(MetricsSystem.class);
81-
final LabelledGauge gauge = mock(LabelledGauge.class);
84+
final LabelledGauge peerClientLabelledGauge = mock(LabelledGauge.class);
85+
final LabelledGauge peerDirectionLabelledGauge = mock(LabelledGauge.class);
8286

8387
when(metricsSystem.createLabelledGauge(
84-
eq(TekuMetricCategory.LIBP2P), eq("connected_peers_current"), any(), any()))
85-
.thenReturn(gauge);
88+
eq(TekuMetricCategory.LIBP2P), eq("connected_peers_current"), any(), eq("client")))
89+
.thenReturn(peerClientLabelledGauge);
90+
when(metricsSystem.createLabelledGauge(
91+
eq(TekuMetricCategory.LIBP2P), eq("peers_direction_current"), any(), eq("direction")))
92+
.thenReturn(peerDirectionLabelledGauge);
8693
new PeerManager(
8794
metricsSystem,
8895
reputationManager,
@@ -91,8 +98,10 @@ public void shouldCreatePeerTypeMetrics() {
9198
peerId -> 0.0);
9299

93100
for (PeerClientType type : PeerClientType.values()) {
94-
verify(gauge).labels(any(), eq(type.getDisplayName()));
101+
verify(peerClientLabelledGauge).labels(any(), eq(type.getDisplayName()));
95102
}
103+
verify(peerDirectionLabelledGauge).labels(any(), eq("inbound"));
104+
verify(peerDirectionLabelledGauge).labels(any(), eq("outbound"));
96105
}
97106

98107
@Test
@@ -163,4 +172,44 @@ public void shouldReportSuccessfulConnectionsToReputationManager() {
163172
verify(reputationManager).reportInitiatedConnectionSuccessful(peerAddress);
164173
verify(reputationManager, never()).reportInitiatedConnectionFailed(peerAddress);
165174
}
175+
176+
@Test
177+
public void testPeerDirectionMetric() {
178+
// Sanity check
179+
validatePeerMetrics(0, 0);
180+
181+
// Add a peer
182+
final Peer outboundPeer1 = createPeerWithDirection(1, true);
183+
peerManager.onConnectedPeer(outboundPeer1);
184+
validatePeerMetrics(1, 0);
185+
186+
// Add another peer
187+
final Peer inboundPeer1 = createPeerWithDirection(2, false);
188+
peerManager.onConnectedPeer(inboundPeer1);
189+
validatePeerMetrics(1, 1);
190+
191+
// Disconnect a peer
192+
peerManager.onDisconnectedPeer(outboundPeer1, Optional.empty(), true);
193+
validatePeerMetrics(0, 1);
194+
195+
// Add another peer
196+
final Peer inboundPeer2 = createPeerWithDirection(3, false);
197+
peerManager.onConnectedPeer(inboundPeer2);
198+
validatePeerMetrics(0, 2);
199+
}
200+
201+
private void validatePeerMetrics(final double expectedOutbound, final double expectedInbound) {
202+
final StubLabelledGauge labelledGauge =
203+
metricsSystem.getLabelledGauge(TekuMetricCategory.LIBP2P, "peers_direction_current");
204+
assertThat(labelledGauge.getValue("inbound")).hasValue(expectedInbound);
205+
assertThat(labelledGauge.getValue("outbound")).hasValue(expectedOutbound);
206+
}
207+
208+
private Peer createPeerWithDirection(final int id, final boolean outbound) {
209+
final Peer peer = mock(Peer.class);
210+
when(peer.getId()).thenReturn(new MockNodeId(id));
211+
when(peer.connectionInitiatedLocally()).thenReturn(outbound);
212+
when(peer.connectionInitiatedRemotely()).thenReturn(!outbound);
213+
return peer;
214+
}
166215
}

0 commit comments

Comments
 (0)