From 5794ca8431785cf1fd3a46004d0d13b3ed075016 Mon Sep 17 00:00:00 2001 From: Nicholas Wiersma Date: Tue, 7 May 2019 07:14:34 +0200 Subject: [PATCH] Added heartbeat stat (#6) --- stats/aggregate_test.go | 12 +++--------- stats/heartbeat.go | 26 ++++++++++++++++++++++++++ stats/heartbeat_test.go | 33 +++++++++++++++++++++++++++++++++ stats/runtime_test.go | 2 +- 4 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 stats/heartbeat.go create mode 100644 stats/heartbeat_test.go diff --git a/stats/aggregate_test.go b/stats/aggregate_test.go index c142464..49e786c 100644 --- a/stats/aggregate_test.go +++ b/stats/aggregate_test.go @@ -71,15 +71,13 @@ func TestAggregateStatter_Inc(t *testing.T) { m.On("Close").Return(nil) s := stats.NewAggregateStatter(m, time.Millisecond) - time.Sleep(time.Millisecond) - s.Inc("test", 1, 1.0, "foo", "bar") s.Inc("test", 1, 1.0, "foo", "bar") s.Inc("test1", 1, 1.0, "foo", "bar") s.Inc("test", 1, 1.0, "foo1", "bar") s.Inc("rate", 1, 0.1) - time.Sleep(2 * time.Millisecond) + time.Sleep(10 * time.Millisecond) _ = s.Close() @@ -94,14 +92,12 @@ func TestAggregateStatter_Gauge(t *testing.T) { m.On("Close").Return(nil) s := stats.NewAggregateStatter(m, time.Millisecond) - time.Sleep(time.Millisecond) - s.Gauge("test", 1, 1.0, "foo", "bar") s.Gauge("test", 3, 1.0, "foo", "bar") s.Gauge("test1", 4, 1.0, "foo", "bar") s.Gauge("test", 5, 1.0, "foo1", "bar") - time.Sleep(2 * time.Millisecond) + time.Sleep(10 * time.Millisecond) _ = s.Close() @@ -117,15 +113,13 @@ func TestAggregateStatter_Timing(t *testing.T) { m.On("Close").Return(nil) s := stats.NewAggregateStatter(m, time.Millisecond) - time.Sleep(time.Millisecond) - s.Timing("test", time.Millisecond, 1.0, "foo", "bar") s.Timing("test", time.Second, 1.0, "foo", "bar") s.Timing("test1", time.Millisecond, 1.0, "foo", "bar") s.Timing("test", time.Millisecond, 1.0, "foo1", "bar") s.Timing("rate", time.Millisecond, 0.1) - time.Sleep(2 * time.Millisecond) + time.Sleep(10 * time.Millisecond) _ = s.Close() diff --git a/stats/heartbeat.go b/stats/heartbeat.go new file mode 100644 index 0000000..c5a5e44 --- /dev/null +++ b/stats/heartbeat.go @@ -0,0 +1,26 @@ +package stats + +import ( + "time" +) + +// DefaultHeartbeatInterval is the default heartbeat ticker interval. +var DefaultHeartbeatInterval = time.Second + +// Heartbeat enters a loop, reporting a heartbeat counter periodically. +func Heartbeat(stats Statter) { + HeartbeatEvery(stats, DefaultHeartbeatInterval) +} + +// HeartbeatEvery enters a loop, reporting a heartbeat counter at the specified interval. +func HeartbeatEvery(stats Statter, t time.Duration) { + c := time.Tick(t) + for range c { + stats.Inc("heartbeat", 1, 1.0) + } +} + +// HeartbeatFromStatable is the same as HeartbeatEvery but from context. +func HeartbeatFromStatable(sable Statable, t time.Duration) { + HeartbeatEvery(sable.Statter(), t) +} diff --git a/stats/heartbeat_test.go b/stats/heartbeat_test.go new file mode 100644 index 0000000..471b5d5 --- /dev/null +++ b/stats/heartbeat_test.go @@ -0,0 +1,33 @@ +package stats_test + +import ( + "testing" + "time" + + "github.com/hamba/pkg/stats" + "github.com/stretchr/testify/mock" +) + +func TestHeartbeat(t *testing.T) { + m := new(MockStats) + m.On("Inc", "heartbeat", int64(1), float32(1.0), mock.Anything).Return(nil) + stats.DefaultHeartbeatInterval = time.Millisecond + + go stats.Heartbeat(m) + + time.Sleep(100 * time.Millisecond) + + m.AssertCalled(t, "Inc", "heartbeat", int64(1), float32(1.0), mock.Anything) +} + +func TestHeartbeatFromStatable(t *testing.T) { + m := new(MockStats) + m.On("Inc", "heartbeat", int64(1), float32(1.0), mock.Anything).Return(nil) + sable := stats.NewMockStatable(m) + + go stats.HeartbeatFromStatable(sable, time.Millisecond) + + time.Sleep(100 * time.Millisecond) + + m.AssertCalled(t, "Inc", "heartbeat", int64(1), float32(1.0), mock.Anything) +} diff --git a/stats/runtime_test.go b/stats/runtime_test.go index 22e4e3e..aa7b31f 100755 --- a/stats/runtime_test.go +++ b/stats/runtime_test.go @@ -21,7 +21,7 @@ func TestRuntime(t *testing.T) { m.AssertCalled(t, "Gauge", "runtime.cpu.goroutines", mock.Anything, mock.Anything, mock.Anything) } -func TestRuntimeFromContext(t *testing.T) { +func TestRuntimeFromStatable(t *testing.T) { m := new(MockStats) m.On("Gauge", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) m.On("Timing", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)