Skip to content

Commit d76671c

Browse files
committed
add prometheus metric
Signed-off-by: Gang Li <[email protected]> Signed-off-by: Gang Li <[email protected]>
1 parent 66748c0 commit d76671c

File tree

4 files changed

+53
-6
lines changed

4 files changed

+53
-6
lines changed

pkg/featuregate/feature_gate.go

-6
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,6 @@ type MutableFeatureGate interface {
112112
Add(features map[Feature]FeatureSpec) error
113113
// GetAll returns a copy of the map of known feature names to feature specs.
114114
GetAll() map[Feature]FeatureSpec
115-
// AddMetrics adds feature enablement metrics
116-
AddMetrics()
117115
// OverrideDefault sets a local override for the registered default value of a named
118116
// feature. If the feature has not been previously registered (e.g. by a call to Add), has a
119117
// 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) {
363361
"Options are:\n"+strings.Join(known, "\n"))
364362
}
365363

366-
func (f *featureGate) AddMetrics() {
367-
// TODO(henrybear327): implement this.
368-
}
369-
370364
// KnownFeatures returns a slice of strings describing the FeatureGate's known features.
371365
// Deprecated and GA features are hidden from the list.
372366
func (f *featureGate) KnownFeatures() []string {

server/etcdserver/metrics.go

+8
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ var (
140140
},
141141
[]string{"server_id"},
142142
)
143+
serverFeatureEnabled = prometheus.NewGaugeVec(
144+
prometheus.GaugeOpts{
145+
Name: "etcd_server_feature_enabled",
146+
Help: "Whether or not a feature is enabled. 1 is enabled, 0 is not.",
147+
},
148+
[]string{"name", "stage"},
149+
)
143150
fdUsed = prometheus.NewGauge(prometheus.GaugeOpts{
144151
Namespace: "os",
145152
Subsystem: "fd",
@@ -170,6 +177,7 @@ func init() {
170177
prometheus.MustRegister(currentVersion)
171178
prometheus.MustRegister(currentGoVersion)
172179
prometheus.MustRegister(serverID)
180+
prometheus.MustRegister(serverFeatureEnabled)
173181
prometheus.MustRegister(learnerPromoteSucceed)
174182
prometheus.MustRegister(learnerPromoteFailed)
175183
prometheus.MustRegister(fdUsed)

server/etcdserver/server.go

+14
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) {
342342
firstCommitInTerm: notify.NewNotifier(),
343343
clusterVersionChanged: notify.NewNotifier(),
344344
}
345+
346+
addFeatureGateMetrics(cfg.ServerFeatureGate, serverFeatureEnabled)
345347
serverID.With(prometheus.Labels{"server_id": b.cluster.nodeID.String()}).Set(1)
346348
srv.cluster.SetVersionChangedNotifier(srv.clusterVersionChanged)
347349

@@ -2519,3 +2521,15 @@ func (s *EtcdServer) getTxPostLockInsideApplyHook() func() {
25192521
func (s *EtcdServer) CorruptionChecker() CorruptionChecker {
25202522
return s.corruptionChecker
25212523
}
2524+
2525+
func addFeatureGateMetrics(fg featuregate.FeatureGate, guageVec *prometheus.GaugeVec) {
2526+
for feature, featureSpec := range fg.(featuregate.MutableFeatureGate).GetAll() {
2527+
var metricVal float64
2528+
if fg.Enabled(feature) {
2529+
metricVal = 1
2530+
} else {
2531+
metricVal = 0
2532+
}
2533+
guageVec.With(prometheus.Labels{"name": string(feature), "stage": string(featureSpec.PreRelease)}).Set(metricVal)
2534+
}
2535+
}

server/etcdserver/server_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,15 @@ import (
2424
"os"
2525
"path/filepath"
2626
"reflect"
27+
"strings"
2728
"sync"
2829
"testing"
2930
"time"
3031

3132
"github.com/coreos/go-semver/semver"
3233
"github.com/golang/protobuf/proto"
34+
"github.com/prometheus/client_golang/prometheus"
35+
ptestutil "github.com/prometheus/client_golang/prometheus/testutil"
3336
"github.com/stretchr/testify/assert"
3437
"github.com/stretchr/testify/require"
3538
"go.uber.org/zap"
@@ -42,6 +45,7 @@ import (
4245
"go.etcd.io/etcd/client/pkg/v3/testutil"
4346
"go.etcd.io/etcd/client/pkg/v3/types"
4447
"go.etcd.io/etcd/client/pkg/v3/verify"
48+
"go.etcd.io/etcd/pkg/v3/featuregate"
4549
"go.etcd.io/etcd/pkg/v3/idutil"
4650
"go.etcd.io/etcd/pkg/v3/notify"
4751
"go.etcd.io/etcd/pkg/v3/pbutil"
@@ -1683,3 +1687,30 @@ func TestIsActive(t *testing.T) {
16831687
require.Equal(t, tc.expectActive, s.isActive())
16841688
}
16851689
}
1690+
1691+
func TestAddFeatureGateMetrics(t *testing.T) {
1692+
const testAlphaGate featuregate.Feature = "TestAlpha"
1693+
const testBetaGate featuregate.Feature = "TestBeta"
1694+
const testGAGate featuregate.Feature = "TestGA"
1695+
1696+
featuremap := map[featuregate.Feature]featuregate.FeatureSpec{
1697+
testGAGate: {Default: true, PreRelease: featuregate.GA},
1698+
testAlphaGate: {Default: true, PreRelease: featuregate.Alpha},
1699+
testBetaGate: {Default: false, PreRelease: featuregate.Beta},
1700+
}
1701+
fg := featuregate.New("test", zaptest.NewLogger(t))
1702+
fg.Add(featuremap)
1703+
1704+
addFeatureGateMetrics(fg, serverFeatureEnabled)
1705+
1706+
expected := `# HELP etcd_server_feature_enabled Whether or not a feature is enabled. 1 is enabled, 0 is not.
1707+
# TYPE etcd_server_feature_enabled gauge
1708+
etcd_server_feature_enabled{name="AllAlpha",stage="ALPHA"} 0
1709+
etcd_server_feature_enabled{name="AllBeta",stage="BETA"} 0
1710+
etcd_server_feature_enabled{name="TestAlpha",stage="ALPHA"} 1
1711+
etcd_server_feature_enabled{name="TestBeta",stage="BETA"} 0
1712+
etcd_server_feature_enabled{name="TestGA",stage=""} 1
1713+
`
1714+
err := ptestutil.GatherAndCompare(prometheus.DefaultGatherer, strings.NewReader(expected), "etcd_server_feature_enabled")
1715+
require.NoErrorf(t, err, "unexpected metric collection result: \n%s", err)
1716+
}

0 commit comments

Comments
 (0)