Skip to content

Commit

Permalink
op-challenger: Add basic metrics & pprof setup
Browse files Browse the repository at this point in the history
This adds metrics & pprof to the op-challenger. I had to add a default config
option to the metrics & pprof in order to make the tests work (because it
verifies that the result of the CLI parsing is as expected when compared to
an config struct which is constructed).

This also had to modify how the challenger stores its version information
because we include that information in the metrics when we record that it is
up. Unlike the proposer & batcher, the challenger has a different initialization
flow which does not easily make the version information accessible.
  • Loading branch information
trianglesphere committed Aug 18, 2023
1 parent 9d9a79a commit 532d8ce
Show file tree
Hide file tree
Showing 12 changed files with 204 additions and 12 deletions.
2 changes: 1 addition & 1 deletion op-batcher/batcher/batch_submitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func Main(version string, cliCtx *cli.Context) error {
l.Info("starting metrics server", "addr", metricsCfg.ListenAddr, "port", metricsCfg.ListenPort)
go func() {
if err := m.Serve(ctx, metricsCfg.ListenAddr, metricsCfg.ListenPort); err != nil {
l.Error("error starting metrics server", err)
l.Error("error starting metrics server", "err", err)
}
}()
m.StartBalanceMetrics(ctx, l, batchSubmitter.L1Client, batchSubmitter.TxManager.From())
Expand Down
16 changes: 14 additions & 2 deletions op-challenger/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"

"github.com/ethereum-optimism/optimism/op-node/chaincfg"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
oppprof "github.com/ethereum-optimism/optimism/op-service/pprof"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
)
Expand Down Expand Up @@ -105,7 +107,9 @@ type Config struct {
CannonL2 string // L2 RPC Url
CannonSnapshotFreq uint // Frequency of snapshots to create when executing cannon (in VM instructions)

TxMgrConfig txmgr.CLIConfig
TxMgrConfig txmgr.CLIConfig
MetricsConfig opmetrics.CLIConfig
PprofConfig oppprof.CLIConfig
}

func NewConfig(
Expand All @@ -122,7 +126,9 @@ func NewConfig(

TraceType: traceType,

TxMgrConfig: txmgr.NewCLIConfig(l1EthRpc),
TxMgrConfig: txmgr.NewCLIConfig(l1EthRpc),
MetricsConfig: opmetrics.DefaultCLIConfig(),
PprofConfig: oppprof.DefaultCLIConfig(),

CannonSnapshotFreq: DefaultCannonSnapshotFreq,
}
Expand Down Expand Up @@ -182,5 +188,11 @@ func (c Config) Check() error {
if err := c.TxMgrConfig.Check(); err != nil {
return err
}
if err := c.MetricsConfig.Check(); err != nil {
return err
}
if err := c.PprofConfig.Check(); err != nil {
return err
}
return nil
}
48 changes: 44 additions & 4 deletions op-challenger/fault/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/fault/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/fault/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-challenger/version"
"github.com/ethereum-optimism/optimism/op-service/client"
oppprof "github.com/ethereum-optimism/optimism/op-service/pprof"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
Expand All @@ -30,11 +32,13 @@ type service struct {
agreeWithProposedOutput bool
caller *FaultCaller
logger log.Logger
metrics metrics.Metricer
}

// NewService creates a new Service.
func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*service, error) {
txMgr, err := txmgr.NewSimpleTxManager("challenger", logger, &metrics.NoopTxMetrics{}, cfg.TxMgrConfig)
m := metrics.NewMetrics()
txMgr, err := txmgr.NewSimpleTxManager("challenger", logger, &m.TxMetrics, cfg.TxMgrConfig)
if err != nil {
return nil, fmt.Errorf("failed to create the transaction manager: %w", err)
}
Expand All @@ -44,6 +48,27 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se
return nil, fmt.Errorf("failed to dial L1: %w", err)
}

pprofConfig := cfg.PprofConfig
if pprofConfig.Enabled {
logger.Info("starting pprof", "addr", pprofConfig.ListenAddr, "port", pprofConfig.ListenPort)
go func() {
if err := oppprof.ListenAndServe(ctx, pprofConfig.ListenAddr, pprofConfig.ListenPort); err != nil {
logger.Error("error starting pprof", "err", err)
}
}()
}

metricsCfg := cfg.MetricsConfig
if metricsCfg.Enabled {
logger.Info("starting metrics server", "addr", metricsCfg.ListenAddr, "port", metricsCfg.ListenPort)
go func() {
if err := m.Serve(ctx, metricsCfg.ListenAddr, metricsCfg.ListenPort); err != nil {
logger.Error("error starting metrics server", "err", err)
}
}()
m.StartBalanceMetrics(ctx, logger, client, txMgr.From())
}

contract, err := bindings.NewFaultDisputeGameCaller(cfg.GameAddress, client)
if err != nil {
return nil, fmt.Errorf("failed to bind the fault dispute game contract: %w", err)
Expand Down Expand Up @@ -76,11 +101,22 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se
return nil, fmt.Errorf("unsupported trace type: %v", cfg.TraceType)
}

