diff --git a/metrics/exp/exp.go b/metrics/exp/exp.go index 7e3f82a075..b40d4bd257 100644 --- a/metrics/exp/exp.go +++ b/metrics/exp/exp.go @@ -123,6 +123,12 @@ func (exp *exp) publishGauge(name string, metric metrics.GaugeSnapshot) { v := exp.getInt(name) v.Set(metric.Value()) } +func (exp *exp) publishResettingGauge(name string, metric metrics.ResettingGaugeSnapshot) { + v := exp.getInt(name) + if val := metric.Value(); val != 0 { + v.Set(val) + } +} func (exp *exp) publishGaugeFloat64(name string, metric metrics.GaugeFloat64Snapshot) { exp.getFloat(name).Set(metric.Value()) } @@ -194,6 +200,8 @@ func (exp *exp) syncToExpvar() { exp.publishCounterFloat64(name, i.Snapshot()) case metrics.Gauge: exp.publishGauge(name, i.Snapshot()) + case metrics.ResettingGauge: + exp.publishResettingGauge(name, i.Snapshot()) case metrics.GaugeFloat64: exp.publishGaugeFloat64(name, i.Snapshot()) case metrics.GaugeInfo: diff --git a/metrics/influxdb/influxdb.go b/metrics/influxdb/influxdb.go index 5c8501fd9d..751d2b07e5 100644 --- a/metrics/influxdb/influxdb.go +++ b/metrics/influxdb/influxdb.go @@ -26,6 +26,16 @@ func readMeter(namespace, name string, i interface{}) (string, map[string]interf "value": metric.Snapshot().Value(), } return measurement, fields + case metrics.ResettingGauge: + ms := metric.Snapshot() + if ms.Value() == 0 { + break + } + measurement := fmt.Sprintf("%s%s.gauge", namespace, name) + fields := map[string]interface{}{ + "value": ms.Value(), + } + return measurement, fields case metrics.GaugeFloat64: measurement := fmt.Sprintf("%s%s.gauge", namespace, name) fields := map[string]interface{}{ diff --git a/metrics/influxdb/testdata/influxdbv1.want b/metrics/influxdb/testdata/influxdbv1.want index ded9434c73..93552de851 100644 --- a/metrics/influxdb/testdata/influxdbv1.want +++ b/metrics/influxdb/testdata/influxdbv1.want @@ -7,5 +7,6 @@ goth.test/gauge_float64.gauge value=34567.89 978307200000000000 goth.test/gauge_info.gauge value="{\"arch\":\"amd64\",\"commit\":\"7caa2d8163ae3132c1c2d6978c76610caee2d949\",\"os\":\"linux\",\"protocol_versions\":\"64 65 66\",\"version\":\"1.10.18-unstable\"}" 978307200000000000 goth.test/histogram.histogram count=3i,max=3i,mean=2,min=1i,p25=1,p50=2,p75=3,p95=3,p99=3,p999=3,p9999=3,stddev=0.816496580927726,variance=0.6666666666666666 978307200000000000 goth.test/meter.meter count=0i,m1=0,m15=0,m5=0,mean=0 978307200000000000 +goth.test/resetting_gauge.gauge value=23456i 978307200000000000 goth.test/resetting_timer.timer count=6i,max=120000000i,mean=30000000,min=10000000i,p50=12500000,p75=40500000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000 978307200000000000 goth.test/timer.timer count=6i,m1=0,m15=0,m5=0,max=120000000i,mean=38333333.333333336,meanrate=0,min=20000000i,p50=22500000,p75=48000000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000,stddev=36545253.529775314,variance=1335555555555555.2 978307200000000000 diff --git a/metrics/influxdb/testdata/influxdbv2.want b/metrics/influxdb/testdata/influxdbv2.want index ded9434c73..93552de851 100644 --- a/metrics/influxdb/testdata/influxdbv2.want +++ b/metrics/influxdb/testdata/influxdbv2.want @@ -7,5 +7,6 @@ goth.test/gauge_float64.gauge value=34567.89 978307200000000000 goth.test/gauge_info.gauge value="{\"arch\":\"amd64\",\"commit\":\"7caa2d8163ae3132c1c2d6978c76610caee2d949\",\"os\":\"linux\",\"protocol_versions\":\"64 65 66\",\"version\":\"1.10.18-unstable\"}" 978307200000000000 goth.test/histogram.histogram count=3i,max=3i,mean=2,min=1i,p25=1,p50=2,p75=3,p95=3,p99=3,p999=3,p9999=3,stddev=0.816496580927726,variance=0.6666666666666666 978307200000000000 goth.test/meter.meter count=0i,m1=0,m15=0,m5=0,mean=0 978307200000000000 +goth.test/resetting_gauge.gauge value=23456i 978307200000000000 goth.test/resetting_timer.timer count=6i,max=120000000i,mean=30000000,min=10000000i,p50=12500000,p75=40500000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000 978307200000000000 goth.test/timer.timer count=6i,m1=0,m15=0,m5=0,max=120000000i,mean=38333333.333333336,meanrate=0,min=20000000i,p50=22500000,p75=48000000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000,stddev=36545253.529775314,variance=1335555555555555.2 978307200000000000 diff --git a/metrics/internal/sampledata.go b/metrics/internal/sampledata.go index de9b207b6d..e5e225d2e5 100644 --- a/metrics/internal/sampledata.go +++ b/metrics/internal/sampledata.go @@ -32,6 +32,17 @@ func ExampleMetrics() metrics.Registry { metrics.NewRegisteredCounterFloat64("test/counter", registry).Inc(12345) metrics.NewRegisteredCounterFloat64("test/counter_float64", registry).Inc(54321.98) metrics.NewRegisteredGauge("test/gauge", registry).Update(23456) + + metrics.NewRegisteredResettingGauge("test/empty_resetting_gauge", registry) + { + gauge := metrics.NewRegisteredResettingGauge("test/resetting_gauge", registry) + gauge.Update(23456) + } + { + gauge := metrics.NewRegisteredResettingGauge("test/resetting_gauge_reset", registry) + gauge.Update(23456) + gauge.Snapshot() + } metrics.NewRegisteredGaugeFloat64("test/gauge_float64", registry).Update(34567.89) metrics.NewRegisteredGaugeInfo("test/gauge_info", registry).Update( metrics.GaugeInfoValue{ @@ -70,7 +81,7 @@ func ExampleMetrics() metrics.Registry { timer.Update(24 * time.Millisecond) timer.Stop() } - registry.Register("test/empty_resetting_timer", metrics.NewResettingTimer().Snapshot()) + metrics.NewRegisteredResettingTimer("test/empty_resetting_timer", registry).Snapshot() { // go runtime metrics var sLatency = "7\xff\x81\x03\x01\x01\x10Float64Histogram\x01\xff\x82\x00\x01\x02\x01\x06Counts\x01\xff\x84\x00\x01\aBuckets\x01\xff\x86\x00\x00\x00\x16\xff\x83\x02\x01\x01\b[]uint64\x01\xff\x84\x00\x01\x06\x00\x00\x17\xff\x85\x02\x01\x01\t[]float64\x01\xff\x86\x00\x01\b\x00\x00\xfe\x06T\xff\x82\x01\xff\xa2\x00\xfe\r\xef\x00\x01\x02\x02\x04\x05\x04\b\x15\x17 B?6.L;$!2) \x1a? \x190aH7FY6#\x190\x1d\x14\x10\x1b\r\t\x04\x03\x01\x01\x00\x03\x02\x00\x03\x05\x05\x02\x02\x06\x04\v\x06\n\x15\x18\x13'&.\x12=H/L&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\xa3\xfe\xf0\xff\x00\xf8\x95\xd6&\xe8\v.q>\xf8\x95\xd6&\xe8\v.\x81>\xf8\xdfA:\xdc\x11ʼn>\xf8\x95\xd6&\xe8\v.\x91>\xf8:\x8c0\xe2\x8ey\x95>\xf8\xdfA:\xdc\x11ř>\xf8\x84\xf7C֔\x10\x9e>\xf8\x95\xd6&\xe8\v.\xa1>\xf8:\x8c0\xe2\x8ey\xa5>\xf8\xdfA:\xdc\x11ũ>\xf8\x84\xf7C֔\x10\xae>\xf8\x95\xd6&\xe8\v.\xb1>\xf8:\x8c0\xe2\x8ey\xb5>\xf8\xdfA:\xdc\x11Ź>\xf8\x84\xf7C֔\x10\xbe>\xf8\x95\xd6&\xe8\v.\xc1>\xf8:\x8c0\xe2\x8ey\xc5>\xf8\xdfA:\xdc\x11\xc5\xc9>\xf8\x84\xf7C֔\x10\xce>\xf8\x95\xd6&\xe8\v.\xd1>\xf8:\x8c0\xe2\x8ey\xd5>\xf8\xdfA:\xdc\x11\xc5\xd9>\xf8\x84\xf7C֔\x10\xde>\xf8\x95\xd6&\xe8\v.\xe1>\xf8:\x8c0\xe2\x8ey\xe5>\xf8\xdfA:\xdc\x11\xc5\xe9>\xf8\x84\xf7C֔\x10\xee>\xf8\x95\xd6&\xe8\v.\xf1>\xf8:\x8c0\xe2\x8ey\xf5>\xf8\xdfA:\xdc\x11\xc5\xf9>\xf8\x84\xf7C֔\x10\xfe>\xf8\x95\xd6&\xe8\v.\x01?\xf8:\x8c0\xe2\x8ey\x05?\xf8\xdfA:\xdc\x11\xc5\t?\xf8\x84\xf7C֔\x10\x0e?\xf8\x95\xd6&\xe8\v.\x11?\xf8:\x8c0\xe2\x8ey\x15?\xf8\xdfA:\xdc\x11\xc5\x19?\xf8\x84\xf7C֔\x10\x1e?\xf8\x95\xd6&\xe8\v.!?\xf8:\x8c0\xe2\x8ey%?\xf8\xdfA:\xdc\x11\xc5)?\xf8\x84\xf7C֔\x10.?\xf8\x95\xd6&\xe8\v.1?\xf8:\x8c0\xe2\x8ey5?\xf8\xdfA:\xdc\x11\xc59?\xf8\x84\xf7C֔\x10>?\xf8\x95\xd6&\xe8\v.A?\xf8:\x8c0\xe2\x8eyE?\xf8\xdfA:\xdc\x11\xc5I?\xf8\x84\xf7C֔\x10N?\xf8\x95\xd6&\xe8\v.Q?\xf8:\x8c0\xe2\x8eyU?\xf8\xdfA:\xdc\x11\xc5Y?\xf8\x84\xf7C֔\x10^?\xf8\x95\xd6&\xe8\v.a?\xf8:\x8c0\xe2\x8eye?\xf8\xdfA:\xdc\x11\xc5i?\xf8\x84\xf7C֔\x10n?\xf8\x95\xd6&\xe8\v.q?\xf8:\x8c0\xe2\x8eyu?\xf8\xdfA:\xdc\x11\xc5y?\xf8\x84\xf7C֔\x10~?\xf8\x95\xd6&\xe8\v.\x81?\xf8:\x8c0\xe2\x8ey\x85?\xf8\xdfA:\xdc\x11ʼn?\xf8\x84\xf7C֔\x10\x8e?\xf8\x95\xd6&\xe8\v.\x91?\xf8:\x8c0\xe2\x8ey\x95?\xf8\xdfA:\xdc\x11ř?\xf8\x84\xf7C֔\x10\x9e?\xf8\x95\xd6&\xe8\v.\xa1?\xf8:\x8c0\xe2\x8ey\xa5?\xf8\xdfA:\xdc\x11ũ?\xf8\x84\xf7C֔\x10\xae?\xf8\x95\xd6&\xe8\v.\xb1?\xf8:\x8c0\xe2\x8ey\xb5?\xf8\xdfA:\xdc\x11Ź?\xf8\x84\xf7C֔\x10\xbe?\xf8\x95\xd6&\xe8\v.\xc1?\xf8:\x8c0\xe2\x8ey\xc5?\xf8\xdfA:\xdc\x11\xc5\xc9?\xf8\x84\xf7C֔\x10\xce?\xf8\x95\xd6&\xe8\v.\xd1?\xf8:\x8c0\xe2\x8ey\xd5?\xf8\xdfA:\xdc\x11\xc5\xd9?\xf8\x84\xf7C֔\x10\xde?\xf8\x95\xd6&\xe8\v.\xe1?\xf8:\x8c0\xe2\x8ey\xe5?\xf8\xdfA:\xdc\x11\xc5\xe9?\xf8\x84\xf7C֔\x10\xee?\xf8\x95\xd6&\xe8\v.\xf1?\xf8:\x8c0\xe2\x8ey\xf5?\xf8\xdfA:\xdc\x11\xc5\xf9?\xf8\x84\xf7C֔\x10\xfe?\xf8\x95\xd6&\xe8\v.\x01@\xf8:\x8c0\xe2\x8ey\x05@\xf8\xdfA:\xdc\x11\xc5\t@\xf8\x84\xf7C֔\x10\x0e@\xf8\x95\xd6&\xe8\v.\x11@\xf8:\x8c0\xe2\x8ey\x15@\xf8\xdfA:\xdc\x11\xc5\x19@\xf8\x84\xf7C֔\x10\x1e@\xf8\x95\xd6&\xe8\v.!@\xf8:\x8c0\xe2\x8ey%@\xf8\xdfA:\xdc\x11\xc5)@\xf8\x84\xf7C֔\x10.@\xf8\x95\xd6&\xe8\v.1@\xf8:\x8c0\xe2\x8ey5@\xf8\xdfA:\xdc\x11\xc59@\xf8\x84\xf7C֔\x10>@\xf8\x95\xd6&\xe8\v.A@\xf8:\x8c0\xe2\x8eyE@\xf8\xdfA:\xdc\x11\xc5I@\xf8\x84\xf7C֔\x10N@\xf8\x95\xd6&\xe8\v.Q@\xf8:\x8c0\xe2\x8eyU@\xf8\xdfA:\xdc\x11\xc5Y@\xf8\x84\xf7C֔\x10^@\xf8\x95\xd6&\xe8\v.a@\xf8:\x8c0\xe2\x8eye@\xf8\xdfA:\xdc\x11\xc5i@\xf8\x84\xf7C֔\x10n@\xf8\x95\xd6&\xe8\v.q@\xf8:\x8c0\xe2\x8eyu@\xf8\xdfA:\xdc\x11\xc5y@\xf8\x84\xf7C֔\x10~@\xf8\x95\xd6&\xe8\v.\x81@\xf8:\x8c0\xe2\x8ey\x85@\xf8\xdfA:\xdc\x11ʼn@\xf8\x84\xf7C֔\x10\x8e@\xf8\x95\xd6&\xe8\v.\x91@\xf8:\x8c0\xe2\x8ey\x95@\xf8\xdfA:\xdc\x11ř@\xf8\x84\xf7C֔\x10\x9e@\xf8\x95\xd6&\xe8\v.\xa1@\xf8:\x8c0\xe2\x8ey\xa5@\xf8\xdfA:\xdc\x11ũ@\xf8\x84\xf7C֔\x10\xae@\xf8\x95\xd6&\xe8\v.\xb1@\xf8:\x8c0\xe2\x8ey\xb5@\xf8\xdfA:\xdc\x11Ź@\xf8\x84\xf7C֔\x10\xbe@\xf8\x95\xd6&\xe8\v.\xc1@\xf8:\x8c0\xe2\x8ey\xc5@\xf8\xdfA:\xdc\x11\xc5\xc9@\xf8\x84\xf7C֔\x10\xce@\xf8\x95\xd6&\xe8\v.\xd1@\xf8:\x8c0\xe2\x8ey\xd5@\xf8\xdfA:\xdc\x11\xc5\xd9@\xf8\x84\xf7C֔\x10\xde@\xf8\x95\xd6&\xe8\v.\xe1@\xf8:\x8c0\xe2\x8ey\xe5@\xf8\xdfA:\xdc\x11\xc5\xe9@\xf8\x84\xf7C֔\x10\xee@\xf8\x95\xd6&\xe8\v.\xf1@\xf8:\x8c0\xe2\x8ey\xf5@\xf8\xdfA:\xdc\x11\xc5\xf9@\xf8\x84\xf7C֔\x10\xfe@\xf8\x95\xd6&\xe8\v.\x01A\xfe\xf0\x7f\x00" diff --git a/metrics/prometheus/collector.go b/metrics/prometheus/collector.go index 353336763b..69d5f3f25e 100644 --- a/metrics/prometheus/collector.go +++ b/metrics/prometheus/collector.go @@ -50,6 +50,7 @@ func newCollector() *collector { // Add adds the metric i to the collector. This method returns an error if the // metric type is not supported/known. func (c *collector) Add(name string, i any) error { + fmt.Println(name, i) switch m := i.(type) { case metrics.Counter: c.addCounter(name, m.Snapshot()) @@ -57,6 +58,8 @@ func (c *collector) Add(name string, i any) error { c.addCounterFloat64(name, m.Snapshot()) case metrics.Gauge: c.addGauge(name, m.Snapshot()) + case metrics.ResettingGauge: + c.addResettingGauge(name, m.Snapshot()) case metrics.GaugeFloat64: c.addGaugeFloat64(name, m.Snapshot()) case metrics.GaugeInfo: @@ -87,6 +90,13 @@ func (c *collector) addGauge(name string, m metrics.GaugeSnapshot) { c.writeGaugeCounter(name, m.Value()) } +func (c *collector) addResettingGauge(name string, m metrics.GaugeSnapshot) { + if m.Value() == 0 { + return + } + c.writeGaugeCounter(name, m.Value()) +} + func (c *collector) addGaugeFloat64(name string, m metrics.GaugeFloat64Snapshot) { c.writeGaugeCounter(name, m.Value()) } diff --git a/metrics/prometheus/testdata/prometheus.want b/metrics/prometheus/testdata/prometheus.want index a999d83801..2ae7d1f71e 100644 --- a/metrics/prometheus/testdata/prometheus.want +++ b/metrics/prometheus/testdata/prometheus.want @@ -49,6 +49,9 @@ test_histogram {quantile="0.9999"} 3 # TYPE test_meter gauge test_meter 0 +# TYPE test_resetting_gauge gauge +test_resetting_gauge 23456 + # TYPE test_resetting_timer_count counter test_resetting_timer_count 6 diff --git a/metrics/registry.go b/metrics/registry.go index 8bfbc08042..fcb003bc87 100644 --- a/metrics/registry.go +++ b/metrics/registry.go @@ -214,7 +214,7 @@ func (r *StandardRegistry) Unregister(name string) { func (r *StandardRegistry) loadOrRegister(name string, i interface{}) (interface{}, bool, bool) { switch i.(type) { - case Counter, CounterFloat64, Gauge, GaugeFloat64, GaugeInfo, Healthcheck, Histogram, Meter, Timer, ResettingTimer: + case Counter, CounterFloat64, Gauge, ResettingGauge, GaugeFloat64, GaugeInfo, Healthcheck, Histogram, Meter, Timer, ResettingTimer: default: return nil, false, false } diff --git a/metrics/resetting_gauge.go b/metrics/resetting_gauge.go new file mode 100644 index 0000000000..2f744531dc --- /dev/null +++ b/metrics/resetting_gauge.go @@ -0,0 +1,100 @@ +package metrics + +import "sync/atomic" + +// ResettingGaugeSnapshot contains a readonly int64. +type ResettingGaugeSnapshot interface { + Value() int64 +} + +// ResettingGauge holds an int64 value that can be set arbitrarily. +type ResettingGauge interface { + Snapshot() ResettingGaugeSnapshot + Update(int64) + UpdateIfGt(int64) + Dec(int64) + Inc(int64) +} + +// GetOrRegisterResettingGauge returns an existing Gauge or constructs and registers a +// new ResettingGauge. +func GetOrRegisterResettingGauge(name string, r Registry) ResettingGauge { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewResettingGauge).(ResettingGauge) +} + +// NewResettingGauge constructs a new StandardResettingGauge. +func NewResettingGauge() ResettingGauge { + if !Enabled { + return NilResettingGauge{} + } + return &StandardResettingGauge{} +} + +// NewRegisteredResettingGauge constructs and registers a new StandardResettingGauge. +func NewRegisteredResettingGauge(name string, r Registry) ResettingGauge { + c := NewResettingGauge() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// resettingGaugeSnapshot is a read-only copy of another Gauge. +type resettingGaugeSnapshot int64 + +// Value returns the value at the time the snapshot was taken. +func (g resettingGaugeSnapshot) Value() int64 { return int64(g) } + +// NilResettingGauge is a no-op Gauge. +type NilResettingGauge struct{} + +func (NilResettingGauge) Snapshot() ResettingGaugeSnapshot { return (*emptySnapshot)(nil) } +func (NilResettingGauge) Update(v int64) {} +func (NilResettingGauge) UpdateIfGt(v int64) {} +func (NilResettingGauge) Dec(i int64) {} +func (NilResettingGauge) Inc(i int64) {} + +// StandardResettingGauge is the resetting implementation of a Gauge and uses the +// sync/atomic package to manage a single int64 value. +type StandardResettingGauge struct { + value atomic.Int64 +} + +// Snapshot returns a read-only copy of the gauge. +func (g *StandardResettingGauge) Snapshot() ResettingGaugeSnapshot { + snapshot := resettingGaugeSnapshot(g.value.Load()) + g.value.Store(0) + return snapshot +} + +// Update updates the gauge's value. +func (g *StandardResettingGauge) Update(v int64) { + g.value.Store(v) +} + +// Update updates the gauge's value if v is larger then the current value. +func (g *StandardResettingGauge) UpdateIfGt(v int64) { + for { + exist := g.value.Load() + if exist >= v { + break + } + if g.value.CompareAndSwap(exist, v) { + break + } + } +} + +// Dec decrements the gauge's current value by the given amount. +func (g *StandardResettingGauge) Dec(i int64) { + g.value.Add(-i) +} + +// Inc increments the gauge's current value by the given amount. +func (g *StandardResettingGauge) Inc(i int64) { + g.value.Add(i) +} diff --git a/miner/metrics.go b/miner/metrics.go new file mode 100644 index 0000000000..f5547a7eec --- /dev/null +++ b/miner/metrics.go @@ -0,0 +1,27 @@ +// Copyright 2024 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package miner + +import "github.com/ethereum/go-ethereum/metrics" + +// blockRecommitFeeGaugeName is the name of the metrics collection that tracks +// the block fees generated by each recommit round (relative to the latest). +var blockRecommitFeeGaugeName = "miner/fees/recommits" + +// blockFinalFeeGauge is the metric tracking the best fee proposed based on the +// local transaction pool. +var blockFinalFeeGauge = metrics.NewRegisteredResettingGauge("miner/fees/proposed", nil) diff --git a/miner/payload_building.go b/miner/payload_building.go index cbdb82a642..45fd899e7c 100644 --- a/miner/payload_building.go +++ b/miner/payload_building.go @@ -19,6 +19,7 @@ package miner import ( "crypto/sha256" "encoding/binary" + "fmt" "math/big" "sync" "time" @@ -27,10 +28,15 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) +// bigGwei is usde by the metrics to report on block fees on a scale that fits +// into an int64. +var bigGwei = big.NewInt(1_000_000_000) + // BuildPayloadArgs contains the provided parameters for building payload. // Check engine-api specification for more details. // https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#payloadattributesv3 @@ -75,6 +81,8 @@ type Payload struct { stop chan struct{} lock sync.Mutex cond *sync.Cond + + recommits []*big.Int } // newPayload initializes the payload object. @@ -99,6 +107,9 @@ func (payload *Payload) update(r *newPayloadResult, elapsed time.Duration) { return // reject stale update default: } + // Stash away all the commit fees to report in metrics + payload.recommits = append(payload.recommits, r.fees) + // Ensure the newly provided full block has a higher transaction fee. // In post-merge stage, there is no uncle reward anymore and transaction // fee(apart from the mev revenue) is the only indicator for comparison. @@ -172,6 +183,13 @@ func (payload *Payload) ResolveFull() *engine.ExecutionPayloadEnvelope { default: close(payload.stop) } + // Report all the recommits into individual metrics + for i := len(payload.recommits) - 1; i >= 0; i-- { + // Track the generated fees in the metrics + gauge := fmt.Sprintf("%s/%d", blockRecommitFeeGaugeName, len(payload.recommits)-i-1) + metrics.GetOrRegisterResettingGauge(gauge, nil).Update(new(big.Int).Div(payload.recommits[i], bigGwei).Int64()) + } + blockFinalFeeGauge.Update(new(big.Int).Div(payload.fullFees, bigGwei).Int64()) return engine.BlockToExecutableData(payload.full, payload.fullFees, payload.sidecars) } @@ -221,7 +239,6 @@ func (miner *Miner) buildPayload(args *BuildPayloadArgs) (*Payload, error) { beaconRoot: args.BeaconRoot, noTxs: false, } - for { select { case <-timer.C: