6
"github.com/rcrowley/go-metrics"
10
movingWindowSize = 1028
13
// movingWindowSample is sample using moving window reservoir to keep selection of stream values.
14
type movingWindowSample struct {
22
func newMovingWindowSample() metrics.Sample {
23
if metrics.UseNilMetrics {
24
return metrics.NilSample{}
27
return &movingWindowSample{
28
buffer: make([]int64, movingWindowSize),
29
size: movingWindowSize,
33
// Clear clears all sample
34
func (mw *movingWindowSample) Clear() {
36
defer mw.lock.Unlock()
43
// Count returns the number of samples recorded, which may exceed the reservoir size.
44
func (mw *movingWindowSample) Count() int64 {
46
defer mw.lock.RUnlock()
50
// Max returns the maximum value in the sample.
51
func (mw *movingWindowSample) Max() int64 {
52
return metrics.SampleMax(mw.Values())
55
// Mean returns the mean of the values in the sample.
56
func (mw *movingWindowSample) Mean() float64 {
57
return metrics.SampleMean(mw.Values())
60
// Min returns the minimum value in the sample
61
func (mw *movingWindowSample) Min() int64 {
62
return metrics.SampleMin(mw.Values())
65
// Percentile returns an arbitrary percentile of values in the sample.
66
func (mw *movingWindowSample) Percentile(p float64) float64 {
67
return metrics.SamplePercentile(mw.Values(), p)
70
// Percentiles returns a slice of arbitrary percentiles of values in the sample.
71
func (mw *movingWindowSample) Percentiles(ps []float64) []float64 {
72
return metrics.SamplePercentiles(mw.Values(), ps)
75
// Size returns the size of the sample, which is at most the reservoir size.
76
func (mw *movingWindowSample) Size() int {
78
defer mw.lock.RUnlock()
87
// Snapshot returns a read-only copy of the sample.
88
func (mw *movingWindowSample) Snapshot() metrics.Sample {
90
defer mw.lock.RUnlock()
92
return metrics.NewSampleSnapshot(mw.count, mw.Values())
95
// StdDev returns the standard deviation of the values in the sample.
96
func (mw *movingWindowSample) StdDev() float64 {
97
return metrics.SampleStdDev(mw.Values())
100
// Sum returns the sum of the values in the sample.
101
func (mw *movingWindowSample) Sum() int64 {
102
return metrics.SampleSum(mw.Values())
105
// Update samples a new value.
106
func (mw *movingWindowSample) Update(v int64) {
108
defer mw.lock.Unlock()
110
mw.buffer[mw.index] = v
113
if mw.index == mw.size {
119
// Values returns a copy of the values in the sample.
120
func (mw *movingWindowSample) Values() []int64 {
122
defer mw.lock.RUnlock()
124
values := make([]int64, mw.size)
126
// buffer has been overflow, so window's values consist of 2 parts:
127
// from current position (included) to the end of buffer and from the beginning of buffer to current position (excluded)
128
// e.g.: [7, 8, 3, 4, 5, 6], current position = 3, values are [3, 4, 5, 6, 7, 8]
129
copied := copy(values, mw.buffer[mw.index:])
130
if copied < mw.size {
131
copy(values[copied:], mw.buffer[:mw.index])
134
// buffer hasn't been overflown, so window's values is slice from beginning of buffer to current position (latter is excluded)
135
// e.g.: [1, 2, 3, 4, 0, 0], current position = 4, values are [1, 2, 3, 4, 0, 0]
136
copy(values, mw.buffer[0:mw.index])
141
// Variance returns the variance of the values in the sample.
142
func (mw *movingWindowSample) Variance() float64 {
143
return metrics.SampleVariance(mw.Values())