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

app/peerinfo: add nickname field to peerinfo protocol #3428

Merged
merged 12 commits into from
Jan 8, 2025
10 changes: 7 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ type Config struct {
TestnetConfig eth2util.Network
ProcDirectory string
ConsensusProtocol string
Nickname string

TestConfig TestConfig
}
Expand Down Expand Up @@ -257,7 +258,10 @@ func Run(ctx context.Context, conf Config) (err error) {

sender := new(p2p.Sender)

wirePeerInfo(life, tcpNode, peerIDs, cluster.GetInitialMutationHash(), sender, conf.BuilderAPI)
if len(conf.Nickname) > 32 {
return errors.New("nickname can not exceed 32 characters")
}
wirePeerInfo(life, tcpNode, peerIDs, cluster.GetInitialMutationHash(), sender, conf.BuilderAPI, conf.Nickname)

// seenPubkeys channel to send seen public keys from validatorapi to monitoringapi.
seenPubkeys := make(chan core.PubKey)
Expand Down Expand Up @@ -297,9 +301,9 @@ func Run(ctx context.Context, conf Config) (err error) {
}

// wirePeerInfo wires the peerinfo protocol.
func wirePeerInfo(life *lifecycle.Manager, tcpNode host.Host, peers []peer.ID, lockHash []byte, sender *p2p.Sender, builderEnabled bool) {
func wirePeerInfo(life *lifecycle.Manager, tcpNode host.Host, peers []peer.ID, lockHash []byte, sender *p2p.Sender, builderEnabled bool, nickname string) {
gitHash, _ := version.GitCommit()
peerInfo := peerinfo.New(tcpNode, peers, version.Version, lockHash, gitHash, sender.SendReceive, builderEnabled)
peerInfo := peerinfo.New(tcpNode, peers, version.Version, lockHash, gitHash, sender.SendReceive, builderEnabled, nickname)
life.RegisterStart(lifecycle.AsyncAppCtx, lifecycle.StartPeerInfo, lifecycle.HookFuncCtx(peerInfo.Run))
}

Expand Down
5 changes: 4 additions & 1 deletion app/peerinfo/adhoc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ func TestDoOnce(t *testing.T) {
vers := version.Version
lockHash := []byte("123")
gitHash := "abc"
nickname := "johndoe"

// Register the server handler that either
_ = peerinfo.New(server, []peer.ID{server.ID(), client.ID()}, vers, lockHash, gitHash, p2p.SendReceive, true)
_ = peerinfo.New(server, []peer.ID{server.ID(), client.ID()}, vers, lockHash, gitHash, p2p.SendReceive, true, nickname)

info, _, ok, err := peerinfo.DoOnce(context.Background(), client, server.ID())
require.NoError(t, err)
Expand All @@ -35,4 +37,5 @@ func TestDoOnce(t *testing.T) {
require.Equal(t, gitHash, info.GetGitHash())
require.Equal(t, lockHash, info.GetLockHash())
require.True(t, info.GetBuilderApiEnabled())
require.Equal(t, nickname, info.Nickname)
}
8 changes: 8 additions & 0 deletions app/peerinfo/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,12 @@ var (
Name: "builder_api_enabled",
Help: "Set to 1 if builder API is enabled on this peer, else 0 if disabled.",
}, []string{"peer"})

peerNickname = promauto.NewResetGaugeVec(prometheus.GaugeOpts{
Namespace: "app",
Subsystem: "peerinfo",
Name: "nickname",
Help: "Constant gauge with nickname label set to peer's charon nickname.",
ConstLabels: nil,
}, []string{"peer", "nickname"})
)
31 changes: 22 additions & 9 deletions app/peerinfo/peerinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,18 @@ func Protocols() []protocol.ID {
type (
tickerProvider func() (<-chan time.Time, func())
nowFunc func() time.Time
metricSubmitter func(peerID peer.ID, clockOffset time.Duration, version, gitHash string, startTime time.Time, builderAPIEnabled bool)
metricSubmitter func(peerID peer.ID, clockOffset time.Duration, version, gitHash string, startTime time.Time, builderAPIEnabled bool, nickname string)
)

// New returns a new peer info protocol instance.
func New(tcpNode host.Host, peers []peer.ID, version version.SemVer, lockHash []byte, gitHash string,
sendFunc p2p.SendReceiveFunc, builderEnabled bool,
sendFunc p2p.SendReceiveFunc, builderEnabled bool, nickname string,
) *PeerInfo {
// Set own version and git hash and start time metrics.
// Set own version and git hash and nickname and start time and metrics.
DiogoSantoss marked this conversation as resolved.
Show resolved Hide resolved
name := p2p.PeerName(tcpNode.ID())
peerVersion.WithLabelValues(name, version.String()).Set(1)
peerGitHash.WithLabelValues(name, gitHash).Set(1)
peerNickname.WithLabelValues(name, nickname).Set(1)
peerStartGauge.WithLabelValues(name).Set(float64(time.Now().Unix()))

if builderEnabled {
Expand All @@ -68,24 +69,24 @@ func New(tcpNode host.Host, peers []peer.ID, version version.SemVer, lockHash []
}

return newInternal(tcpNode, peers, version, lockHash, gitHash, sendFunc, p2p.RegisterHandler,
tickerProvider, time.Now, newMetricsSubmitter(), builderEnabled)
tickerProvider, time.Now, newMetricsSubmitter(), builderEnabled, nickname)
}

// NewForT returns a new peer info protocol instance for testing only.
func NewForT(_ *testing.T, tcpNode host.Host, peers []peer.ID, version version.SemVer, lockHash []byte, gitHash string,
sendFunc p2p.SendReceiveFunc, registerHandler p2p.RegisterHandlerFunc,
tickerProvider tickerProvider, nowFunc nowFunc, metricSubmitter metricSubmitter,
builderAPIEnabled bool,
builderAPIEnabled bool, nickname string,
) *PeerInfo {
return newInternal(tcpNode, peers, version, lockHash, gitHash, sendFunc, registerHandler,
tickerProvider, nowFunc, metricSubmitter, builderAPIEnabled)
tickerProvider, nowFunc, metricSubmitter, builderAPIEnabled, nickname)
}

// newInternal returns a new instance for New or NewForT.
func newInternal(tcpNode host.Host, peers []peer.ID, version version.SemVer, lockHash []byte, gitHash string,
sendFunc p2p.SendReceiveFunc, registerHandler p2p.RegisterHandlerFunc,
tickerProvider tickerProvider, nowFunc nowFunc, metricSubmitter metricSubmitter,
builderAPIEnabled bool,
builderAPIEnabled bool, nickname string,
) *PeerInfo {
startTime := timestamppb.New(nowFunc())

Expand All @@ -100,10 +101,14 @@ func newInternal(tcpNode host.Host, peers []peer.ID, version version.SemVer, loc
SentAt: timestamppb.New(nowFunc()),
StartedAt: startTime,
BuilderApiEnabled: builderAPIEnabled,
Nickname: nickname,
}, true, nil
},
)

