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

cmd/relay: enabled new libp2p relay metrics #3040

Merged
merged 6 commits into from
Apr 16, 2024
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
27 changes: 19 additions & 8 deletions cmd/relay/p2p.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,46 @@
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay"
ma "github.com/multiformats/go-multiaddr"
"github.com/prometheus/client_golang/prometheus"

"github.com/obolnetwork/charon/app/errors"
"github.com/obolnetwork/charon/app/log"
"github.com/obolnetwork/charon/app/peerinfo"
"github.com/obolnetwork/charon/app/promauto"
"github.com/obolnetwork/charon/app/z"
"github.com/obolnetwork/charon/p2p"
)

// startP2P returns a started libp2p host or an error.
func startP2P(ctx context.Context, config Config, key *k1.PrivateKey, reporter metrics.Reporter) (host.Host, error) {
func startP2P(ctx context.Context, config Config, key *k1.PrivateKey, reporter metrics.Reporter) (host.Host, *prometheus.Registry, error) {
if len(config.P2PConfig.TCPAddrs) == 0 {
return nil, errors.New("p2p TCP addresses required")
return nil, nil, errors.New("p2p TCP addresses required")

Check warning on line 32 in cmd/relay/p2p.go

View check run for this annotation

Codecov / codecov/patch

cmd/relay/p2p.go#L32

Added line #L32 was not covered by tests
}

if config.LibP2PLogLevel != "" {
if err := libp2plog.SetLogLevel("relay", config.LibP2PLogLevel); err != nil {
return nil, errors.Wrap(err, "set relay log level")
return nil, nil, errors.Wrap(err, "set relay log level")

Check warning on line 37 in cmd/relay/p2p.go

View check run for this annotation

Codecov / codecov/patch

cmd/relay/p2p.go#L37

Added line #L37 was not covered by tests
}
if err := libp2plog.SetLogLevel("rcmgr", config.LibP2PLogLevel); err != nil {
return nil, errors.Wrap(err, "set rcmgr log level")
return nil, nil, errors.Wrap(err, "set rcmgr log level")

Check warning on line 40 in cmd/relay/p2p.go

View check run for this annotation

Codecov / codecov/patch

cmd/relay/p2p.go#L40

Added line #L40 was not covered by tests
}
}

tcpNode, err := p2p.NewTCPNode(ctx, config.P2PConfig, key, p2p.NewOpenGater(), config.FilterPrivAddrs,
libp2p.ResourceManager(new(network.NullResourceManager)), libp2p.BandwidthReporter(reporter))
if err != nil {
return nil, errors.Wrap(err, "new tcp node")
return nil, nil, errors.Wrap(err, "new tcp node")

Check warning on line 47 in cmd/relay/p2p.go

View check run for this annotation

Codecov / codecov/patch

cmd/relay/p2p.go#L47

Added line #L47 was not covered by tests
}

p2p.RegisterConnectionLogger(ctx, tcpNode, nil)

labels := map[string]string{"relay_peer": p2p.PeerName(tcpNode.ID())}
log.SetLokiLabels(labels)
promRegistry, err := promauto.NewRegistry(labels)
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't it a bit weird creating a prometheus registry in startP2P function? Does it make sense to create it outside of it (in cmd/relay/relay.go:Run afaict) and pass it as an argument, similarly to how the reporter is passed (another monitoring structure)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem here is in the dependency on labels which we can populate only after we started a tcpNode.
I would rework it in a different way to remove this dependency, but would be a drastic change, not for the scope of this PR for sure.

if err != nil {
return nil, nil, errors.Wrap(err, "create prometheus registry")
}

Check warning on line 57 in cmd/relay/p2p.go

View check run for this annotation

Codecov / codecov/patch

cmd/relay/p2p.go#L56-L57

Added lines #L56 - L57 were not covered by tests

relayResources := relay.DefaultResources()
relayResources.Limit.Data = 32 * (1 << 20) // 32MB
relayResources.Limit.Duration = time.Hour
Expand All @@ -56,9 +65,11 @@
relayResources.MaxReservations = config.MaxConns
relayResources.MaxCircuits = config.MaxResPerPeer

relayService, err := relay.New(tcpNode, relay.WithResources(relayResources))
// This enables relay metrics: https://github.com/libp2p/go-libp2p/blob/master/p2p/protocol/circuitv2/relay/metrics.go
mt := relay.NewMetricsTracer(relay.WithRegisterer(promRegistry))
relayService, err := relay.New(tcpNode, relay.WithResources(relayResources), relay.WithMetricsTracer(mt))
if err != nil {
return nil, errors.Wrap(err, "new relay service")
return nil, nil, errors.Wrap(err, "new relay service")

Check warning on line 72 in cmd/relay/p2p.go

View check run for this annotation

Codecov / codecov/patch

cmd/relay/p2p.go#L72

Added line #L72 was not covered by tests
}

go func() {
Expand All @@ -67,7 +78,7 @@
_ = relayService.Close()
}()

return tcpNode, nil
return tcpNode, promRegistry, nil
}

const unknownCluster = "unknown"
Expand Down
10 changes: 1 addition & 9 deletions cmd/relay/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (

"github.com/obolnetwork/charon/app/errors"
"github.com/obolnetwork/charon/app/log"
"github.com/obolnetwork/charon/app/promauto"
"github.com/obolnetwork/charon/app/version"
"github.com/obolnetwork/charon/app/z"
"github.com/obolnetwork/charon/eth2util/enr"
Expand Down Expand Up @@ -72,20 +71,13 @@ func Run(ctx context.Context, config Config) error {
bwTuples := make(chan bwTuple)
counter := newBandwidthCounter(ctx, bwTuples)

tcpNode, err := startP2P(ctx, config, key, counter)
tcpNode, promRegistry, err := startP2P(ctx, config, key, counter)
if err != nil {
return err
}

go monitorConnections(ctx, tcpNode, bwTuples)

labels := map[string]string{"relay_peer": p2p.PeerName(tcpNode.ID())}
log.SetLokiLabels(labels)
promRegistry, err := promauto.NewRegistry(labels)
if err != nil {
return err
}

// Start serving HTTP: ENR and monitoring.
serverErr := make(chan error, 3) // Buffer for 3 servers.
go func() {
Expand Down
42 changes: 42 additions & 0 deletions cmd/relay/relay_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"io"
"net/http"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -224,3 +225,44 @@ func testServeAddrs(t *testing.T, p2pConfig p2p.Config, path string, asserter fu

require.NoError(t, eg.Wait())
}

func TestRelayMetricsExported(t *testing.T) {
temp := t.TempDir()

config := Config{
DataDir: temp,
LogConfig: log.DefaultConfig(),
P2PConfig: p2p.Config{TCPAddrs: []string{testutil.AvailableAddr(t).String()}},
HTTPAddr: testutil.AvailableAddr(t).String(),
MonitoringAddr: testutil.AvailableAddr(t).String(),
}

_, err := p2p.NewSavedPrivKey(temp)
require.NoError(t, err)

ctx, cancel := context.WithCancel(context.Background())

go func() {
err := Run(ctx, config)
testutil.SkipIfBindErr(t, err)
assert.NoError(t, err)
}()

fetchMetrics := func() string {
resp, err := http.Get(fmt.Sprintf("http://%s/metrics", config.MonitoringAddr))
if err == nil {
body, err := io.ReadAll(resp.Body)
if err == nil {
return string(body)
}
}

return ""
}

require.Eventually(t, func() bool {
return strings.Contains(fetchMetrics(), "libp2p_relaysvc_")
}, 10*time.Second, time.Second, "waiting for relay service to start")

cancel()
}
Loading