return newTypedService(ctx, logger, cfg, loader, gameDepth, client, trace, updater, txMgr)
return newTypedService(ctx, logger, cfg, loader, gameDepth, client, trace, updater, txMgr, m)
}

// newTypedService creates a new Service from a provided trace provider.
func newTypedService(ctx context.Context, logger log.Logger, cfg *config.Config, loader Loader, gameDepth uint64, client *ethclient.Client, provider types.TraceProvider, updater types.OracleUpdater, txMgr txmgr.TxManager) (*service, error) {
func newTypedService(ctx context.Context,
logger log.Logger,
cfg *config.Config,
loader Loader,
gameDepth uint64,
client *ethclient.Client,
provider types.TraceProvider,
updater types.OracleUpdater,
txMgr txmgr.TxManager,
metrics metrics.Metricer,
) (*service, error) {

if err := ValidateAbsolutePrestate(ctx, provider, loader); err != nil {
return nil, fmt.Errorf("failed to validate absolute prestate: %w", err)
}
Expand All @@ -96,11 +132,15 @@ func newTypedService(ctx context.Context, logger log.Logger, cfg *config.Config,
return nil, fmt.Errorf("failed to bind the fault contract: %w", err)
}

metrics.RecordInfo(version.SimpleWithMeta)
metrics.RecordUp()

return &service{
agent: NewAgent(loader, int(gameDepth), provider, responder, updater, cfg.AgreeWithProposedOutput, gameLogger),
agreeWithProposedOutput: cfg.AgreeWithProposedOutput,
caller: caller,
logger: gameLogger,
metrics: metrics,
}, nil
}

Expand Down
8 changes: 8 additions & 0 deletions op-challenger/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
opservice "github.com/ethereum-optimism/optimism/op-service"
openum "github.com/ethereum-optimism/optimism/op-service/enum"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
oppprof "github.com/ethereum-optimism/optimism/op-service/pprof"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"

Expand Down Expand Up @@ -134,6 +136,8 @@ var optionalFlags = []cli.Flag{
func init() {
optionalFlags = append(optionalFlags, oplog.CLIFlags(envVarPrefix)...)
optionalFlags = append(optionalFlags, txmgr.CLIFlags(envVarPrefix)...)
optionalFlags = append(optionalFlags, opmetrics.CLIFlags(envVarPrefix)...)
optionalFlags = append(optionalFlags, oppprof.CLIFlags(envVarPrefix)...)

Flags = append(requiredFlags, optionalFlags...)
}
Expand Down Expand Up @@ -201,6 +205,8 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
}

txMgrConfig := txmgr.ReadCLIConfig(ctx)
metricsConfig := opmetrics.ReadCLIConfig(ctx)
pprofConfig := oppprof.ReadCLIConfig(ctx)

traceTypeFlag := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name)))

Expand All @@ -222,5 +228,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
CannonSnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name),
AgreeWithProposedOutput: ctx.Bool(AgreeWithProposedOutputFlag.Name),
TxMgrConfig: txMgrConfig,
MetricsConfig: metricsConfig,
PprofConfig: pprofConfig,
}, nil
}
86 changes: 86 additions & 0 deletions op-challenger/metrics/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package metrics

import (
"context"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/prometheus/client_golang/prometheus"

opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
txmetrics "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
)

const Namespace = "op_challenger"

type Metricer interface {
RecordInfo(version string)
RecordUp()

// Record Tx metrics
txmetrics.TxMetricer
}

type Metrics struct {
ns string
registry *prometheus.Registry
factory opmetrics.Factory

txmetrics.TxMetrics

info prometheus.GaugeVec
up prometheus.Gauge
}

var _ Metricer = (*Metrics)(nil)

func NewMetrics() *Metrics {
registry := opmetrics.NewRegistry()
factory := opmetrics.With(registry)

return &Metrics{
ns: Namespace,
registry: registry,
factory: factory,

TxMetrics: txmetrics.MakeTxMetrics(Namespace, factory),

info: *factory.NewGaugeVec(prometheus.GaugeOpts{
Namespace: Namespace,
Name: "info",
Help: "Pseudo-metric tracking version and config info",
}, []string{
"version",
}),
up: factory.NewGauge(prometheus.GaugeOpts{
Namespace: Namespace,
Name: "up",
Help: "1 if the op-challenger has finished starting up",
}),
}
}

func (m *Metrics) Serve(ctx context.Context, host string, port int) error {
return opmetrics.ListenAndServe(ctx, m.registry, host, port)
}

func (m *Metrics) StartBalanceMetrics(ctx context.Context, l log.Logger, client *ethclient.Client, account common.Address) {
opmetrics.LaunchBalanceMetrics(ctx, l, m.registry, m.ns, client, account)
}

