From 265cbd5abfbdd4feb725daace4a0f188c0dd5224 Mon Sep 17 00:00:00 2001 From: Adora Laura Kalb Date: Fri, 19 Apr 2024 11:40:05 +0200 Subject: [PATCH] add caching functionality --- cache/cache.go | 2 +- cache/cache_test.go | 4 ++-- collector/collector.go | 30 +++++++++++++++++++++++++----- helpers/helpers.go | 25 +++++++++++++++++++++++++ main.go | 3 +++ models/api_response.go | 8 ++++---- 6 files changed, 60 insertions(+), 12 deletions(-) create mode 100644 helpers/helpers.go diff --git a/cache/cache.go b/cache/cache.go index 6d0b9bd..dfd64d8 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -50,7 +50,7 @@ func newCacheMissError() *CacheMissError { return &CacheMissError{} } -func NewLocalCache() *ScoreCache { +func NewScoreCache() *ScoreCache { lc := &ScoreCache{ scores: make(map[netip.Addr]ServerScore), stop: make(chan struct{}), diff --git a/cache/cache_test.go b/cache/cache_test.go index 254b5d3..e5f1e96 100644 --- a/cache/cache_test.go +++ b/cache/cache_test.go @@ -24,7 +24,7 @@ import ( func TestCacheGet(t *testing.T) { const testFloat = 1.23456 - cache := NewLocalCache() + cache := NewScoreCache() cache.Add(testFloat, netip.MustParseAddr("1.2.3.4"), time.Now().Add(5*time.Minute)) score, _ := cache.Get(netip.MustParseAddr("1.2.3.4")) @@ -39,7 +39,7 @@ func TestCacheMiss(t *testing.T) { expiredTime := now.Add(-(time.Minute * 10)) - cache := NewLocalCache() + cache := NewScoreCache() cache.Add(testFloat, netip.MustParseAddr("1.2.3.4"), expiredTime) _, err := cache.Get(netip.MustParseAddr("1.2.3.4")) diff --git a/collector/collector.go b/collector/collector.go index 7a332e4..77ef95d 100644 --- a/collector/collector.go +++ b/collector/collector.go @@ -27,6 +27,7 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" + "golang.adora.codes/ntppool-exporter/cache" "golang.adora.codes/ntppool-exporter/models" ) @@ -61,7 +62,24 @@ func (c Collector) Collect(ch chan<- prometheus.Metric) { } func (c Collector) collect(ch chan<- prometheus.Metric, logger log.Logger) { - httpError := false + score, err := cache.GlobalScoreCache.Get(c.target) + if err == nil { + level.Debug(logger).Log("msg", "Serving score from cache", + "server", c.target.String(), "score", score.Score) + + serverScoreMetric := prometheus.NewDesc("ntppool_server_score", + "Shows the server score currently assigned at ntppool.org", + nil, nil) + + m1 := prometheus.MustNewConstMetric(serverScoreMetric, prometheus.GaugeValue, score.Score) + m1 = prometheus.NewMetricWithTimestamp(time.Now(), m1) + ch <- m1 + return + } + + level.Debug(logger).Log("msg", "Cache miss, querying API", + "server", c.target.String()) + var serverApiScore float64 = 0 const apiEndpoint = "https://www.ntppool.org/scores/" const apiQuery = "/json?limit=1&monitor=24" @@ -73,7 +91,7 @@ func (c Collector) collect(ch chan<- prometheus.Metric, logger log.Logger) { if err != nil { level.Error(logger).Log("msg", "Error sending HTTP request", "url", url, "message", err) - httpError = true + return } res, err := client.Do(req) if err != nil { @@ -97,9 +115,11 @@ func (c Collector) collect(ch chan<- prometheus.Metric, logger log.Logger) { return } - if !httpError { - serverApiScore = response.History[0].Score - } + serverApiScore = response.History[0].Score + + cache.GlobalScoreCache.Add(serverApiScore, c.target, time.Now()) + level.Debug(logger).Log("msg", "Added score to cache", + "server", c.target.String(), "score", score.Score) // TODO: Test or delete serverScoreMetric := prometheus.NewDesc("ntppool_server_score", diff --git a/helpers/helpers.go b/helpers/helpers.go new file mode 100644 index 0000000..98ccb04 --- /dev/null +++ b/helpers/helpers.go @@ -0,0 +1,25 @@ +/* +Copyright 2024 Adora Laura Kalb + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package helpers + +import ( + "time" +) + +func UnixToTime(i int64) time.Time { + return time.Unix(i, 0) +} diff --git a/main.go b/main.go index ac10d7f..07b6f58 100644 --- a/main.go +++ b/main.go @@ -33,6 +33,7 @@ import ( "github.com/prometheus/common/version" "github.com/prometheus/exporter-toolkit/web" webflag "github.com/prometheus/exporter-toolkit/web/kingpinflag" + "golang.adora.codes/ntppool-exporter/cache" "golang.adora.codes/ntppool-exporter/collector" ) @@ -95,6 +96,8 @@ func main() { kingpin.Parse() logger := promlog.New(promlogConfig) + cache.GlobalScoreCache = cache.NewScoreCache() + level.Info(logger).Log("msg", "Starting ntppool_exporter", "version", version.Info()) level.Info(logger).Log("build_context", version.BuildContext()) diff --git a/models/api_response.go b/models/api_response.go index 3dcd88d..014ee77 100644 --- a/models/api_response.go +++ b/models/api_response.go @@ -34,8 +34,8 @@ type ApiResponse struct { } type ApiResponseHistory struct { - Timestamp int `json:"ts"` - Step int `json:"step"` - Score float64 `json:"score"` - MonitorID int `json:"monitor_id"` + TimestampInt int64 `json:"ts"` + Step int `json:"step"` + Score float64 `json:"score"` + MonitorID int `json:"monitor_id"` }