Skip to content

Commit 59f6e49

Browse files
committed
SD-11577: decouple kv namespace from scrape interval
1 parent ddc5fc5 commit 59f6e49

File tree

3 files changed

+46
-5
lines changed

3 files changed

+46
-5
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ The exporter can be configured using env variables or command flags.
6767
| `SCRAPE_DELAY` | scrape delay in seconds, default `300` |
6868
| `SCRAPE_INTERVAL` | scrape interval in seconds (will query cloudflare every SCRAPE_INTERVAL seconds), default `60` |
6969
| `METRICS_DENYLIST` | (Optional) cloudflare-exporter metrics to not export, comma delimited list of cloudflare-exporter metrics. If not set, all metrics are exported |
70+
| `KV_CACHE_INTERVAL` | (Optional) KV namespace cache refresh interval, default `5m` |
7071
| `ENABLE_PPROF` | (Optional) enable pprof profiling endpoints at `/debug/pprof/`. Accepts `true` or `false`, default `false`. **Warning**: Only enable in development/debugging environments |
7172
| `ZONE_<NAME>` | `DEPRECATED since 0.0.5` (optional) Zone ID. Add zones you want to scrape by adding env vars in this format. You can find the zone ids in Cloudflare dashboards. |
7273
| `LOG_LEVEL` | Set loglevel. Options are error, warn, info, debug. default `error` |
@@ -85,6 +86,7 @@ Corresponding flags:
8586
-metrics_path="/metrics": path for metrics, default /metrics
8687
-scrape_delay=300: scrape delay in seconds, defaults to 300
8788
-scrape_interval=60: scrape interval in seconds, defaults to 60
89+
-kv_cache_interval="5m": KV namespace cache refresh interval, default 5 minutes
8890
-metrics_denylist="": cloudflare-exporter metrics to not export, comma delimited list
8991
-enable_pprof=false: enable pprof profiling endpoints at /debug/pprof/
9092
-log_level="error": log level(error,warn,info,debug)

main.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"runtime"
88
"strings"
99
"sync"
10+
"sync/atomic"
1011
"time"
1112

1213
"github.com/nelkinda/health-go"
@@ -25,6 +26,10 @@ var (
2526
cftimeout time.Duration
2627
gql *GraphQL
2728
log = logrus.New()
29+
30+
// kvNamespaceCache stores accountID -> namespaceID -> name.
31+
// Atomically replaced by refreshKVNamespaceCache, read by getKVNamespaceMap.
32+
kvNamespaceCache atomic.Pointer[map[string]map[string]string]
2833
)
2934

3035
// var (
@@ -151,6 +156,30 @@ func fetchMetrics(deniedMetricsSet MetricsSet) {
151156
wg.Wait()
152157
}
153158

159+
func refreshKVNamespaceCache() {
160+
accounts := fetchAccounts()
161+
newCache := make(map[string]map[string]string, len(accounts))
162+
for _, a := range accounts {
163+
nsMap, err := fetchKVNamespaces(a.ID)
164+
if err != nil {
165+
log.Warnf("failed to refresh KV namespace cache for account %s: %v", a.ID, err)
166+
continue
167+
}
168+
newCache[a.ID] = nsMap
169+
}
170+
171+
kvNamespaceCache.Store(&newCache)
172+
log.Info("KV namespace cache refreshed")
173+
}
174+
175+
func getKVNamespaceMap(accountID string) map[string]string {
176+
cache := kvNamespaceCache.Load()
177+
if cache == nil {
178+
return nil
179+
}
180+
return (*cache)[accountID]
181+
}
182+
154183
func runExporter() {
155184
cfgMetricsPath := viper.GetString("metrics_path")
156185

@@ -174,6 +203,16 @@ func runExporter() {
174203
log.Debugf("Metrics set: %v", metricsSet)
175204
mustRegisterMetrics(metricsSet)
176205

206+
// Populate KV namespace cache at boot, then refresh on interval.
207+
refreshKVNamespaceCache()
208+
kvCacheInterval := viper.GetDuration("kv_cache_interval")
209+
log.Info("KV namespace cache refresh interval set to ", kvCacheInterval)
210+
go func() {
211+
for range time.NewTicker(kvCacheInterval).C {
212+
refreshKVNamespaceCache()
213+
}
214+
}()
215+
177216
scrapeInterval := time.Duration(viper.GetInt("scrape_interval")) * time.Second
178217
log.Info("Scrape interval set to ", scrapeInterval)
179218

@@ -257,6 +296,10 @@ func main() {
257296
viper.BindEnv("cf_timeout")
258297
viper.SetDefault("cf_timeout", 10*time.Second)
259298

299+
flags.Duration("kv_cache_interval", 5*time.Minute, "KV namespace cache refresh interval, default 5 minutes")
300+
viper.BindEnv("kv_cache_interval")
301+
viper.SetDefault("kv_cache_interval", 5*time.Minute)
302+
260303
flags.String("metrics_denylist", "", "metrics to not expose, comma delimited list")
261304
viper.BindEnv("metrics_denylist")
262305
viper.SetDefault("metrics_denylist", "")

prometheus.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -631,11 +631,7 @@ func fetchKVAnalytics(account cfaccounts.Account, wg *sync.WaitGroup, deniedMetr
631631
wg.Add(1)
632632
defer wg.Done()
633633

634-
namespaceMap, err := fetchKVNamespaces(account.ID)
635-
if err != nil {
636-
log.Error("failed to fetch KV namespaces for account ", account.ID, ": ", err)
637-
return
638-
}
634+
namespaceMap := getKVNamespaceMap(account.ID)
639635

640636
r, err := fetchKVOperations(account.ID)
641637
if err != nil {

0 commit comments

Comments
 (0)