Skip to content
Draft
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
20 changes: 20 additions & 0 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
package metrics

import (
"runtime"

"github.com/microsoft/retina/internal/buildinfo"
"github.com/microsoft/retina/pkg/exporter"
"github.com/microsoft/retina/pkg/log"
"github.com/microsoft/retina/pkg/utils"
Expand Down Expand Up @@ -194,6 +197,23 @@ func InitializeMetrics() {
parsedPacketsCounterDescription,
)

// Build Info metric - set to 1 with version and architecture labels
BuildInfo = exporter.CreatePrometheusGaugeVecForMetric(
exporter.DefaultRegistry,
utils.BuildInfoName,
BuildInfoDescription,
utils.BuildVersion,
utils.BuildArchitecture,
utils.BuildOS,
)
// Set the build info to 1 with the current build information
// Use "unknown" as fallback if version is not set during build
version := buildinfo.Version
if version == "" {
version = "unknown"
}
BuildInfo.WithLabelValues(version, runtime.GOARCH, runtime.GOOS).Set(1)

isInitialized = true
metricsLogger.Info("Metrics initialized")
}
Expand Down
35 changes: 34 additions & 1 deletion pkg/metrics/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
package metrics

import (
"runtime"
"testing"

"github.com/microsoft/retina/pkg/log"
dto "github.com/prometheus/client_model/go"
)

func TestInitialization_FirstInit(t *testing.T) {
Expand All @@ -15,7 +17,7 @@
InitializeMetrics()

// All metrics should be initialized.
objs := []interface{}{DropPacketsGauge, DropBytesGauge, ForwardBytesGauge, ForwardPacketsGauge, NodeConnectivityStatusGauge, NodeConnectivityLatencyGauge, PluginManagerFailedToReconcileCounter}
objs := []interface{}{DropPacketsGauge, DropBytesGauge, ForwardBytesGauge, ForwardPacketsGauge, NodeConnectivityStatusGauge, NodeConnectivityLatencyGauge, PluginManagerFailedToReconcileCounter, BuildInfo}

Check failure on line 20 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows, arm64)

The line is 205 characters long, which exceeds the maximum of 200 characters. (lll)

Check failure on line 20 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (linux, arm64)

The line is 205 characters long, which exceeds the maximum of 200 characters. (lll)

Check failure on line 20 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows, amd64)

The line is 205 characters long, which exceeds the maximum of 200 characters. (lll)

Check failure on line 20 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (linux, amd64)

The line is 205 characters long, which exceeds the maximum of 200 characters. (lll)
for _, obj := range objs {
if obj == nil {
t.Fatalf("Expected all metrics to be initialized")
Expand All @@ -35,3 +37,34 @@
// Should not panic when reinitializing.
InitializeMetrics()
}

func TestBuildInfo(t *testing.T) {
log.SetupZapLogger(log.GetDefaultLogOpts())

Check failure on line 42 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows, arm64)

Error return value of `log.SetupZapLogger` is not checked (errcheck)

Check failure on line 42 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (linux, arm64)

Error return value of `log.SetupZapLogger` is not checked (errcheck)

Check failure on line 42 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows, amd64)

Error return value of `log.SetupZapLogger` is not checked (errcheck)

Check failure on line 42 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (linux, amd64)

Error return value of `log.SetupZapLogger` is not checked (errcheck)

InitializeMetrics()

if BuildInfo == nil {
t.Fatalf("Expected BuildInfo to be initialized")
}

// Verify that the build info gauge has been set with runtime information
// Note: buildinfo.Version is populated via ldflags during build, so in tests it will
// use the "unknown" fallback. The actual version label is tested in integration tests
// or when running a built binary.
metric := &dto.Metric{}
// Use the actual runtime values that were used to set the metric
err := BuildInfo.WithLabelValues("unknown", runtime.GOARCH, runtime.GOOS).Write(metric)
if err != nil {
t.Fatalf("Failed to write metric: %v", err)
}

