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

feat(issue-253): initial metrics implementation #686

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ sequenceDiagram
mev_boost-->>consensus: submitBlindedBlock response
```

# Metrics

Optionally the `-prometheus-port=9000` flag can be passed to expose prometheus metrics on specified port

# Maintainers

- [@metachris](https://github.com/metachris)
Expand Down
7 changes: 7 additions & 0 deletions cli/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var flags = []cli.Flag{
timeoutGetPayloadFlag,
timeoutRegValFlag,
maxRetriesFlag,
prometheusListenAddr,
}

var (
Expand Down Expand Up @@ -83,6 +84,12 @@ var (
Usage: "disables adding the version to every log entry",
Category: LoggingCategory,
}
prometheusListenAddr = &cli.IntFlag{
Name: "prometheus-port",
Sources: cli.EnvVars("PROMETHEUS_PORT"),
Usage: "when set to a valid http port, will export runtime metrics to a prometheus server on that port",
Category: LoggingCategory,
}
// Genesis Flags
customGenesisForkFlag = &cli.StringFlag{
Name: "genesis-fork-version",
Expand Down
21 changes: 21 additions & 0 deletions cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"flag"
"fmt"
"math"
"os"
"strings"
"time"
Expand All @@ -13,6 +14,8 @@ import (
"github.com/flashbots/mev-boost/common"
"github.com/flashbots/mev-boost/config"
"github.com/flashbots/mev-boost/server"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v3"
)
Expand Down Expand Up @@ -69,6 +72,13 @@ func start(_ context.Context, cmd *cli.Command) error {
relays, monitors, minBid, relayCheck = setupRelays(cmd)
listenAddr = cmd.String(addrFlag.Name)
)
prometheusRegistry := prometheus.NewRegistry()
if err := prometheusRegistry.Register(collectors.NewGoCollector()); err != nil {
log.WithError(err).Error("Failed to register metrics for GoCollector")
}
if err := prometheusRegistry.Register(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{})); err != nil {
log.WithError(err).Error("Failed to register ProcessCollector")
}

opts := server.BoostServiceOpts{
Log: log,
Expand All @@ -83,6 +93,8 @@ func start(_ context.Context, cmd *cli.Command) error {
RequestTimeoutGetPayload: time.Duration(cmd.Int(timeoutGetPayloadFlag.Name)) * time.Millisecond,
RequestTimeoutRegVal: time.Duration(cmd.Int(timeoutRegValFlag.Name)) * time.Millisecond,
RequestMaxRetries: int(cmd.Int(maxRetriesFlag.Name)),
PrometheusListenAddr: int(cmd.Int(prometheusListenAddr.Name)),
PrometheusRegistry: prometheusRegistry,
}
service, err := server.NewBoostService(opts)
if err != nil {
Expand All @@ -93,6 +105,15 @@ func start(_ context.Context, cmd *cli.Command) error {
log.Error("no relay passed the health-check!")
}

if opts.PrometheusListenAddr > 0 && opts.PrometheusListenAddr <= math.MaxUint16 {
0xste marked this conversation as resolved.
Show resolved Hide resolved
go func() {
log.Infof("Metric Server Listening on %d", opts.PrometheusListenAddr)
if err := service.StartMetricsServer(); err != nil {
log.WithError(err).Error("metrics server exited with error")
}
}()
}

log.Infof("Listening on %v", listenAddr)
return service.StartHTTPServer()
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/google/uuid v1.6.0
github.com/gorilla/mux v1.8.1
github.com/holiman/uint256 v1.3.1
github.com/prometheus/client_golang v1.16.0
github.com/prysmaticlabs/go-bitfield v0.0.0-20240328144219-a1caa50c3a1e
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
Expand Down Expand Up @@ -44,7 +45,6 @@ require (
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
Expand Down
28 changes: 27 additions & 1 deletion server/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
"github.com/flashbots/mev-boost/server/types"
"github.com/google/uuid"
"github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/sirupsen/logrus"
)

Expand All @@ -37,6 +39,7 @@ var (
errInvalidPubkey = errors.New("invalid pubkey")
errNoSuccessfulRelayResponse = errors.New("no successful relay response")
errServerAlreadyRunning = errors.New("server already running")
errNilPrometheusRegistry = errors.New("nil prometheus registry")
)

var (
Expand Down Expand Up @@ -69,6 +72,8 @@ type BoostServiceOpts struct {
RequestTimeoutGetPayload time.Duration
RequestTimeoutRegVal time.Duration
RequestMaxRetries int
PrometheusListenAddr int
PrometheusRegistry *prometheus.Registry
}

// BoostService - the mev-boost service
Expand All @@ -93,6 +98,9 @@ type BoostService struct {

slotUID *slotUID
slotUIDLock sync.Mutex

prometheusListenAddr int
prometheusRegistry *prometheus.Registry
}

// NewBoostService created a new BoostService
Expand Down Expand Up @@ -130,7 +138,9 @@ func NewBoostService(opts BoostServiceOpts) (*BoostService, error) {
Timeout: opts.RequestTimeoutRegVal,
CheckRedirect: httpClientDisallowRedirects,
},
requestMaxRetries: opts.RequestMaxRetries,
requestMaxRetries: opts.RequestMaxRetries,
prometheusListenAddr: opts.PrometheusListenAddr,
prometheusRegistry: opts.PrometheusRegistry,
}, nil
}

Expand Down Expand Up @@ -194,6 +204,22 @@ func (m *BoostService) StartHTTPServer() error {
return err
}

// StartMetricsServer starts the HTTP server for exporting open-metrics
func (m *BoostService) StartMetricsServer() error {
if m.prometheusRegistry == nil {
return errNilPrometheusRegistry
}
serveMux := http.NewServeMux()
serveMux.Handle("/metrics", promhttp.HandlerFor(m.prometheusRegistry, promhttp.HandlerOpts{
ErrorLog: m.log,
EnableOpenMetrics: true,
}))
return http.ListenAndServe(
fmt.Sprintf(":%d", m.prometheusListenAddr),
serveMux,
)
}

func (m *BoostService) startBidCacheCleanupTask() {
for {
time.Sleep(1 * time.Minute)
Expand Down