diff --git a/metrics/exp/exp.go b/metrics/exp/exp.go index dd528d1525..100fd9d167 100644 --- a/metrics/exp/exp.go +++ b/metrics/exp/exp.go @@ -177,7 +177,7 @@ func (exp *exp) publishTimer(name string, metric metrics.Timer) { func (exp *exp) publishResettingTimer(name string, metric metrics.ResettingTimer) { t := metric.Snapshot() ps := t.Percentiles([]float64{50, 75, 95, 99}) - exp.getInt(name + ".count").Set(int64(len(t.Values()))) + exp.getInt(name + ".count").Set(int64(t.Count())) exp.getFloat(name + ".mean").Set(t.Mean()) exp.getInt(name + ".50-percentile").Set(ps[0]) exp.getInt(name + ".75-percentile").Set(ps[1]) diff --git a/metrics/influxdb/influxdb.go b/metrics/influxdb/influxdb.go index ef2e4154a9..83c2edfb0d 100644 --- a/metrics/influxdb/influxdb.go +++ b/metrics/influxdb/influxdb.go @@ -99,17 +99,16 @@ func readMeter(namespace, name string, i interface{}) (string, map[string]interf return measurement, fields case metrics.ResettingTimer: t := metric.Snapshot() - if len(t.Values()) == 0 { + if t.Count() == 0 { break } ps := t.Percentiles([]float64{50, 95, 99}) - val := t.Values() measurement := fmt.Sprintf("%s%s.span", namespace, name) fields := map[string]interface{}{ - "count": len(val), - "max": val[len(val)-1], + "count": t.Count(), + "max": t.Max(), "mean": t.Mean(), - "min": val[0], + "min": t.Min(), "p50": ps[0], "p95": ps[1], "p99": ps[2], diff --git a/metrics/prometheus/collector.go b/metrics/prometheus/collector.go index c3b5cabfbc..45e8a914be 100644 --- a/metrics/prometheus/collector.go +++ b/metrics/prometheus/collector.go @@ -122,12 +122,11 @@ func (c *collector) addTimer(name string, m metrics.TimerSnapshot) { } func (c *collector) addResettingTimer(name string, m metrics.ResettingTimerSnapshot) { - if len(m.Values()) <= 0 { + if m.Count() <= 0 { return } ps := m.Percentiles([]float64{50, 95, 99}) - val := m.Values() - c.writeSummaryCounter(name, len(val)) + c.writeSummaryCounter(name, m.Count()) c.buff.WriteString(fmt.Sprintf(typeSummaryTpl, mutateKey(name))) c.writeSummaryPercentile(name, "0.50", ps[0]) c.writeSummaryPercentile(name, "0.95", ps[1]) diff --git a/metrics/resetting_timer.go b/metrics/resetting_timer.go index 7e609e480f..b5bbc753cc 100644 --- a/metrics/resetting_timer.go +++ b/metrics/resetting_timer.go @@ -12,8 +12,10 @@ import ( const InitialResettingTimerSliceCap = 10 type ResettingTimerSnapshot interface { - Values() []int64 + Count() int Mean() float64 + Max() int64 + Min() int64 Percentiles([]float64) []int64 } @@ -63,7 +65,10 @@ func (NilResettingTimer) Time(f func()) { f() } func (NilResettingTimer) Update(time.Duration) {} func (NilResettingTimer) Percentiles([]float64) []int64 { return nil } func (NilResettingTimer) Mean() float64 { return 0.0 } +func (NilResettingTimer) Max() int64 { return 0 } +func (NilResettingTimer) Min() int64 { return 0 } func (NilResettingTimer) UpdateSince(time.Time) {} +func (NilResettingTimer) Count() int { return 0 } // StandardResettingTimer is the standard implementation of a ResettingTimer. // and Meter. @@ -72,11 +77,6 @@ type StandardResettingTimer struct { mutex sync.Mutex } -//// Values returns a slice with all measurements. -//func (t *StandardResettingTimer) Values() []int64 { -// return t.values -//} - // Snapshot resets the timer and returns a read-only copy of its contents. func (t *StandardResettingTimer) Snapshot() ResettingTimerSnapshot { t.mutex.Lock() @@ -114,13 +114,15 @@ func (t *StandardResettingTimer) UpdateSince(ts time.Time) { type resettingTimerSnapshot struct { values []int64 mean float64 + max int64 + min int64 thresholdBoundaries []int64 calculated bool } -// Values returns all values from snapshot. -func (t *resettingTimerSnapshot) Values() []int64 { - return t.values +// Count return the length of the values from snapshot. +func (t *resettingTimerSnapshot) Count() int { + return len(t.values) } // Percentiles returns the boundaries for the input percentiles. @@ -134,12 +136,32 @@ func (t *resettingTimerSnapshot) Percentiles(percentiles []float64) []int64 { // note: this method is not thread safe func (t *resettingTimerSnapshot) Mean() float64 { if !t.calculated { - t.calc([]float64{}) + t.calc(nil) } return t.mean } +// Max returns the max of the snapshotted values +// note: this method is not thread safe +func (t *resettingTimerSnapshot) Max() int64 { + if !t.calculated { + t.calc(nil) + } + + return t.max +} + +// Min returns the min of the snapshotted values +// note: this method is not thread safe +func (t *resettingTimerSnapshot) Min() int64 { + if !t.calculated { + t.calc(nil) + } + + return t.min +} + func (t *resettingTimerSnapshot) calc(percentiles []float64) { slices.Sort(t.values) count := len(t.values) @@ -149,18 +171,18 @@ func (t *resettingTimerSnapshot) calc(percentiles []float64) { t.calculated = true return } - min := t.values[0] - max := t.values[count-1] + t.min = t.values[0] + t.max = t.values[count-1] cumulativeValues := make([]int64, count) - cumulativeValues[0] = min + cumulativeValues[0] = t.min for i := 1; i < count; i++ { cumulativeValues[i] = t.values[i] + cumulativeValues[i-1] } t.thresholdBoundaries = make([]int64, len(percentiles)) - thresholdBoundary := max + thresholdBoundary := t.max for i, pct := range percentiles { if count > 1 { diff --git a/metrics/resetting_timer_test.go b/metrics/resetting_timer_test.go index 77c49dc386..5bc88e38bd 100644 --- a/metrics/resetting_timer_test.go +++ b/metrics/resetting_timer_test.go @@ -75,16 +75,12 @@ func TestResettingTimer(t *testing.T) { ps := snap.Percentiles([]float64{50, 95, 99}) - val := snap.Values() + if tt.wantMin != snap.Min() { + t.Fatalf("%d: min: got %d, want %d", ind, snap.Min(), tt.wantMin) + } - if len(val) > 0 { - if tt.wantMin != val[0] { - t.Fatalf("%d: min: got %d, want %d", ind, val[0], tt.wantMin) - } - - if tt.wantMax != val[len(val)-1] { - t.Fatalf("%d: max: got %d, want %d", ind, val[len(val)-1], tt.wantMax) - } + if tt.wantMax != snap.Max() { + t.Fatalf("%d: max: got %d, want %d", ind, snap.Max(), tt.wantMax) } if tt.wantMean != snap.Mean() { @@ -177,16 +173,12 @@ func TestResettingTimerWithFivePercentiles(t *testing.T) { ps := snap.Percentiles([]float64{5, 20, 50, 95, 99}) - val := snap.Values() + if tt.wantMin != snap.Min() { + t.Fatalf("%d: min: got %d, want %d", ind, snap.Min(), tt.wantMin) + } - if len(val) > 0 { - if tt.wantMin != val[0] { - t.Fatalf("%d: min: got %d, want %d", ind, val[0], tt.wantMin) - } - - if tt.wantMax != val[len(val)-1] { - t.Fatalf("%d: max: got %d, want %d", ind, val[len(val)-1], tt.wantMax) - } + if tt.wantMax != snap.Max() { + t.Fatalf("%d: max: got %d, want %d", ind, snap.Max(), tt.wantMax) } if tt.wantMean != snap.Mean() {