Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit bfe5678

Browse files
authored
Add metrics for builder (#24)
* Add metrics for builder * add metrics for individual simulations * Add builder metrics to README (#34)
1 parent dccbf1c commit bfe5678

File tree

11 files changed

+115
-0
lines changed

11 files changed

+115
-0
lines changed

README.md

+13
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,26 @@ $ geth --help
9292
9393
--miner.extradata value
9494
Block extra data set by the miner (default = client version)
95+
96+
METRICS
97+
98+
--metrics.builder value (default: false)
99+
Enable builder metrics collection and reporting
95100
```
96101

97102
Environment variables:
98103
```
99104
BUILDER_TX_SIGNING_KEY - private key of the builder used to sign payment transaction, must be the same as the coinbase address
100105
```
101106

107+
## Metrics
108+
109+
To enable metrics on the builder you will need to enable metrics with the flags `--metrics --metrics.addr 127.0.0.1 --metrics.builder` which will run
110+
a metrics server serving at `127.0.0.1:6060/debug/metrics`. This will record performance metrics such as block profit and block building times.
111+
The full list of metrics can be found in `miner/metrics.go`.
112+
113+
See the [metrics docs](https://geth.ethereum.org/docs/monitoring/metrics) for geth for more documentation.
114+
102115
## Details of the implementation
103116

104117
There are two parts of the builder.

cmd/geth/chaincmd.go

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ The dumpgenesis command dumps the genesis block configuration in JSON format to
7979
utils.CacheGCFlag,
8080
utils.MetricsEnabledFlag,
8181
utils.MetricsEnabledExpensiveFlag,
82+
utils.MetricsEnabledBuilderFlag,
8283
utils.MetricsHTTPFlag,
8384
utils.MetricsPortFlag,
8485
utils.MetricsEnableInfluxDBFlag,

cmd/geth/config.go

+3
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ func applyMetricConfig(ctx *cli.Context, cfg *gethConfig) {
252252
if ctx.IsSet(utils.MetricsEnabledExpensiveFlag.Name) {
253253
cfg.Metrics.EnabledExpensive = ctx.Bool(utils.MetricsEnabledExpensiveFlag.Name)
254254
}
255+
if ctx.IsSet(utils.MetricsEnabledBuilderFlag.Name) {
256+
cfg.Metrics.EnabledBuilder = ctx.Bool(utils.MetricsEnabledBuilderFlag.Name)
257+
}
255258
if ctx.IsSet(utils.MetricsHTTPFlag.Name) {
256259
cfg.Metrics.HTTP = ctx.String(utils.MetricsHTTPFlag.Name)
257260
}

cmd/geth/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ var (
214214
metricsFlags = []cli.Flag{
215215
utils.MetricsEnabledFlag,
216216
utils.MetricsEnabledExpensiveFlag,
217+
utils.MetricsEnabledBuilderFlag,
217218
utils.MetricsHTTPFlag,
218219
utils.MetricsPortFlag,
219220
utils.MetricsEnableInfluxDBFlag,

cmd/utils/flags.go

+6
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,12 @@ var (
10261026
Usage: "Enable expensive metrics collection and reporting",
10271027
Category: flags.MetricsCategory,
10281028
}
1029+
// Builder metrics flag
1030+
MetricsEnabledBuilderFlag = &cli.BoolFlag{
1031+
Name: "metrics.builder",
1032+
Usage: "Enable builder metrics collection and reporting",
1033+
Category: flags.MetricsCategory,
1034+
}
10291035

10301036
// MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint.
10311037
// Since the pprof service enables sensitive/vulnerable behavior, this allows a user

core/state/metrics.go

+3
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,7 @@ var (
2525
storageDeletedMeter = metrics.NewRegisteredMeter("state/delete/storage", nil)
2626
accountTrieCommittedMeter = metrics.NewRegisteredMeter("state/commit/accountnodes", nil)
2727
storageTriesCommittedMeter = metrics.NewRegisteredMeter("state/commit/storagenodes", nil)
28+
29+
stateCopyMeter = metrics.NewRegisteredMeter("state/copy", nil)
30+
stateSnapshotMeter = metrics.NewRegisteredMeter("state/snapshot", nil)
2831
)

core/state/statedb.go

+10
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,11 @@ func (s *StateDB) Copy() *StateDB {
738738
state.snapStorage[k] = temp
739739
}
740740
}
741+
742+
if metrics.EnabledBuilder {
743+
stateCopyMeter.Mark(1)
744+
}
745+
741746
return state
742747
}
743748

@@ -746,6 +751,11 @@ func (s *StateDB) Snapshot() int {
746751
id := s.nextRevisionId
747752
s.nextRevisionId++
748753
s.validRevisions = append(s.validRevisions, revision{id, s.journal.length()})
754+
755+
if metrics.EnabledBuilder {
756+
stateSnapshotMeter.Mark(1)
757+
}
758+
749759
return id
750760
}
751761

metrics/config.go

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package metrics
2020
type Config struct {
2121
Enabled bool `toml:",omitempty"`
2222
EnabledExpensive bool `toml:",omitempty"`
23+
EnabledBuilder bool `toml:",omitempty"`
2324
HTTP string `toml:",omitempty"`
2425
Port int `toml:",omitempty"`
2526
EnableInfluxDB bool `toml:",omitempty"`
@@ -39,6 +40,7 @@ type Config struct {
3940
var DefaultConfig = Config{
4041
Enabled: false,
4142
EnabledExpensive: false,
43+
EnabledBuilder: false,
4244
HTTP: "127.0.0.1",
4345
Port: 6060,
4446
EnableInfluxDB: false,

metrics/metrics.go

+14
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,18 @@ var Enabled = false
2626
// for health monitoring and debug metrics that might impact runtime performance.
2727
var EnabledExpensive = false
2828

29+
// EnabledBuilder is a flag meant to collect metrics and performance of the builder
30+
var EnabledBuilder = false
31+
2932
// enablerFlags is the CLI flag names to use to enable metrics collections.
3033
var enablerFlags = []string{"metrics"}
3134

3235
// expensiveEnablerFlags is the CLI flag names to use to enable metrics collections.
3336
var expensiveEnablerFlags = []string{"metrics.expensive"}
3437

38+
// builderEnablerFlags is the CLI flag names to use to enable metrics collections.
39+
var builderEnablerFlags = []string{"metrics.builder"}
40+
3541
// Init enables or disables the metrics system. Since we need this to run before
3642
// any other code gets to create meters and timers, we'll actually do an ugly hack
3743
// and peek into the command line args for the metrics flag.
@@ -51,6 +57,14 @@ func init() {
5157
EnabledExpensive = true
5258
}
5359
}
60+
61+
for _, enabler := range builderEnablerFlags {
62+
if !EnabledBuilder && flag == enabler {
63+
log.Info("Enabling builder metrics collection")
64+
EnabledBuilder = true
65+
break
66+
}
67+
}
5468
}
5569
}
5670

miner/metrics.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package miner
2+
3+
import (
4+
"github.com/ethereum/go-ethereum/metrics"
5+
)
6+
7+
var (
8+
blockProfitHistogram = metrics.NewRegisteredHistogram("miner/block/profit", nil, metrics.NewExpDecaySample(1028, 0.015))
9+
bundleTxNumHistogram = metrics.NewRegisteredHistogram("miner/bundle/txnum", nil, metrics.NewExpDecaySample(1028, 0.015))
10+
blockProfitGauge = metrics.NewRegisteredGauge("miner/block/profit/gauge", nil)
11+
culmulativeProfitGauge = metrics.NewRegisteredGauge("miner/block/profit/culmulative", nil)
12+
13+
buildBlockTimer = metrics.NewRegisteredTimer("miner/block/build", nil)
14+
mergeAlgoTimer = metrics.NewRegisteredTimer("miner/block/merge", nil)
15+
blockBundleSimulationTimer = metrics.NewRegisteredTimer("miner/block/simulate", nil)
16+
successfulBundleSimulationTimer = metrics.NewRegisteredTimer("miner/bundle/simulate/success", nil)
17+
failedBundleSimulationTimer = metrics.NewRegisteredTimer("miner/bundle/simulate/failed", nil)
18+
19+
20+
simulationMeter = metrics.NewRegisteredMeter("miner/block/simulation", nil)
21+
simulationCommittedMeter = metrics.NewRegisteredMeter("miner/block/simulation/committed", nil)
22+
simulationRevertedMeter = metrics.NewRegisteredMeter("miner/block/simulation/reverted", nil)
23+
24+
gasUsedGauge = metrics.NewRegisteredGauge("miner/block/gasused", nil)
25+
transactionNumGauge = metrics.NewRegisteredGauge("miner/block/txnum", nil)
26+
)

miner/worker.go

+36
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"github.com/ethereum/go-ethereum/eth/tracers/logger"
3838
"github.com/ethereum/go-ethereum/event"
3939
"github.com/ethereum/go-ethereum/log"
40+
"github.com/ethereum/go-ethereum/metrics"
4041
"github.com/ethereum/go-ethereum/params"
4142
"github.com/ethereum/go-ethereum/trie"
4243
)
@@ -1388,7 +1389,11 @@ func (w *worker) fillTransactionsAlgoWorker(interrupt *int32, env *environment)
13881389
}
13891390

13901391
builder := newGreedyBuilder(w.chain, w.chainConfig, w.blockList, env, interrupt)
1392+
start := time.Now()
13911393
newEnv, blockBundles := builder.buildBlock(bundlesToConsider, pending)
1394+
if metrics.EnabledBuilder {
1395+
mergeAlgoTimer.Update(time.Since(start))
1396+
}
13921397
*env = *newEnv
13931398

13941399
return nil, blockBundles, bundlesToConsider
@@ -1432,6 +1437,14 @@ func (w *worker) generateWork(params *generateParams) (*types.Block, error) {
14321437
}
14331438

14341439
log.Info("Block finalized and assembled", "blockProfit", ethIntToFloat(block.Profit), "txs", len(env.txs), "bundles", len(blockBundles), "gasUsed", block.GasUsed(), "time", time.Since(start))
1440+
if metrics.EnabledBuilder {
1441+
buildBlockTimer.Update(time.Since(start))
1442+
blockProfitHistogram.Update(block.Profit.Int64())
1443+
blockProfitGauge.Update(block.Profit.Int64())
1444+
culmulativeProfitGauge.Inc(block.Profit.Int64())
1445+
gasUsedGauge.Update(int64(block.GasUsed()))
1446+
transactionNumGauge.Update(int64(len(env.txs)))
1447+
}
14351448
if params.onBlock != nil {
14361449
go params.onBlock(block, orderCloseTime, blockBundles, allBundles)
14371450
}
@@ -1722,17 +1735,37 @@ func (w *worker) simulateBundles(env *environment, bundles []types.MevBundle, pe
17221735
wg.Add(1)
17231736
go func(idx int, bundle types.MevBundle, state *state.StateDB) {
17241737
defer wg.Done()
1738+
1739+
start := time.Now()
1740+
if metrics.EnabledBuilder {
1741+
bundleTxNumHistogram.Update(int64(len(bundle.Txs)))
1742+
}
1743+
17251744
if len(bundle.Txs) == 0 {
17261745
return
17271746
}
17281747
gasPool := new(core.GasPool).AddGas(env.header.GasLimit)
17291748
simmed, err := w.computeBundleGas(env, bundle, state, gasPool, pendingTxs, 0)
17301749

1750+
if metrics.EnabledBuilder {
1751+
simulationMeter.Mark(1)
1752+
}
1753+
17311754
if err != nil {
1755+
if metrics.EnabledBuilder {
1756+
simulationRevertedMeter.Mark(1)
1757+
failedBundleSimulationTimer.UpdateSince(start)
1758+
}
1759+
17321760
log.Trace("Error computing gas for a bundle", "error", err)
17331761
return
17341762
}
17351763
simResult[idx] = &simmed
1764+
1765+
if metrics.EnabledBuilder {
1766+
simulationCommittedMeter.Mark(1)
1767+
successfulBundleSimulationTimer.UpdateSince(start)
1768+
}
17361769
}(i, bundle, env.state.Copy())
17371770
}
17381771

@@ -1748,6 +1781,9 @@ func (w *worker) simulateBundles(env *environment, bundles []types.MevBundle, pe
17481781
}
17491782

17501783
log.Debug("Simulated bundles", "block", env.header.Number, "allBundles", len(bundles), "okBundles", len(simulatedBundles), "time", time.Since(start))
1784+
if metrics.EnabledBuilder {
1785+
blockBundleSimulationTimer.Update(time.Since(start))
1786+
}
17511787
return simulatedBundles, nil
17521788
}
17531789

0 commit comments

Comments
 (0)