// RecordInfo sets a pseudo-metric that contains versioning and
// config info for the op-proposer.
func (m *Metrics) RecordInfo(version string) {
m.info.WithLabelValues(version).Set(1)
}

// RecordUp sets the up metric to 1.
func (m *Metrics) RecordUp() {
prometheus.MustRegister()
m.up.Set(1)
}

func (m *Metrics) Document() []opmetrics.DocumentedMetric {
return m.factory.Document()
}
14 changes: 14 additions & 0 deletions op-challenger/metrics/noop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package metrics

import (
txmetrics "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
)

type noopMetrics struct {
txmetrics.NoopTxMetrics
}

var NoopMetrics Metricer = new(noopMetrics)

func (*noopMetrics) RecordInfo(version string) {}
func (*noopMetrics) RecordUp() {}
2 changes: 2 additions & 0 deletions op-challenger/scripts/alphabet/charlie.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ $CHALLENGER_DIR/bin/op-challenger \
--game-address $FAULT_GAME_ADDRESS \
--private-key $CHARLIE_KEY \
--num-confirmations 1 \
--metrics.enabled --metrics.port=7304 \
--pprof.enabled --pprof.port=6064 \
--agree-with-proposed-output=true
2 changes: 2 additions & 0 deletions op-challenger/scripts/alphabet/mallory.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ $CHALLENGER_DIR/bin/op-challenger \
--game-address $FAULT_GAME_ADDRESS \
--private-key $MALLORY_KEY \
--num-confirmations 1 \
--metrics.enabled --metrics.port=7305 \
--pprof.enabled --pprof.port=6065 \
--agree-with-proposed-output=false
8 changes: 8 additions & 0 deletions op-challenger/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ var (
Version = "v0.1.0"
Meta = "dev"
)

var SimpleWithMeta = func() string {
v := Version
if Meta != "" {
v += "-" + Meta
}
return v
}()
2 changes: 1 addition & 1 deletion op-proposer/proposer/l2_output_submitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func Main(version string, cliCtx *cli.Context) error {
l.Info("starting metrics server", "addr", metricsCfg.ListenAddr, "port", metricsCfg.ListenPort)
go func() {
if err := m.Serve(ctx, metricsCfg.ListenAddr, metricsCfg.ListenPort); err != nil {
l.Error("error starting metrics server", err)
l.Error("error starting metrics server", "err", err)
}
}()
m.StartBalanceMetrics(ctx, l, proposerConfig.L1Client, proposerConfig.TxManager.From())
Expand Down
14 changes: 12 additions & 2 deletions op-service/metrics/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@ const (
EnabledFlagName = "metrics.enabled"
ListenAddrFlagName = "metrics.addr"
PortFlagName = "metrics.port"
defaultListenAddr = "0.0.0.0"
defaultListenPort = 7300
)

func DefaultCLIConfig() CLIConfig {
return CLIConfig{
Enabled: false,
ListenAddr: defaultListenAddr,
ListenPort: defaultListenPort,
}
}

func CLIFlags(envPrefix string) []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Expand All @@ -25,13 +35,13 @@ func CLIFlags(envPrefix string) []cli.Flag {
&cli.StringFlag{
Name: ListenAddrFlagName,
Usage: "Metrics listening address",
Value: "0.0.0.0", // TODO(CLI-4159): Switch to 127.0.0.1
Value: defaultListenAddr, // TODO(CLI-4159): Switch to 127.0.0.1
EnvVars: opservice.PrefixEnvVar(envPrefix, "METRICS_ADDR"),
},
&cli.IntFlag{
Name: PortFlagName,
Usage: "Metrics listening port",
Value: 7300,
Value: defaultListenPort,
EnvVars: opservice.PrefixEnvVar(envPrefix, "METRICS_PORT"),
},
}
Expand Down
14 changes: 12 additions & 2 deletions op-service/pprof/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,18 @@ const (
EnabledFlagName = "pprof.enabled"
ListenAddrFlagName = "pprof.addr"
PortFlagName = "pprof.port"
defaultListenAddr = "0.0.0.0"
defaultListenPort = 6060
)

func DefaultCLIConfig() CLIConfig {
return CLIConfig{
Enabled: false,
ListenAddr: defaultListenAddr,
ListenPort: defaultListenPort,
}
}

func CLIFlags(envPrefix string) []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Expand All @@ -24,13 +34,13 @@ func CLIFlags(envPrefix string) []cli.Flag {
&cli.StringFlag{
Name: ListenAddrFlagName,
Usage: "pprof listening address",
Value: "0.0.0.0", // TODO(CLI-4159): Switch to 127.0.0.1
Value: defaultListenAddr, // TODO(CLI-4159): Switch to 127.0.0.1
EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_ADDR"),
},
&cli.IntFlag{
Name: PortFlagName,
Usage: "pprof listening port",
Value: 6060,
Value: defaultListenPort,
EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_PORT"),
},
}
Expand Down

0 comments on commit 532d8ce

Please sign in to comment.