Skip to content

Commit

Permalink
Merge pull request #5 from samcm/feat/general-metrics
Browse files Browse the repository at this point in the history
feat(network): Add General/Network level metrics
  • Loading branch information
samcm committed May 9, 2022
2 parents 8600cb0 + a2a2cc5 commit 1cafe3c
Show file tree
Hide file tree
Showing 10 changed files with 346 additions and 39 deletions.
74 changes: 74 additions & 0 deletions pkg/exporter/consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package consensus
import (
"context"
"errors"
"strings"

eth2client "github.com/attestantio/go-eth2-client"
"github.com/attestantio/go-eth2-client/http"
"github.com/rs/zerolog"
"github.com/sirupsen/logrus"
"github.com/spf13/cast"
)

type Node interface {
Expand All @@ -18,6 +20,8 @@ type Node interface {
SyncStatus(ctx context.Context) (*SyncStatus, error)
NodeVersion(ctx context.Context) (string, error)
Spec(ctx context.Context) (map[string]interface{}, error)
BlockNumbers(ctx context.Context) (*BlockchainSlots, error)
Forks(ctx context.Context) ([]Fork, error)
}

type node struct {
Expand Down Expand Up @@ -138,3 +142,73 @@ func (c *node) Spec(ctx context.Context) (map[string]interface{}, error) {

return spec, nil
}

func (c *node) BlockNumbers(ctx context.Context) (*BlockchainSlots, error) {
provider, isProvider := c.client.(eth2client.BeaconBlockHeadersProvider)
if !isProvider {
c.refreshClient(ctx)
return nil, errors.New("client does not implement eth2client.BeaconBlockHeadersProvider")
}

errs := []error{}

slots := &BlockchainSlots{}

head, err := provider.BeaconBlockHeader(ctx, "head")
if err != nil {
errs = append(errs, err)
} else {
slots.Head = uint64(head.Header.Message.Slot)
}

genesis, err := provider.BeaconBlockHeader(ctx, "genesis")
if err != nil {
errs = append(errs, err)
} else {
slots.Genesis = uint64(genesis.Header.Message.Slot)
}

finalized, err := provider.BeaconBlockHeader(ctx, "finalized")
if err != nil {
errs = append(errs, err)
} else {
slots.Finalized = uint64(finalized.Header.Message.Slot)
}

if len(errs) > 0 {
errMsg := ""
for _, e := range errs {
errMsg += e.Error() + ", "
}

return slots, errors.New(errMsg)
}

c.metrics.ObserveBlockchainSlots(*slots)

return slots, nil
}

func (c *node) Forks(ctx context.Context) ([]Fork, error) {
// Extract the forks out of the spec.
spec, err := c.Spec(ctx)
if err != nil {
return nil, err
}

var forks []Fork
for k, v := range spec {
if strings.Contains(k, "_FORK_EPOCH") {
fork := Fork{
Name: strings.Replace(k, "_FORK_EPOCH", "", -1),
Epoch: cast.ToUint64(v),
}

forks = append(forks, fork)
}
}

c.metrics.ObserveForks(forks)

return forks, nil
}
30 changes: 30 additions & 0 deletions pkg/exporter/consensus/jobs/fork.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package jobs

import (
"github.com/prometheus/client_golang/prometheus"
)

type ForkMetrics struct {
Forks prometheus.GaugeVec
}

func NewForkMetrics(namespace string, constLabels map[string]string) ForkMetrics {
namespace = namespace + "_fork"
return ForkMetrics{
Forks: *prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "epoch",
Help: "The epoch for the fork.",
ConstLabels: constLabels,
},
[]string{
"fork",
},
),
}
}

func (f *ForkMetrics) ObserveFork(name string, epoch uint64) {
f.Forks.WithLabelValues(name).Set(float64(epoch))
}
58 changes: 58 additions & 0 deletions pkg/exporter/consensus/jobs/general.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package jobs

import (
"github.com/prometheus/client_golang/prometheus"
)

type GeneralMetrics struct {
Slots prometheus.GaugeVec
NodeVersion prometheus.GaugeVec
NetworkdID prometheus.Gauge
}

func NewGeneralMetrics(namespace string, constLabels map[string]string) GeneralMetrics {
return GeneralMetrics{
Slots: *prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "slot_number",
Help: "The slot number of the beacon chain.",
ConstLabels: constLabels,
},
[]string{
"identifier",
},
),
NodeVersion: *prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "node_version",
Help: "The version of the running beacon node.",
ConstLabels: constLabels,
},
[]string{
"version",
},
),
NetworkdID: prometheus.NewGauge(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "network_id",
Help: "The network id of the node.",
ConstLabels: constLabels,
},
),
}
}

func (g *GeneralMetrics) ObserveSlot(identifier string, slot uint64) {
g.Slots.WithLabelValues(identifier).Set(float64(slot))
}

func (g *GeneralMetrics) ObserveNodeVersion(version string) {
g.NodeVersion.WithLabelValues(version).Set(1)
}

func (g *GeneralMetrics) ObserveNetworkID(networkID uint64) {
g.NetworkdID.Set(float64(networkID))
}
45 changes: 27 additions & 18 deletions pkg/exporter/consensus/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ type Metrics interface {
ObserveSyncStatus(status SyncStatus)
ObserveNodeVersion(version string)
ObserveSpec(spec map[string]interface{})
ObserveBlockchainSlots(blocks BlockchainSlots)
ObserveForks(forks []Fork)
}

