feature: keep track of and export total time observed by a timer (#949)

feature: keep track of and export total time observed by a timer (#772)

Co-authored-by: Ömer Faruk Irmak <omerfirmak@gmail.com>
This commit is contained in:
HAOYUatHZ 2024-08-01 10:35:29 +08:00 committed by GitHub
parent f6a030ccad
commit 05108d108c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 40 additions and 6 deletions

View file

@ -16,6 +16,8 @@
package metrics package metrics
import "time"
// compile-time checks that interfaces are implemented. // compile-time checks that interfaces are implemented.
var ( var (
_ SampleSnapshot = (*emptySnapshot)(nil) _ SampleSnapshot = (*emptySnapshot)(nil)
@ -46,3 +48,4 @@ func (*emptySnapshot) Rate1() float64 { return 0.0 }
func (*emptySnapshot) Rate5() float64 { return 0.0 } func (*emptySnapshot) Rate5() float64 { return 0.0 }
func (*emptySnapshot) Rate15() float64 { return 0.0 } func (*emptySnapshot) Rate15() float64 { return 0.0 }
func (*emptySnapshot) RateMean() float64 { return 0.0 } func (*emptySnapshot) RateMean() float64 { return 0.0 }
func (*emptySnapshot) Total() time.Duration { return 0 }

View file

@ -95,6 +95,7 @@ func readMeter(namespace, name string, i interface{}) (string, map[string]interf
"m5": ms.Rate5(), "m5": ms.Rate5(),
"m15": ms.Rate15(), "m15": ms.Rate15(),
"meanrate": ms.RateMean(), "meanrate": ms.RateMean(),
"total": int64(ms.Total()),
} }
return measurement, fields return measurement, fields
case metrics.ResettingTimer: case metrics.ResettingTimer:

View file

@ -4,10 +4,10 @@ import (
"context" "context"
"time" "time"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/metrics"
influxdb2 "github.com/influxdata/influxdb-client-go/v2" influxdb2 "github.com/influxdata/influxdb-client-go/v2"
"github.com/influxdata/influxdb-client-go/v2/api" "github.com/influxdata/influxdb-client-go/v2/api"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/metrics"
) )
type v2Reporter struct { type v2Reporter struct {

View file

@ -8,6 +8,7 @@ import (
type TimerSnapshot interface { type TimerSnapshot interface {
HistogramSnapshot HistogramSnapshot
MeterSnapshot MeterSnapshot
Total() time.Duration
} }
// Timers capture the duration and rate of events. // Timers capture the duration and rate of events.
@ -17,6 +18,7 @@ type Timer interface {
Time(func()) Time(func())
UpdateSince(time.Time) UpdateSince(time.Time)
Update(time.Duration) Update(time.Duration)
Total() time.Duration
} }
// GetOrRegisterTimer returns an existing Timer or constructs and registers a // GetOrRegisterTimer returns an existing Timer or constructs and registers a
@ -76,11 +78,14 @@ func (NilTimer) Time(f func()) { f() }
func (NilTimer) Update(time.Duration) {} func (NilTimer) Update(time.Duration) {}
func (NilTimer) UpdateSince(time.Time) {} func (NilTimer) UpdateSince(time.Time) {}
func (NilTimer) Total() time.Duration { return time.Duration(0) }
// StandardTimer is the standard implementation of a Timer and uses a Histogram // StandardTimer is the standard implementation of a Timer and uses a Histogram
// and Meter. // and Meter.
type StandardTimer struct { type StandardTimer struct {
histogram Histogram histogram Histogram
meter Meter meter Meter
total time.Duration
mutex sync.Mutex mutex sync.Mutex
} }
@ -91,6 +96,7 @@ func (t *StandardTimer) Snapshot() TimerSnapshot {
return &timerSnapshot{ return &timerSnapshot{
histogram: t.histogram.Snapshot(), histogram: t.histogram.Snapshot(),
meter: t.meter.Snapshot(), meter: t.meter.Snapshot(),
total: t.total,
} }
} }
@ -112,20 +118,24 @@ func (t *StandardTimer) Update(d time.Duration) {
defer t.mutex.Unlock() defer t.mutex.Unlock()
t.histogram.Update(int64(d)) t.histogram.Update(int64(d))
t.meter.Mark(1) t.meter.Mark(1)
t.total += d
} }
// Record the duration of an event that started at a time and ends now. // Record the duration of an event that started at a time and ends now.
func (t *StandardTimer) UpdateSince(ts time.Time) { func (t *StandardTimer) UpdateSince(ts time.Time) {
t.mutex.Lock() t.Update(time.Since(ts))
defer t.mutex.Unlock() }
t.histogram.Update(int64(time.Since(ts)))
t.meter.Mark(1) // Total returns the total time that events observed by this timer took
func (t *StandardTimer) Total() time.Duration {
return t.total
} }
// timerSnapshot is a read-only copy of another Timer. // timerSnapshot is a read-only copy of another Timer.
type timerSnapshot struct { type timerSnapshot struct {
histogram HistogramSnapshot histogram HistogramSnapshot
meter MeterSnapshot meter MeterSnapshot
total time.Duration
} }
// Count returns the number of events recorded at the time the snapshot was // Count returns the number of events recorded at the time the snapshot was
@ -182,3 +192,8 @@ func (t *timerSnapshot) Sum() int64 { return t.histogram.Sum() }
// Variance returns the variance of the values at the time the snapshot was // Variance returns the variance of the values at the time the snapshot was
// taken. // taken.
func (t *timerSnapshot) Variance() float64 { return t.histogram.Variance() } func (t *timerSnapshot) Variance() float64 { return t.histogram.Variance() }
// Total returns the total time that events observed by this timer took
func (t *timerSnapshot) Total() time.Duration {
return t.total
}

View file

@ -112,3 +112,18 @@ func ExampleGetOrRegisterTimer() {
t.Update(47) t.Update(47)
fmt.Println(t.Snapshot().Max()) // Output: 47 fmt.Println(t.Snapshot().Max()) // Output: 47
} }
func TestTimerSum(t *testing.T) {
tm := GetOrRegisterTimer("test.timer.sum", nil)
times := 5000000
for i := 0; i < times; i++ {
tm.Update(time.Second)
}
ss := tm.Snapshot()
if total := tm.Total().Seconds(); total != float64(times) {
t.Errorf("tm.Total().Seconds(): 5000000.0 != %v\n", total)
}
if total := ss.Total().Seconds(); total != float64(times) {
t.Errorf("ss.Total().Seconds(): 5000000.0 != %v\n", total)
}
}