Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelogs/unreleased/9934-amarkdotdev
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add velero_build_info metric exposing the Velero version, git SHA, git tree state, and Go runtime details
13 changes: 13 additions & 0 deletions pkg/cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"net/http"
"net/http/pprof"
"os"
goruntime "runtime"
"strings"
"time"

Expand Down Expand Up @@ -560,6 +561,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string
}()
s.metrics = metrics.NewServerMetrics()
s.metrics.RegisterAllMetrics()
registerBuildInfo(s.metrics)
// Initialize manual backup metrics
s.metrics.InitSchedule("")

Expand Down Expand Up @@ -1204,3 +1206,14 @@ func markPodVolumeRestoresCancel(ctx context.Context, client ctrlclient.Client,
}
}
}

func registerBuildInfo(m *metrics.ServerMetrics) {
m.RegisterBuildInfo(
buildinfo.Version,
buildinfo.GitSHA,
buildinfo.GitTreeState,
goruntime.Version(),
goruntime.GOOS,
goruntime.GOARCH,
)
}
32 changes: 32 additions & 0 deletions pkg/cmd/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/client_golang/prometheus"
corev1api "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand All @@ -34,10 +36,12 @@ import (
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerov2alpha1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
"github.com/vmware-tanzu/velero/pkg/builder"
"github.com/vmware-tanzu/velero/pkg/buildinfo"
"github.com/vmware-tanzu/velero/pkg/client/mocks"
"github.com/vmware-tanzu/velero/pkg/cmd/server/config"
"github.com/vmware-tanzu/velero/pkg/constant"
discovery_mocks "github.com/vmware-tanzu/velero/pkg/discovery/mocks"
"github.com/vmware-tanzu/velero/pkg/metrics"
velerotest "github.com/vmware-tanzu/velero/pkg/test"
"github.com/vmware-tanzu/velero/pkg/uploader"
)
Expand Down Expand Up @@ -448,3 +452,31 @@ func Test_setDefaultBackupLocation(t *testing.T) {
err = setDefaultBackupLocation(t.Context(), c, "velero", "default", logrus.New())
assert.NoError(t, err)
}

func TestRegisterBuildInfo(t *testing.T) {
m := metrics.NewServerMetrics()
m.RegisterAllMetrics()
registerBuildInfo(m)

ch := make(chan prometheus.Metric, 1)
m.Metrics()["build_info"].(*prometheus.GaugeVec).Collect(ch)
close(ch)

var found bool
for metric := range ch {
dtoMetric := &dto.Metric{}
require.NoError(t, metric.Write(dtoMetric))
if dtoMetric.GetGauge().GetValue() != 1 {
continue
}
labels := map[string]string{}
for _, label := range dtoMetric.Label {
labels[label.GetName()] = label.GetValue()
}
assert.Equal(t, buildinfo.Version, labels["version"])
assert.Equal(t, buildinfo.GitSHA, labels["git_commit"])
assert.Equal(t, buildinfo.GitTreeState, labels["git_tree_state"])
found = true
}
require.True(t, found, "build_info metric not found")
}
16 changes: 16 additions & 0 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const (
// Each completed job's duration is recorded in the appropriate bucket, allowing
// analysis of individual job performance and trending over time.
repoMaintenanceDurationSeconds = "repo_maintenance_duration_seconds"
buildInfo = "build_info"

// Labels
nodeMetricLabel = "node"
Expand Down Expand Up @@ -393,6 +394,14 @@ func NewServerMetrics() *ServerMetrics {
},
[]string{repositoryNameLabel},
),
buildInfo: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: metricNamespace,
Name: buildInfo,
Help: "A metric with a constant '1' value labeled with Velero build information.",
},
[]string{"version", "git_commit", "git_tree_state", "go_version", "goos", "goarch"},
),
},
}
}
Expand Down Expand Up @@ -502,6 +511,13 @@ func (m *ServerMetrics) RegisterAllMetrics() {
}
}

// RegisterBuildInfo records static build information for the Velero server.
func (m *ServerMetrics) RegisterBuildInfo(version, gitCommit, gitTreeState, goVersion, goos, goarch string) {
if g, ok := m.metrics[buildInfo].(*prometheus.GaugeVec); ok {
g.WithLabelValues(version, gitCommit, gitTreeState, goVersion, goos, goarch).Set(1)
}
}

// InitSchedule initializes counter metrics of a schedule.
func (m *ServerMetrics) InitSchedule(scheduleName string) {
if c, ok := m.metrics[backupAttemptTotal].(*prometheus.CounterVec); ok {
Expand Down
32 changes: 32 additions & 0 deletions pkg/metrics/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -601,3 +601,35 @@ func getMaintenanceHistogramCount(t *testing.T, vec *prometheus.HistogramVec, re
t.Fatalf("Histogram with repository_name label '%s' not found", repositoryName)
return 0
}

func TestRegisterBuildInfo(t *testing.T) {
m := NewServerMetrics()
m.RegisterBuildInfo("v1.13.0", "abc123", "clean", "go1.22.0", "linux", "amd64")

ch := make(chan prometheus.Metric, 1)
m.metrics[buildInfo].(*prometheus.GaugeVec).Collect(ch)
close(ch)

var found bool
for metric := range ch {
dtoMetric := &dto.Metric{}
require.NoError(t, metric.Write(dtoMetric))
if dtoMetric.GetGauge().GetValue() != 1 {
continue
}
labels := map[string]string{}
for _, label := range dtoMetric.Label {
labels[label.GetName()] = label.GetValue()
}
assert.Equal(t, map[string]string{
"version": "v1.13.0",
"git_commit": "abc123",
"git_tree_state": "clean",
"go_version": "go1.22.0",
"goos": "linux",
"goarch": "amd64",
}, labels)
found = true
}
require.True(t, found, "build_info metric not found")
}