Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

swarm: add early muxer selection to swarm metrics #2119

Merged
merged 2 commits into from
Feb 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
Since the last release, we've added additional metrics to different components.
Metrics were added to:
* [AutoNat](https://github.com/libp2p/go-libp2p/pull/2086): Current Reachability Status and Confidence, Client and Server DialResponses, Server DialRejections. The dashboard is [available here](https://github.com/libp2p/go-libp2p/blob/master/dashboards/autonat/autonat.json).
* Swarm:
- [Early Muxer Selection](https://github.com/libp2p/go-libp2p/pull/2119): Added early_muxer label indicating whether a connection was established using early muxer selection.
- [IP Version](https://github.com/libp2p/go-libp2p/pull/2114): Added ip_version label to connection metrics

## 🐞 Bugfixes <!-- omit in toc -->

Expand Down
2 changes: 2 additions & 0 deletions core/network/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ type ConnectionState struct {
Security protocol.ID
// the transport used on this connection. For example: tcp
Transport string
// indicates whether StreamMultiplexer was selected using inlined muxer negotiation
UsedEarlyMuxerNegotiation bool
}

// ConnSecurity is the interface that one can mix into a connection interface to
Expand Down
107 changes: 107 additions & 0 deletions dashboards/swarm/swarm.json
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,113 @@
"title": "Connection Duration",
"type": "timeseries"
},
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latency graphs are not very useful, at least on my node. Not really sure how to fix it though.

Would it make more sense to just use a pie chart here, and show the fraction of early muxer negotiation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made it a pie chart

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"description": "",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
}
},
"mappings": []
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "regular"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "yellow",
"mode": "fixed"
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "early muxer"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "green",
"mode": "fixed"
}
}
]
}
]
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 25
},
"id": 36,
"options": {
"legend": {
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"pieType": "pie",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "sum(libp2p_swarm_connections_opened_total{transport=\"tcp\",early_muxer=\"true\"} - libp2p_swarm_connections_closed_total{transport=\"tcp\",early_muxer=\"true\"})",
"legendFormat": "early muxer",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "sum(libp2p_swarm_connections_opened_total{transport=\"tcp\",early_muxer=\"false\"} - libp2p_swarm_connections_closed_total{transport=\"tcp\",early_muxer=\"false\"})",
"hide": false,
"legendFormat": "regular",
"range": true,
"refId": "B"
}
],
"title": "Active Connections: Early Muxer Negotiation",
"type": "piechart"
},
{
"collapsed": false,
"gridPos": {
Expand Down
14 changes: 10 additions & 4 deletions p2p/net/swarm/swarm_metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ var (
Name: "connections_opened_total",
Help: "Connections Opened",
},
[]string{"dir", "transport", "security", "muxer", "ip_version"},
[]string{"dir", "transport", "security", "muxer", "early_muxer", "ip_version"},
)
keyTypes = prometheus.NewCounterVec(
prometheus.CounterOpts{
Expand All @@ -42,7 +42,7 @@ var (
Name: "connections_closed_total",
Help: "Connections Closed",
},
[]string{"dir", "transport", "security", "muxer", "ip_version"},
[]string{"dir", "transport", "security", "muxer", "early_muxer", "ip_version"},
)
dialError = prometheus.NewCounterVec(
prometheus.CounterOpts{
Expand All @@ -59,7 +59,7 @@ var (
Help: "Duration of a Connection",
Buckets: prometheus.ExponentialBuckets(1.0/16, 2, 25), // up to 24 days
},
[]string{"dir", "transport", "security", "muxer", "ip_version"},
[]string{"dir", "transport", "security", "muxer", "early_muxer", "ip_version"},
)
connHandshakeLatency = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Expand All @@ -68,7 +68,7 @@ var (
Help: "Duration of the libp2p Handshake",
Buckets: prometheus.ExponentialBuckets(0.001, 1.3, 35),
},
[]string{"transport", "security", "muxer", "ip_version"},
[]string{"transport", "security", "muxer", "early_muxer", "ip_version"},
)
)

Expand Down Expand Up @@ -105,6 +105,12 @@ func appendConnectionState(tags []string, cs network.ConnectionState) []string {
// For example, QUIC doesn't set security nor muxer.
tags = append(tags, string(cs.Security))
tags = append(tags, string(cs.StreamMultiplexer))

earlyMuxer := "false"
if cs.UsedEarlyMuxerNegotiation {
earlyMuxer = "true"
}
tags = append(tags, earlyMuxer)
return tags
}

Expand Down
4 changes: 2 additions & 2 deletions p2p/net/swarm/swarm_metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ func TestMetricsNoAllocNoCover(t *testing.T) {
mt := NewMetricsTracer()

connections := []network.ConnectionState{
{StreamMultiplexer: "yamux", Security: "tls", Transport: "tcp"},
{StreamMultiplexer: "yamux", Security: "noise", Transport: "tcp"},
{StreamMultiplexer: "yamux", Security: "tls", Transport: "tcp", UsedEarlyMuxerNegotiation: true},
{StreamMultiplexer: "yamux", Security: "noise", Transport: "tcp", UsedEarlyMuxerNegotiation: false},
{StreamMultiplexer: "", Security: "", Transport: "quic"},
{StreamMultiplexer: "mplex", Security: "noise", Transport: "tcp"},
}
Expand Down
12 changes: 7 additions & 5 deletions p2p/net/upgrader/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ type transportConn struct {
scope network.ConnManagementScope
stat network.ConnStats

muxer protocol.ID
security protocol.ID
muxer protocol.ID
security protocol.ID
usedEarlyMuxerNegotiation bool
}

var _ transport.CapableConn = &transportConn{}
Expand Down Expand Up @@ -56,8 +57,9 @@ func (t *transportConn) Close() error {

func (t *transportConn) ConnState() network.ConnectionState {
return network.ConnectionState{
StreamMultiplexer: t.muxer,
Security: t.security,
Transport: "tcp",
StreamMultiplexer: t.muxer,
Security: t.security,
Transport: "tcp",
UsedEarlyMuxerNegotiation: t.usedEarlyMuxerNegotiation,
}
}
17 changes: 9 additions & 8 deletions p2p/net/upgrader/upgrader.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,15 @@ func (u *upgrader) upgrade(ctx context.Context, t transport.Transport, maconn ma
}

tc := &transportConn{
MuxedConn: smconn,
ConnMultiaddrs: maconn,
ConnSecurity: sconn,
transport: t,
stat: stat,
scope: connScope,
muxer: muxer,
security: security,
MuxedConn: smconn,
ConnMultiaddrs: maconn,
ConnSecurity: sconn,
transport: t,
stat: stat,
scope: connScope,
muxer: muxer,
security: security,
usedEarlyMuxerNegotiation: sconn.ConnState().UsedEarlyMuxerNegotiation,
}
return tc, nil
}
Expand Down
1 change: 1 addition & 0 deletions p2p/security/noise/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ func (s *secureSession) Close() error {
func SessionWithConnState(s *secureSession, muxer protocol.ID) *secureSession {
if s != nil {
s.connectionState.StreamMultiplexer = muxer
s.connectionState.UsedEarlyMuxerNegotiation = muxer != ""
}
return s
}
2 changes: 2 additions & 0 deletions p2p/security/noise/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,9 @@ func TestHandshakeWithTransportEarlyData(t *testing.T) {
defer respConn.Close()

require.Equal(t, expectedProto, initConn.connectionState.StreamMultiplexer)
require.Equal(t, expectedProto != "", initConn.connectionState.UsedEarlyMuxerNegotiation)
require.Equal(t, expectedProto, respConn.connectionState.StreamMultiplexer)
require.Equal(t, expectedProto != "", respConn.connectionState.UsedEarlyMuxerNegotiation)

initData := []byte("Test data for noise transport")
_, err := initConn.Write(initData)
Expand Down
15 changes: 9 additions & 6 deletions p2p/security/tls/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,15 @@ func (t *Transport) setupConn(tlsConn *tls.Conn, remotePubKey ci.PubKey) (sec.Se
}

return &conn{
Conn: tlsConn,
localPeer: t.localPeer,
privKey: t.privKey,
remotePeer: remotePeerID,
remotePubKey: remotePubKey,
connectionState: network.ConnectionState{StreamMultiplexer: protocol.ID(nextProto)},
Conn: tlsConn,
localPeer: t.localPeer,
privKey: t.privKey,
remotePeer: remotePeerID,
remotePubKey: remotePubKey,
connectionState: network.ConnectionState{
StreamMultiplexer: protocol.ID(nextProto),
UsedEarlyMuxerNegotiation: nextProto != "",
},
}, nil
}

Expand Down
1 change: 1 addition & 0 deletions p2p/security/tls/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ func TestHandshakeWithNextProtoSucceeds(t *testing.T) {
require.True(t, clientConn.RemotePublicKey().Equals(serverKey.GetPublic()), "server public key mismatch")
require.True(t, serverConn.RemotePublicKey().Equals(clientKey.GetPublic()), "client public key mismatch")
require.Equal(t, clientConn.ConnState().StreamMultiplexer, expectedMuxer)
require.Equal(t, clientConn.ConnState().UsedEarlyMuxerNegotiation, expectedMuxer != "")
// exchange some data
_, err = serverConn.Write([]byte("foobar"))
require.NoError(t, err)
Expand Down