feat: add coder_build_info metric (#24365)

_Disclaimer: produced by Claude Opus 4.6_

Adds a `coder_build_info` metric which allows operators to see which
versions of Coder are currently running.

---------

Signed-off-by: Danny Kopping <danny@coder.com>
This commit is contained in:
Danny Kopping
2026-04-15 12:48:38 +00:00
committed by GitHub
parent d0c9571f62
commit 48b90f8cc8
6 changed files with 58 additions and 4 deletions
@@ -710,6 +710,24 @@ func Experiments(registerer prometheus.Registerer, active codersdk.Experiments)
return nil
}
// BuildInfo registers a gauge which is always set to 1, with labels
// describing the running server version. This follows the common
// pattern used by Prometheus itself and many Go services.
func BuildInfo(registerer prometheus.Registerer, version, revision string) error {
gauge := prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: "coderd",
Name: "build_info",
Help: "Describes the current build/version of the Coder server. Value is always 1.",
}, []string{"version", "revision"})
if err := registerer.Register(gauge); err != nil {
return err
}
gauge.WithLabelValues(version, revision).Set(1)
return nil
}
// filterAcceptableAgentLabels handles a slightly messy situation whereby `prometheus-aggregate-agent-stats-by` can control on
// which labels agent stats are aggregated, but for these specific metrics in this file there is no `template` label value,
// and therefore we have to exclude it from the list of acceptable labels.
@@ -906,6 +906,33 @@ func TestExperimentsMetric(t *testing.T) {
}
}
func TestBuildInfo(t *testing.T) {
t.Parallel()
reg := prometheus.NewRegistry()
version := "v2.15.0+abc1234"
revision := "abc1234def5678"
require.NoError(t, prometheusmetrics.BuildInfo(reg, version, revision))
out, err := reg.Gather()
require.NoError(t, err)
require.Len(t, out, 1)
require.Equal(t, "coderd_build_info", out[0].GetName())
metrics := out[0].GetMetric()
require.Len(t, metrics, 1)
// Labels are sorted alphabetically by Prometheus.
labels := metrics[0].GetLabel()
require.Len(t, labels, 2)
require.Equal(t, "revision", labels[0].GetName())
require.Equal(t, revision, labels[0].GetValue())
require.Equal(t, "version", labels[1].GetName())
require.Equal(t, version, labels[1].GetValue())
require.Equal(t, float64(1), metrics[0].GetGauge().GetValue())
}
func prepareWorkspaceAndAgent(ctx context.Context, t *testing.T, client *codersdk.Client, user codersdk.CreateFirstUserResponse, workspaceNum int) agentproto.DRPCAgentClient {
authToken := uuid.NewString()