Skip to content

Commit c572d91

Browse files
committed
fix timer count sampling, new flag -persist-timer-counts
by putting the sampled count first in the time values array and with new inactivTimers map also, BenchmarkManyDifferentSensors should clear the stats maps ...
1 parent 9fdc27b commit c572d91

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

statsdaemon.go

+33-3
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ var (
9797
showVersion = flag.Bool("version", false, "print version string")
9898
deleteGauges = flag.Bool("delete-gauges", true, "don't send values to graphite for inactive gauges, as opposed to sending the previous value")
9999
persistCountKeys = flag.Uint("persist-count-keys", 60, "number of flush-intervals to persist count keys (at zero)")
100+
persistTimerKeys = flag.Uint("persist-timer-counts", 0, "number of flush-intervals to persist timer count keys (at zero)")
100101
receiveCounter = flag.String("receive-counter", "", "Metric name for total metrics received per interval")
101102
percentThreshold = Percentiles{}
102103
prefix = flag.String("prefix", "", "Prefix for all stats")
@@ -116,6 +117,7 @@ var (
116117
timers = make(map[string]Float64Slice)
117118
sets = make(map[string][]string)
118119
inactivCounters = make(map[string]uint)
120+
inactivTimers = make(map[string]uint)
119121
)
120122

121123
func monitor() {
@@ -144,8 +146,14 @@ func packetHandler(s *Packet) {
144146

145147
switch s.Modifier {
146148
case "ms":
147-
// if missing gets nil []float64, works with append()
148-
timers[s.Bucket] = append(timers[s.Bucket], s.ValFlt)
149+
vals := timers[s.Bucket]
150+
if vals == nil {
151+
vals = make([]float64, 1, 5)
152+
vals[0] = 0.0
153+
}
154+
// first slot is sampled count, following are times
155+
vals[0] += float64(1 / s.Sampling)
156+
timers[s.Bucket] = append(vals, s.ValFlt)
149157
case "g":
150158
var gaugeValue float64
151159
if s.ValStr == "" {
@@ -290,8 +298,12 @@ func processSets(buffer *bytes.Buffer, now int64) int64 {
290298

291299
func processTimers(buffer *bytes.Buffer, now int64, pctls Percentiles) int64 {
292300
var num int64
301+
persist := *persistTimerKeys
302+
293303
for bucket, timer := range timers {
294304
num++
305+
sampled := timer[0]
306+
timer = timer[1:]
295307

296308
sort.Sort(timer)
297309
min := timer[0]
@@ -336,13 +348,31 @@ func processTimers(buffer *bytes.Buffer, now int64, pctls Percentiles) int64 {
336348
mean_s := strconv.FormatFloat(mean, 'f', -1, 64)
337349
max_s := strconv.FormatFloat(max, 'f', -1, 64)
338350
min_s := strconv.FormatFloat(min, 'f', -1, 64)
351+
count_s := strconv.FormatFloat(sampled, 'f', -1, 64)
339352

340353
fmt.Fprintf(buffer, "%s%s.mean%s %s %d\n", *prefix, bucket, *postfix, mean_s, now)
341354
fmt.Fprintf(buffer, "%s%s.upper%s %s %d\n", *prefix, bucket, *postfix, max_s, now)
342355
fmt.Fprintf(buffer, "%s%s.lower%s %s %d\n", *prefix, bucket, *postfix, min_s, now)
343-
fmt.Fprintf(buffer, "%s%s.count%s %d %d\n", *prefix, bucket, *postfix, count, now)
356+
fmt.Fprintf(buffer, "%s%s.count%s %s %d\n", *prefix, bucket, *postfix, count_s, now)
344357

345358
delete(timers, bucket)
359+
if persist > 0 {
360+
countKey := fmt.Sprintf("%s%s.count%s", *prefix, bucket, *postfix)
361+
inactivTimers[countKey] = 0
362+
}
363+
}
364+
365+
// continue sending zeros for no-longer-active timer counts for configured flush-intervals
366+
for bucket, purgeCount := range inactivTimers {
367+
if purgeCount > 0 {
368+
fmt.Fprintf(buffer, "%s 0 %d\n", bucket, now)
369+
num++
370+
}
371+
if purgeCount >= persist {
372+
delete(inactivTimers, bucket)
373+
} else {
374+
inactivTimers[bucket] = purgeCount + 1
375+
}
346376
}
347377
return num
348378
}

statsdaemon_test.go

+14-8
Original file line numberDiff line numberDiff line change
@@ -458,13 +458,15 @@ func TestPacketHandlerTimer(t *testing.T) {
458458
Sampling: float32(1),
459459
}
460460
packetHandler(p)
461-
assert.Equal(t, len(timers["glork"]), 1)
462-
assert.Equal(t, timers["glork"][0], float64(320))
461+
assert.Equal(t, len(timers["glork"]), 2)
462+
assert.Equal(t, timers["glork"][0], float64(1))
463+
assert.Equal(t, timers["glork"][1], float64(320))
463464

464465
p.ValFlt = float64(100)
465466
packetHandler(p)
466-
assert.Equal(t, len(timers["glork"]), 2)
467-
assert.Equal(t, timers["glork"][1], float64(100))
467+
assert.Equal(t, len(timers["glork"]), 3)
468+
assert.Equal(t, timers["glork"][0], float64(2))
469+
assert.Equal(t, timers["glork"][2], float64(100))
468470
}
469471

470472
func TestPacketHandlerSet(t *testing.T) {
@@ -545,7 +547,7 @@ func TestProcessCountersPrefix(t *testing.T) {
545547
func TestProcessTimers(t *testing.T) {
546548
// Some data with expected mean of 20
547549
timers = make(map[string]Float64Slice)
548-
timers["response_time"] = []float64{0, 30, 30}
550+
timers["response_time"] = []float64{3, 0, 30, 30}
549551

550552
now := int64(1418052649)
551553

@@ -652,7 +654,7 @@ func TestProcessSets(t *testing.T) {
652654
func TestProcessTimersUpperPercentile(t *testing.T) {
653655
// Some data with expected 75% of 2
654656
timers = make(map[string]Float64Slice)
655-
timers["response_time"] = []float64{0, 1, 2, 3}
657+
timers["response_time"] = []float64{4, 0, 1, 2, 3}
656658

657659
now := int64(1418052649)
658660

@@ -675,7 +677,7 @@ func TestProcessTimersUpperPercentilePostfix(t *testing.T) {
675677
flag.Set("postfix", ".test")
676678
// Some data with expected 75% of 2
677679
timers = make(map[string]Float64Slice)
678-
timers["postfix_response_time"] = []float64{0, 1, 2, 3}
680+
timers["postfix_response_time"] = []float64{4, 0, 1, 2, 3}
679681
now := int64(1418052649)
680682

681683
var buffer bytes.Buffer
@@ -697,7 +699,7 @@ func TestProcessTimersUpperPercentilePostfix(t *testing.T) {
697699

698700
func TestProcessTimesLowerPercentile(t *testing.T) {
699701
timers = make(map[string]Float64Slice)
700-
timers["time"] = []float64{0, 1, 2, 3}
702+
timers["time"] = []float64{4, 0, 1, 2, 3}
701703

702704
now := int64(1418052649)
703705

@@ -769,7 +771,11 @@ func TestMultipleUDPSends(t *testing.T) {
769771
}
770772

771773
func BenchmarkManyDifferentSensors(t *testing.B) {
774+
counters = make(map[string]float64)
775+
gauges = make(map[string]float64)
776+
timers = make(map[string]Float64Slice)
772777
r := rand.New(rand.NewSource(438))
778+
773779
for i := 0; i < 1000; i++ {
774780
bucket := "response_time" + strconv.Itoa(i)
775781
for i := 0; i < 10000; i++ {

0 commit comments

Comments
 (0)