add prometheus metric

Signed-off-by: Gang Li <ganglica@google.com>
Signed-off-by: Gang Li <gangligit@gmail.com>
This commit is contained in:
Gang Li 2025-02-19 23:28:53 +00:00 committed by Gang Li
parent 66748c0d46
commit d76671ca80
4 changed files with 53 additions and 6 deletions

View File

@ -112,8 +112,6 @@ type MutableFeatureGate interface {
Add(features map[Feature]FeatureSpec) error
// GetAll returns a copy of the map of known feature names to feature specs.
GetAll() map[Feature]FeatureSpec
// AddMetrics adds feature enablement metrics
AddMetrics()
// OverrideDefault sets a local override for the registered default value of a named
// feature. If the feature has not been previously registered (e.g. by a call to Add), has a
// locked default, or if the gate has already registered itself with a FlagSet, a non-nil
@ -363,10 +361,6 @@ func (f *featureGate) AddFlag(fs *flag.FlagSet, flagName string) {
"Options are:\n"+strings.Join(known, "\n"))
}
func (f *featureGate) AddMetrics() {
// TODO(henrybear327): implement this.
}
// KnownFeatures returns a slice of strings describing the FeatureGate's known features.
// Deprecated and GA features are hidden from the list.
func (f *featureGate) KnownFeatures() []string {

View File

@ -140,6 +140,13 @@ var (
},
[]string{"server_id"},
)
serverFeatureEnabled = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "etcd_server_feature_enabled",
Help: "Whether or not a feature is enabled. 1 is enabled, 0 is not.",
},
[]string{"name", "stage"},
)
fdUsed = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "os",
Subsystem: "fd",
@ -170,6 +177,7 @@ func init() {
prometheus.MustRegister(currentVersion)
prometheus.MustRegister(currentGoVersion)
prometheus.MustRegister(serverID)
prometheus.MustRegister(serverFeatureEnabled)
prometheus.MustRegister(learnerPromoteSucceed)
prometheus.MustRegister(learnerPromoteFailed)
prometheus.MustRegister(fdUsed)

View File

@ -342,6 +342,8 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) {
firstCommitInTerm: notify.NewNotifier(),
clusterVersionChanged: notify.NewNotifier(),
}
addFeatureGateMetrics(cfg.ServerFeatureGate, serverFeatureEnabled)
serverID.With(prometheus.Labels{"server_id": b.cluster.nodeID.String()}).Set(1)
srv.cluster.SetVersionChangedNotifier(srv.clusterVersionChanged)
@ -2519,3 +2521,15 @@ func (s *EtcdServer) getTxPostLockInsideApplyHook() func() {
func (s *EtcdServer) CorruptionChecker() CorruptionChecker {
return s.corruptionChecker
}
func addFeatureGateMetrics(fg featuregate.FeatureGate, guageVec *prometheus.GaugeVec) {
for feature, featureSpec := range fg.(featuregate.MutableFeatureGate).GetAll() {
var metricVal float64
if fg.Enabled(feature) {
metricVal = 1
} else {
metricVal = 0
}
guageVec.With(prometheus.Labels{"name": string(feature), "stage": string(featureSpec.PreRelease)}).Set(metricVal)
}
}

View File

@ -24,12 +24,15 @@ import (
"os"
"path/filepath"
"reflect"
"strings"
"sync"
"testing"
"time"
"github.com/coreos/go-semver/semver"
"github.com/golang/protobuf/proto"
"github.com/prometheus/client_golang/prometheus"
ptestutil "github.com/prometheus/client_golang/prometheus/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
@ -42,6 +45,7 @@ import (
"go.etcd.io/etcd/client/pkg/v3/testutil"
"go.etcd.io/etcd/client/pkg/v3/types"
"go.etcd.io/etcd/client/pkg/v3/verify"
"go.etcd.io/etcd/pkg/v3/featuregate"
"go.etcd.io/etcd/pkg/v3/idutil"
"go.etcd.io/etcd/pkg/v3/notify"
"go.etcd.io/etcd/pkg/v3/pbutil"
@ -1683,3 +1687,30 @@ func TestIsActive(t *testing.T) {
require.Equal(t, tc.expectActive, s.isActive())
}
}
func TestAddFeatureGateMetrics(t *testing.T) {
const testAlphaGate featuregate.Feature = "TestAlpha"
const testBetaGate featuregate.Feature = "TestBeta"
const testGAGate featuregate.Feature = "TestGA"
featuremap := map[featuregate.Feature]featuregate.FeatureSpec{
testGAGate: {Default: true, PreRelease: featuregate.GA},
testAlphaGate: {Default: true, PreRelease: featuregate.Alpha},
testBetaGate: {Default: false, PreRelease: featuregate.Beta},
}
fg := featuregate.New("test", zaptest.NewLogger(t))
fg.Add(featuremap)
addFeatureGateMetrics(fg, serverFeatureEnabled)
expected := `# HELP etcd_server_feature_enabled Whether or not a feature is enabled. 1 is enabled, 0 is not.
# TYPE etcd_server_feature_enabled gauge
etcd_server_feature_enabled{name="AllAlpha",stage="ALPHA"} 0
etcd_server_feature_enabled{name="AllBeta",stage="BETA"} 0
etcd_server_feature_enabled{name="TestAlpha",stage="ALPHA"} 1
etcd_server_feature_enabled{name="TestBeta",stage="BETA"} 0
etcd_server_feature_enabled{name="TestGA",stage=""} 1
`
err := ptestutil.GatherAndCompare(prometheus.DefaultGatherer, strings.NewReader(expected), "etcd_server_feature_enabled")
require.NoErrorf(t, err, "unexpected metric collection result: \n%s", err)
}