diff --git a/internal/ingress/controller/nginx.go b/internal/ingress/controller/nginx.go index 00f83c495..72b0da1b5 100644 --- a/internal/ingress/controller/nginx.go +++ b/internal/ingress/controller/nginx.go @@ -269,8 +269,12 @@ func (n *NGINXController) Start() { if n.syncStatus != nil { go n.syncStatus.Run(stopCh) } + + n.metricCollector.OnStartedLeading(n.cfg.ElectionID) }, OnStoppedLeading: func() { + n.metricCollector.OnStoppedLeading(n.cfg.ElectionID) + // Remove prometheus metrics related to SSL certificates srvs := sets.NewString() for _, s := range n.runningConfig.Servers { diff --git a/internal/ingress/metric/collectors/controller.go b/internal/ingress/metric/collectors/controller.go index c24caaa45..8aeeaffe9 100644 --- a/internal/ingress/metric/collectors/controller.go +++ b/internal/ingress/metric/collectors/controller.go @@ -46,6 +46,8 @@ type Controller struct { constLabels prometheus.Labels labels prometheus.Labels + + leaderElection *prometheus.GaugeVec } // NewController creates a new prometheus collector for the @@ -112,6 +114,13 @@ func NewController(pod, namespace, class string) *Controller { }, sslLabelHost, ), + leaderElection: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "leader_election_status", + Help: "Gauge reporting status of the leader election, 0 indicates follower, 1 indicates leader. 'name' is the string used to identify the lease", + }, + []string{"name"}, + ), } return cm @@ -127,6 +136,16 @@ func (cm *Controller) IncReloadErrorCount() { cm.reloadOperationErrors.With(cm.constLabels).Inc() } +// OnStartedLeading indicates the pod is not the current leader +func (cm *Controller) OnStartedLeading(electionID string) { + cm.leaderElection.WithLabelValues(electionID).Set(0) +} + +// OnStoppedLeading indicates the pod is not the current leader +func (cm *Controller) OnStoppedLeading(electionID string) { + cm.leaderElection.WithLabelValues(electionID).Set(1.0) +} + // ConfigSuccess set a boolean flag according to the output of the controller configuration reload func (cm *Controller) ConfigSuccess(hash uint64, success bool) { if success { diff --git a/internal/ingress/metric/dummy.go b/internal/ingress/metric/dummy.go index 4c6872195..46ce3f7a8 100644 --- a/internal/ingress/metric/dummy.go +++ b/internal/ingress/metric/dummy.go @@ -52,3 +52,9 @@ func (dc DummyCollector) SetSSLExpireTime([]*ingress.Server) {} // SetHosts ... func (dc DummyCollector) SetHosts(hosts sets.String) {} + +// OnStartedLeading indicates the pod is not the current leader +func (dc DummyCollector) OnStartedLeading(electionID string) {} + +// OnStoppedLeading indicates the pod is not the current leader +func (dc DummyCollector) OnStoppedLeading(electionID string) {} diff --git a/internal/ingress/metric/main.go b/internal/ingress/metric/main.go index 4950a2497..fc161c4fa 100644 --- a/internal/ingress/metric/main.go +++ b/internal/ingress/metric/main.go @@ -36,6 +36,9 @@ type Collector interface { IncReloadCount() IncReloadErrorCount() + OnStartedLeading(string) + OnStoppedLeading(string) + RemoveMetrics(ingresses, endpoints []string) SetSSLExpireTime([]*ingress.Server) @@ -147,3 +150,13 @@ func (c *collector) SetSSLExpireTime(servers []*ingress.Server) { func (c *collector) SetHosts(hosts sets.String) { c.socket.SetHosts(hosts) } + +// OnStartedLeading indicates the pod is not the current leader +func (c *collector) OnStartedLeading(electionID string) { + c.ingressController.OnStartedLeading(electionID) +} + +// OnStoppedLeading indicates the pod is not the current leader +func (c *collector) OnStoppedLeading(electionID string) { + c.ingressController.OnStoppedLeading(electionID) +}