From b6a101cdfe327b839ced7cfc626c6bd78201ff0f Mon Sep 17 00:00:00 2001 From: Tom Clegg Date: Fri, 8 Apr 2022 16:05:26 -0400 Subject: [PATCH] 18794: Export config timestamp/hash as prometheus metric. Arvados-DCO-1.1-Signed-off-by: Tom Clegg --- lib/config/load.go | 19 +++++++++++++++++++ lib/config/load_test.go | 12 ++++++++++++ lib/service/cmd.go | 2 ++ 3 files changed, 33 insertions(+) diff --git a/lib/config/load.go b/lib/config/load.go index 28f300e3bb..d03ef5388d 100644 --- a/lib/config/load.go +++ b/lib/config/load.go @@ -6,6 +6,7 @@ package config import ( "bytes" + "crypto/sha256" _ "embed" "encoding/json" "errors" @@ -22,6 +23,7 @@ import ( "git.arvados.org/arvados.git/sdk/go/arvados" "github.com/ghodss/yaml" "github.com/imdario/mergo" + "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" ) @@ -569,3 +571,20 @@ func (ldr *Loader) autofillPreemptible(label string, cc *arvados.Cluster) { } } + +// RegisterMetrics registers metrics showing the timestamp and content +// hash of the currently loaded config. +// +// Must not be called more than once for a given registry. Must not be +// called before Load(). Metrics are not updated by subsequent calls +// to Load(). +func (ldr *Loader) RegisterMetrics(reg *prometheus.Registry) { + vec := prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: "arvados", + Subsystem: "config", + Name: "source_timestamp_seconds", + Help: "Timestamp of config file when it was loaded.", + }, []string{"sha256"}) + vec.WithLabelValues(fmt.Sprintf("%x", sha256.Sum256(ldr.configdata))).Set(float64(ldr.sourceTimestamp.UnixNano()) / 1e9) + reg.MustRegister(vec) +} diff --git a/lib/config/load_test.go b/lib/config/load_test.go index cef7ea944b..b43cda38c8 100644 --- a/lib/config/load_test.go +++ b/lib/config/load_test.go @@ -20,6 +20,8 @@ import ( "git.arvados.org/arvados.git/sdk/go/arvados" "git.arvados.org/arvados.git/sdk/go/ctxlog" "github.com/ghodss/yaml" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/expfmt" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" check "gopkg.in/check.v1" @@ -798,5 +800,15 @@ func (s *LoadSuite) TestSourceTimestamp(c *check.C) { c.Assert(err, check.IsNil) c.Check(cfg.SourceTimestamp, check.Equals, cfg.SourceTimestamp.UTC()) c.Check(int(cfg.SourceTimestamp.Sub(trial.expectTime).Seconds()), check.Equals, 0) + + var buf bytes.Buffer + reg := prometheus.NewRegistry() + ldr.RegisterMetrics(reg) + enc := expfmt.NewEncoder(&buf, expfmt.FmtText) + got, _ := reg.Gather() + for _, mf := range got { + enc.Encode(mf) + } + c.Check(buf.String(), check.Matches, `# HELP .*\n# TYPE .*\narvados_config_source_timestamp_seconds{sha256="83aea5d82eb1d53372cd65c936c60acc1c6ef946e61977bbca7cfea709d201a8"} \Q`+fmt.Sprintf("%g", float64(cfg.SourceTimestamp.UnixNano())/1e9)+`\E\n`) } } diff --git a/lib/service/cmd.go b/lib/service/cmd.go index 1ed2ac1314..6f5efa5cb7 100644 --- a/lib/service/cmd.go +++ b/lib/service/cmd.go @@ -117,6 +117,8 @@ func (c *command) RunCommand(prog string, args []string, stdin io.Reader, stdout ctx = context.WithValue(ctx, contextKeyURL{}, listenURL) reg := prometheus.NewRegistry() + loader.RegisterMetrics(reg) + handler := c.newHandler(ctx, cluster, cluster.SystemRootToken, reg) if err = handler.CheckHealth(); err != nil { return 1 -- 2.30.2