// Maps peers to their nickname
nicknames := map[peer.ID]string{tcpNode.ID(): nickname}

// Create log filters
lockHashFilters := make(map[peer.ID]z.Field)
versionFilters := make(map[peer.ID]z.Field)
Expand All @@ -125,6 +130,7 @@ func newInternal(tcpNode host.Host, peers []peer.ID, version version.SemVer, loc
nowFunc: nowFunc,
lockHashFilters: lockHashFilters,
versionFilters: versionFilters,
nicknames: nicknames,
}
}

Expand All @@ -142,6 +148,7 @@ type PeerInfo struct {
nowFunc func() time.Time
lockHashFilters map[peer.ID]z.Field
versionFilters map[peer.ID]z.Field
nicknames map[peer.ID]string
}

// Run runs the peer info protocol until the context is cancelled.
Expand Down Expand Up @@ -175,6 +182,7 @@ func (p *PeerInfo) sendOnce(ctx context.Context, now time.Time) {
SentAt: timestamppb.New(now),
StartedAt: p.startTime,
BuilderApiEnabled: p.builderAPIEnabled,
Nickname: p.nicknames[p.tcpNode.ID()],
}

go func(peerID peer.ID) {
Expand All @@ -194,6 +202,8 @@ func (p *PeerInfo) sendOnce(ctx context.Context, now time.Time) {

name := p2p.PeerName(peerID)

p.nicknames[p.tcpNode.ID()] = resp.Nickname

// Validator git hash with regex.
if !gitHashMatch.MatchString(resp.GetGitHash()) {
log.Warn(ctx, "Invalid peer git hash", nil, z.Str("peer", name))
Expand Down Expand Up @@ -221,7 +231,7 @@ func (p *PeerInfo) sendOnce(ctx context.Context, now time.Time) {
// Set peer compatibility to true.
peerCompatibleGauge.WithLabelValues(name).Set(1)

p.metricSubmitter(peerID, clockOffset, resp.GetCharonVersion(), resp.GetGitHash(), resp.GetStartedAt().AsTime(), resp.GetBuilderApiEnabled())
p.metricSubmitter(peerID, clockOffset, resp.GetCharonVersion(), resp.GetGitHash(), resp.GetStartedAt().AsTime(), resp.GetBuilderApiEnabled(), resp.GetNickname())

// Log unexpected lock hash
if !bytes.Equal(resp.GetLockHash(), p.lockHash) {
Expand Down Expand Up @@ -269,10 +279,13 @@ func supportedPeerVersion(peerVersion string, supported []version.SemVer) error
// newMetricsSubmitter returns a prometheus metric submitter.
func newMetricsSubmitter() metricSubmitter {
return func(peerID peer.ID, clockOffset time.Duration, version string, gitHash string,
startTime time.Time, builderAPIEnabled bool,
startTime time.Time, builderAPIEnabled bool, nickname string,
) {
peerName := p2p.PeerName(peerID)

peerNickname.Reset(peerName)
peerNickname.WithLabelValues(peerName, nickname).Set(1)

// Limit range of possible values
if clockOffset < -time.Hour {
clockOffset = -time.Hour
Expand Down
3 changes: 2 additions & 1 deletion app/peerinfo/peerinfo_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func TestPeerBuilderAPIEnabledGauge(t *testing.T) {
lockHash := []byte("123")
gitHash := "abc"
peerName := p2p.PeerName(server.ID())
peerNickname := "johndoe"

tests := []struct {
name string
Expand All @@ -84,7 +85,7 @@ func TestPeerBuilderAPIEnabledGauge(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
_ = New(server, []peer.ID{server.ID(), client.ID()}, version.Version, lockHash, gitHash, nil, test.builderEnabled)
_ = New(server, []peer.ID{server.ID(), client.ID()}, version.Version, lockHash, gitHash, nil, test.builderEnabled, peerNickname)

expectedMetric := fmt.Sprintf(`
# HELP app_peerinfo_builder_api_enabled Set to 1 if builder API is enabled on this peer, else 0 if disabled.
Expand Down
10 changes: 6 additions & 4 deletions app/peerinfo/peerinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
func TestPeerInfo(t *testing.T) {
now := time.Now()
const gitCommit = "1234567"
baseNickname := "john-"

// when a major release happens, charon will only be compatible with a single version
versions := version.Supported()
Expand Down Expand Up @@ -49,7 +50,7 @@ func TestPeerInfo(t *testing.T) {
Offset: time.Minute,
},
{
Version: semver(t, "v0.0"),
Version: semver(t, "v1.0"),
Ignore: true,
},
}
Expand Down Expand Up @@ -92,7 +93,7 @@ func TestPeerInfo(t *testing.T) {
tickProvider := func() (<-chan time.Time, func()) {
return nil, func() {}
}
metricSubmitter := func(peer.ID, time.Duration, string, string, time.Time, bool) {
metricSubmitter := func(peer.ID, time.Duration, string, string, time.Time, bool, string) {
panic("unexpected metric submitted")
}

Expand All @@ -107,7 +108,7 @@ func TestPeerInfo(t *testing.T) {

var submittedMutex sync.Mutex
var submitted int
metricSubmitter = func(peerID peer.ID, clockOffset time.Duration, version, gitHash string, startTime time.Time, builderEnabled bool) {
metricSubmitter = func(peerID peer.ID, clockOffset time.Duration, version, gitHash string, startTime time.Time, builderEnabled bool, nickname string) {
for i, tcpNode := range tcpNodes {
if tcpNode.ID() != peerID {
continue
Expand All @@ -117,6 +118,7 @@ func TestPeerInfo(t *testing.T) {
require.Equal(t, gitCommit, gitHash)
require.Equal(t, nowFunc(i)().Unix(), startTime.Unix())
require.True(t, builderEnabled)
require.Equal(t, baseNickname+p2p.PeerName(peerID), nickname)

submittedMutex.Lock()
submitted++
Expand All @@ -132,7 +134,7 @@ func TestPeerInfo(t *testing.T) {
}

peerInfo := peerinfo.NewForT(t, tcpNodes[i], peers, node.Version, node.LockHash, gitCommit, p2p.SendReceive, p2p.RegisterHandler,
tickProvider, nowFunc(i), metricSubmitter, true)
tickProvider, nowFunc(i), metricSubmitter, true, baseNickname+p2p.PeerName(peers[i]))

peerInfos = append(peerInfos, peerInfo)
}
Expand Down
Loading
Loading