diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-16 10:22:48 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-16 10:22:48 +0300 |
| commit | 4371aa94b0793c70a3e146fad6398f0dcb540048 (patch) | |
| tree | c7a4e1fd6726927d3344dace8d38cda7efef706d /internal/daemon/metrics.go | |
| parent | ee8221e6c88640dba31c69c59c19e65a8dc54a3e (diff) | |
Release 0.5.1: auto-unexclude, merge excluded_host into auth DB0.5.1
- /metrics: auto-remove exclusion when records mtime > excluded_at so
hosts that resume uploading unexclude themselves on next scrape
- Consolidate excluded_host table into the auth DB (goprecords-auth.db)
instead of a separate file — removes -db daemon flag and GOPRECORDS_DB env
- README: add host exclusion section with kubectl exec examples
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/daemon/metrics.go')
| -rw-r--r-- | internal/daemon/metrics.go | 83 |
1 files changed, 57 insertions, 26 deletions
diff --git a/internal/daemon/metrics.go b/internal/daemon/metrics.go index 192db77..21701db 100644 --- a/internal/daemon/metrics.go +++ b/internal/daemon/metrics.go @@ -35,7 +35,11 @@ func buildMetrics(ctx context.Context, statsDir, dbPath string) ([]byte, error) if err != nil { return nil, fmt.Errorf("list records: %w", err) } - excluded, err := loadExcludedSet(ctx, dbPath) + db := openMetricsDB(ctx, dbPath) + if db != nil { + defer db.Close() + } + excluded, err := loadExcludedMap(ctx, db) if err != nil { return nil, fmt.Errorf("load excluded hosts: %w", err) } @@ -46,12 +50,63 @@ func buildMetrics(ctx context.Context, statsDir, dbPath string) ([]byte, error) if err != nil { continue } - isExcluded := excluded[e.Host] + isExcluded := resolveExcluded(ctx, db, e.Host, mtime, excluded) writeHostMetric(&sb, e.Host, mtime, isExcluded) } return []byte(sb.String()), nil } +// openMetricsDB opens (and schema-initialises) the SQLite DB at dbPath. +// Returns nil silently on empty path or any open/schema error so the metrics +// endpoint degrades gracefully when no DB is configured. +func openMetricsDB(ctx context.Context, dbPath string) *sql.DB { + if dbPath == "" { + return nil + } + db, err := storage.Open(ctx, dbPath) + if err != nil { + return nil + } + if err := storage.CreateSchema(ctx, db); err != nil { + db.Close() + return nil + } + return db +} + +// loadExcludedMap returns a map of host→excluded_at for all excluded hosts. +func loadExcludedMap(ctx context.Context, db *sql.DB) (map[string]int64, error) { + if db == nil { + return map[string]int64{}, nil + } + hosts, err := storage.LoadExcludedHosts(ctx, db) + if err != nil { + return nil, err + } + m := make(map[string]int64, len(hosts)) + for _, h := range hosts { + m[h.Host] = h.ExcludedAt + } + return m, nil +} + +// resolveExcluded returns true if the host is currently excluded. +// If the records file mtime is newer than excluded_at the exclusion is +// automatically lifted in the DB and the host is treated as active again. +func resolveExcluded(ctx context.Context, db *sql.DB, host string, mtime int64, excluded map[string]int64) bool { + excludedAt, isExcluded := excluded[host] + if !isExcluded { + return false + } + if mtime > excludedAt { + if db != nil { + _ = storage.RemoveExcludedHost(ctx, db, host) + } + return false + } + return true +} + func writeMetricHeader(sb *strings.Builder) { sb.WriteString("# HELP goprecords_host_records_last_update_timestamp_seconds Unix timestamp of the last records file update for each host.\n") sb.WriteString("# TYPE goprecords_host_records_last_update_timestamp_seconds gauge\n") @@ -74,27 +129,3 @@ func recordsMtime(statsDir, host string) (int64, error) { } return fi.ModTime().Unix(), nil } - -func loadExcludedSet(ctx context.Context, dbPath string) (map[string]bool, error) { - if dbPath == "" { - return map[string]bool{}, nil - } - db, err := storage.Open(ctx, dbPath) - if err != nil { - return map[string]bool{}, nil - } - defer db.Close() - return loadExcludedHosts(ctx, db) -} - -func loadExcludedHosts(ctx context.Context, db *sql.DB) (map[string]bool, error) { - hosts, err := storage.LoadExcludedHosts(ctx, db) - if err != nil { - return nil, err - } - set := make(map[string]bool, len(hosts)) - for _, h := range hosts { - set[h.Host] = true - } - return set, nil -} |
