From 4bffea4f107e21cc48498f8974d5142bb3f0cac7 Mon Sep 17 00:00:00 2001 From: Knut Ahlers Date: Tue, 24 Jul 2018 13:36:12 +0200 Subject: [PATCH] Fix: Limit historical performance data in order not to consume an endless amount of memory Signed-off-by: Knut Ahlers --- .gitignore | 1 + main.go | 18 ++++++++++++------ ring.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 ring.go diff --git a/.gitignore b/.gitignore index fdeda75..f556e37 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ request-log +webcheck diff --git a/main.go b/main.go index 68f9efb..ea62e1b 100644 --- a/main.go +++ b/main.go @@ -19,7 +19,10 @@ import ( log "github.com/sirupsen/logrus" ) -const dateFormat = time.RFC1123 +const ( + dateFormat = time.RFC1123 + numHistoricalDurations = 300 +) var ( cfg = struct { @@ -54,7 +57,7 @@ const ( type checkResult struct { DumpFile string - Durations []time.Duration + Durations *ringDuration Message string Start time.Time Status checkStatus @@ -64,8 +67,11 @@ type checkResult struct { } func newCheckResult(status checkStatus, message string, duration time.Duration) *checkResult { + r := newRingDuration(numHistoricalDurations) + r.SetNext(duration) + return &checkResult{ - Durations: []time.Duration{duration}, + Durations: r, Message: message, Start: time.Now(), Status: status, @@ -76,7 +82,7 @@ func (c *checkResult) AddDuration(d time.Duration) { c.lock.Lock() defer c.lock.Unlock() - c.Durations = append(c.Durations, d) + c.Durations.SetNext(d) } func (c *checkResult) DurationStats() string { @@ -84,7 +90,7 @@ func (c *checkResult) DurationStats() string { defer c.lock.RUnlock() var ( - s = stats.LoadRawData(c.Durations) + s = stats.LoadRawData(c.Durations.GetAll()) min, avg, max float64 err error ) @@ -176,7 +182,7 @@ func main() { lastResult.DumpFile = fn } } else { - lastResult.AddDuration(result.Durations[0]) + lastResult.AddDuration(result.Durations.GetCurrent()) } lastResult.Print() diff --git a/ring.go b/ring.go new file mode 100644 index 0000000..fa51a02 --- /dev/null +++ b/ring.go @@ -0,0 +1,51 @@ +package main + +import ( + "sync" + "time" +) + +type ringDuration struct { + store []time.Duration + current int + + lock sync.RWMutex +} + +func newRingDuration(maxLen int) *ringDuration { + return &ringDuration{ + store: make([]time.Duration, 0, maxLen), + current: -1, // Initial value to start the ring with element 0 + } +} + +func (r *ringDuration) SetNext(i time.Duration) { + r.lock.Lock() + defer r.lock.Unlock() + + next := r.current + 1 + if next == cap(r.store) { + next = 0 + } + + if next == len(r.store) { + r.store = append(r.store, 0) + } + + r.store[next] = i + r.current = next +} + +func (r *ringDuration) GetAll() []time.Duration { + r.lock.RLock() + defer r.lock.RUnlock() + + return r.store +} + +func (r *ringDuration) GetCurrent() time.Duration { + r.lock.RLock() + defer r.lock.RUnlock() + + return r.store[r.current] +}