if metric.Gauge == nil {

Check failure on line 61 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows, arm64)

avoid direct access to proto field metric.Gauge, use metric.GetGauge() instead (protogetter)

Check failure on line 61 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (linux, arm64)

avoid direct access to proto field metric.Gauge, use metric.GetGauge() instead (protogetter)

Check failure on line 61 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows, amd64)

avoid direct access to proto field metric.Gauge, use metric.GetGauge() instead (protogetter)

Check failure on line 61 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (linux, amd64)

avoid direct access to proto field metric.Gauge, use metric.GetGauge() instead (protogetter)
t.Fatalf("Expected gauge metric, got nil")
}

if *metric.Gauge.Value != 1 {

Check failure on line 65 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows, arm64)

avoid direct access to proto field *metric.Gauge.Value, use metric.GetGauge().GetValue() instead (protogetter)

Check failure on line 65 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (linux, arm64)

avoid direct access to proto field *metric.Gauge.Value, use metric.GetGauge().GetValue() instead (protogetter)

Check failure on line 65 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows, amd64)

avoid direct access to proto field *metric.Gauge.Value, use metric.GetGauge().GetValue() instead (protogetter)

Check failure on line 65 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (linux, amd64)

avoid direct access to proto field *metric.Gauge.Value, use metric.GetGauge().GetValue() instead (protogetter)
t.Errorf("Expected gauge value to be 1, got %f", *metric.Gauge.Value)

Check failure on line 66 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows, arm64)

avoid direct access to proto field *metric.Gauge.Value, use metric.GetGauge().GetValue() instead (protogetter)

Check failure on line 66 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (linux, arm64)

avoid direct access to proto field *metric.Gauge.Value, use metric.GetGauge().GetValue() instead (protogetter)

Check failure on line 66 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows, amd64)

avoid direct access to proto field *metric.Gauge.Value, use metric.GetGauge().GetValue() instead (protogetter)

Check failure on line 66 in pkg/metrics/metrics_test.go

View workflow job for this annotation

GitHub Actions / Lint (linux, amd64)

avoid direct access to proto field *metric.Gauge.Value, use metric.GetGauge().GetValue() instead (protogetter)
}

t.Logf("✓ BuildInfo metric correctly set to 1 with labels: version=unknown, arch=%s, os=%s", runtime.GOARCH, runtime.GOOS)
}
6 changes: 6 additions & 0 deletions pkg/metrics/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ const (
ConntrackBytesTxDescription = "Number of tx bytes"
ConntrackBytesRxDescription = "Number of rx bytes"
ConntrackTotalConnectionsDescription = "Total number of connections"

// Build info
BuildInfoDescription = "Retina build information"
)

// Metric Counters
Expand Down Expand Up @@ -107,6 +110,9 @@ var (
ConntrackBytesTx GaugeVec
ConntrackBytesRx GaugeVec
ConntrackTotalConnections GaugeVec

// Build Info
BuildInfo GaugeVec
)

func ToPrometheusType(metric interface{}) prometheus.Collector {
Expand Down
5 changes: 5 additions & 0 deletions pkg/utils/attr_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ var (
Active = "ACTIVE"
Device = "device"

// Build Info labels
BuildVersion = "version"
BuildArchitecture = "architecture"
BuildOS = "os"

// TCP Connection Statistic Names
ResetCount = "ResetCount"
ClosedFin = "ClosedFin"
Expand Down
3 changes: 3 additions & 0 deletions pkg/utils/metric_names.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ const (
ConntrackBytesTxGaugeName = "conntrack_bytes_tx"
ConntrackBytesRxGaugeName = "conntrack_bytes_rx"
ConntrackTotalConnectionsName = "conntrack_total_connections"

// Build Info
BuildInfoName = "build_info"
)

// IsAdvancedMetric is a helper function to determine if a name is an advanced metric
Expand Down
Loading