@@ -11,6 +11,7 @@ package app
1111import (
1212 "context"
1313 "fmt"
14+ "strings"
1415 "time"
1516
1617 "github.com/prometheus/client_golang/prometheus"
@@ -35,6 +36,14 @@ var subscribeResponseFailedCounter = prometheus.NewCounterVec(prometheus.Counter
3536 Help : "Total number of failed subscribe requests" ,
3637}, []string {"source" , "subscription" })
3738
39+ // target
40+ var targetUPMetric = prometheus .NewGaugeVec (prometheus.GaugeOpts {
41+ Namespace : "gnmic" ,
42+ Subsystem : "target" ,
43+ Name : "up" ,
44+ Help : "Has value 1 if the gNMI connection to the target is established; otherwise, 0." ,
45+ }, []string {"name" })
46+
3847// cluster
3948var clusterNumberOfLockedTargets = prometheus .NewGauge (prometheus.GaugeOpts {
4049 Namespace : "gnmic" ,
@@ -49,6 +58,66 @@ var clusterIsLeader = prometheus.NewGauge(prometheus.GaugeOpts{
4958 Help : "Has value 1 if this gnmic instance is the cluster leader, 0 otherwise" ,
5059})
5160
61+ func (a * App ) registerTargetMetrics () {
62+ err := a .reg .Register (targetUPMetric )
63+ if err != nil {
64+ a .Logger .Printf ("failed to register target metric: %v" , err )
65+ }
66+ a .configLock .RLock ()
67+ for _ , t := range a .Config .Targets {
68+ targetUPMetric .WithLabelValues (t .Name ).Set (0 )
69+ }
70+ a .configLock .RUnlock ()
71+ go func () {
72+ ticker := time .NewTicker (clusterMetricsUpdatePeriod )
73+ defer ticker .Stop ()
74+ for {
75+ select {
76+ case <- a .ctx .Done ():
77+ return
78+ case <- ticker .C :
79+ ownTargets := make (map [string ]string )
80+ if a .isLeader {
81+ lockedNodesPrefix := fmt .Sprintf ("gnmic/%s/targets" , a .Config .ClusterName )
82+ ctx , cancel := context .WithTimeout (a .ctx , clusterMetricsUpdatePeriod / 2 )
83+ lockedNodes , err := a .locker .List (ctx , lockedNodesPrefix )
84+ cancel ()
85+ if err != nil {
86+ a .Logger .Printf ("failed to get locked nodes key: %v" , err )
87+ }
88+ for k , v := range lockedNodes {
89+ ownTargets [strings .TrimPrefix (k , lockedNodesPrefix + "/" )] = v
90+ }
91+ }
92+
93+ a .configLock .RLock ()
94+ for _ , tc := range a .Config .Targets {
95+ a .operLock .RLock ()
96+ t , ok := a .Targets [tc .Name ]
97+ a .operLock .RUnlock ()
98+ if ok {
99+ switch t .ConnState () {
100+ case "IDLE" , "READY" :
101+ targetUPMetric .WithLabelValues (tc .Name ).Set (1 )
102+ default :
103+ targetUPMetric .WithLabelValues (tc .Name ).Set (0 )
104+ }
105+ } else {
106+ if a .isLeader {
107+ if ownTargets [tc .Name ] == a .Config .Clustering .InstanceName {
108+ targetUPMetric .WithLabelValues (tc .Name ).Set (0 )
109+ }
110+ } else {
111+ targetUPMetric .WithLabelValues (tc .Name ).Set (0 )
112+ }
113+ }
114+ }
115+ a .configLock .RUnlock ()
116+ }
117+ }
118+ }()
119+ }
120+
52121func (a * App ) startClusterMetrics () {
53122 if a .Config .APIServer == nil || ! a .Config .APIServer .EnableMetrics || a .Config .Clustering == nil {
54123 return
0 commit comments