type metrics struct {
nodeVersion *prometheus.GaugeVec

syncMetrics jobs.SyncStatus
specMetrics jobs.Spec
generalMetrics jobs.GeneralMetrics
syncMetrics jobs.SyncStatus
specMetrics jobs.Spec
forkMetrics jobs.ForkMetrics
}

func NewMetrics(nodeName, namespace string) Metrics {
Expand All @@ -24,28 +28,20 @@ func NewMetrics(nodeName, namespace string) Metrics {
constLabels["node_name"] = nodeName

m := &metrics{

nodeVersion: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "node_version",
Help: "The version of the running beacon node.",
ConstLabels: constLabels,
},
[]string{
"version",
},
),
specMetrics: jobs.NewSpec(namespace, constLabels),
syncMetrics: jobs.NewSyncStatus(namespace, constLabels),
generalMetrics: jobs.NewGeneralMetrics(namespace, constLabels),
specMetrics: jobs.NewSpec(namespace, constLabels),
syncMetrics: jobs.NewSyncStatus(namespace, constLabels),
forkMetrics: jobs.NewForkMetrics(namespace, constLabels),
}

prometheus.MustRegister(m.generalMetrics.Slots)
prometheus.MustRegister(m.generalMetrics.NodeVersion)

prometheus.MustRegister(m.syncMetrics.Percentage)
prometheus.MustRegister(m.syncMetrics.EstimatedHighestSlot)
prometheus.MustRegister(m.syncMetrics.HeadSlot)
prometheus.MustRegister(m.syncMetrics.Distance)
prometheus.MustRegister(m.syncMetrics.IsSyncing)
prometheus.MustRegister(m.nodeVersion)

prometheus.MustRegister(m.specMetrics.SafeSlotsToUpdateJustified)
prometheus.MustRegister(m.specMetrics.DepositChainID)
Expand All @@ -71,11 +67,12 @@ func NewMetrics(nodeName, namespace string) Metrics {
prometheus.MustRegister(m.specMetrics.SlotsPerEpoch)
prometheus.MustRegister(m.specMetrics.PresetBase)

prometheus.MustRegister(m.forkMetrics.Forks)
return m
}

func (m *metrics) ObserveNodeVersion(version string) {
m.nodeVersion.WithLabelValues(version).Set(float64(1))
m.generalMetrics.ObserveNodeVersion(version)
}

func (m *metrics) ObserveSpec(spec map[string]interface{}) {
Expand All @@ -89,3 +86,15 @@ func (m *metrics) ObserveSyncStatus(status SyncStatus) {
m.syncMetrics.ObserveSyncIsSyncing(status.IsSyncing)
m.syncMetrics.ObserveSyncPercentage(status.Percent())
}

func (m *metrics) ObserveBlockchainSlots(blocks BlockchainSlots) {
m.generalMetrics.ObserveSlot("head", blocks.Head)
m.generalMetrics.ObserveSlot("genesis", blocks.Genesis)
m.generalMetrics.ObserveSlot("finalized", blocks.Finalized)
}

func (m *metrics) ObserveForks(forks []Fork) {
for _, fork := range forks {
m.forkMetrics.ObserveFork(fork.Name, uint64(fork.Epoch))
}
}
11 changes: 11 additions & 0 deletions pkg/exporter/consensus/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,14 @@ func (c *SyncStatus) Percent() float64 {

return (float64(c.HeadSlot) / float64(c.EstimatedHeadSlot) * 100)
}

type BlockchainSlots struct {
Head uint64
Genesis uint64
Finalized uint64
}

type Fork struct {
Name string
Epoch uint64
}
36 changes: 36 additions & 0 deletions pkg/exporter/execution/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ type Node interface {
Bootstrap(ctx context.Context) error
SyncStatus(ctx context.Context) (*SyncStatus, error)
NetworkID(ctx context.Context) (int64, error)
ChainID(ctx context.Context) (int64, error)
MostRecentBlockNumber(ctx context.Context) (uint64, error)
EstimatedGasPrice(ctx context.Context) (float64, error)
}

type node struct {
Expand Down Expand Up @@ -91,3 +94,36 @@ func (e *node) NetworkID(ctx context.Context) (int64, error) {

return id.Int64(), nil
}

func (e *node) MostRecentBlockNumber(ctx context.Context) (uint64, error) {
blockNumber, err := e.client.BlockNumber(ctx)
if err != nil {
return 0, err
}

e.metrics.ObserveMostRecentBlock(int64(blockNumber))

return blockNumber, nil
}

func (e *node) EstimatedGasPrice(ctx context.Context) (float64, error) {
gasPrice, err := e.client.SuggestGasPrice(ctx)
if err != nil {
return 0, err
}

e.metrics.ObserveGasPrice(float64(gasPrice.Int64()))

return float64(gasPrice.Int64()), nil
}

func (e *node) ChainID(ctx context.Context) (int64, error) {
id, err := e.client.ChainID(ctx)
if err != nil {
return 0, err
}

e.metrics.ObserveChainID(id.Int64())

return id.Int64(), nil
}
Loading

0 comments on commit 1cafe3c

Please sign in to comment.