Repository: l3af-project/l3afd (language: go)

Issue:
Metric to monitor ebpf_program version running on the node
L3AFD should be extended to include a new metric that reports the ebpf_program version running on the node. In this way, the details of the ebpf_program version can be monitored.

```
l3afd_NFRunning{direction="egress",ebpf_program="traffic-mirroring",host="l3af-local-test",interface_name="enp0s3"} 1
l3afd_NFRunning{direction="ingress",ebpf_program="traffic-mirroring",host="l3af-local-test",interface_name="enp0s3"} 1
```
Add new tag _version_.


Discussion / hints:

Fix patch:
diff --git a/kf/bpf.go b/kf/bpf.go
index 90e8c501..60a2e3d0 100644
--- a/kf/bpf.go
+++ b/kf/bpf.go
@@ -240,7 +240,7 @@ func (b *BPF) Stop(ifaceName, direction string, chain bool) error {
 	stats.Incr(stats.NFStopCount, b.Program.Name, direction, ifaceName)
 
 	// Setting NFRunning to 0, indicates not running
-	stats.Set(0.0, stats.NFRunning, b.Program.Name, direction, ifaceName)
+	stats.SetWithVersion(0.0, stats.NFRunning, b.Program.Name, b.Program.Version, direction, ifaceName)
 
 	if len(b.Program.CmdStop) < 1 {
 		if err := b.ProcessTerminate(); err != nil {
diff --git a/kf/processCheck.go b/kf/processCheck.go
index c9e32d22..59889e56 100644
--- a/kf/processCheck.go
+++ b/kf/processCheck.go
@@ -51,7 +51,7 @@ func (c *pCheck) pMonitorWorker(bpfProgs map[string]*list.List, direction string
 				}
 				isRunning, _ := bpf.isRunning()
 				if isRunning {
-					stats.Set(1.0, stats.NFRunning, bpf.Program.Name, direction, ifaceName)
+					stats.SetWithVersion(1.0, stats.NFRunning, bpf.Program.Name, bpf.Program.Version, direction, ifaceName)
 					continue
 				}
 				// Not running trying to restart
@@ -63,7 +63,7 @@ func (c *pCheck) pMonitorWorker(bpfProgs map[string]*list.List, direction string
 						log.Error().Err(err).Msgf("pMonitor BPF Program start failed for program %s", bpf.Program.Name)
 					}
 				} else {
-					stats.Set(0.0, stats.NFRunning, bpf.Program.Name, direction, ifaceName)
+					stats.SetWithVersion(0.0, stats.NFRunning, bpf.Program.Name, bpf.Program.Version, direction, ifaceName)
 				}
 			}
 		}
diff --git a/stats/metrics.go b/stats/metrics.go
index 554cad98..6183dd70 100644
--- a/stats/metrics.go
+++ b/stats/metrics.go
@@ -62,7 +62,7 @@ func SetupMetrics(hostname, daemonName, metricsAddr string) {
 			Name:      "NFRunning",
 			Help:      "This value indicates network functions is running or not",
 		},
-		[]string{"host", "ebpf_program", "direction", "interface_name"},
+		[]string{"host", "ebpf_program", "version", "direction", "interface_name"},
 	)
 
 	if err := prometheus.Register(nfRunningVec); err != nil {
@@ -149,7 +149,7 @@ func Set(value float64, gaugeVec *prometheus.GaugeVec, ebpfProgram, direction, i
 		}),
 	)
 	if err != nil {
-		log.Warn().Msgf("Metrics: unable to fetch counter with fields: ebpf_program: %s, direction: %s, interface_name: %s",
+		log.Warn().Msgf("Metrics: unable to fetch gauge with fields: ebpf_program: %s, direction: %s, interface_name: %s",
 			ebpfProgram, direction, ifaceName)
 		return
 	}
@@ -170,9 +170,31 @@ func SetValue(value float64, gaugeVec *prometheus.GaugeVec, ebpfProgram, mapName
 		}),
 	)
 	if err != nil {
-		log.Warn().Msgf("Metrics: unable to fetch counter with fields: ebpf_program: %s, map_name: %s, interface_name: %s",
+		log.Warn().Msgf("Metrics: unable to fetch gauge with fields: ebpf_program: %s, map_name: %s, interface_name: %s",
 			ebpfProgram, mapName, ifaceName)
 		return
 	}
 	nfGauge.Set(value)
 }
+
+func SetWithVersion(value float64, gaugeVec *prometheus.GaugeVec, ebpfProgram, version, direction, ifaceName string) {
+
+	if gaugeVec == nil {
+		log.Warn().Msg("Metrics: gauge vector is nil and needs to be initialized before Set")
+		return
+	}
+	nfGauge, err := gaugeVec.GetMetricWith(
+		prometheus.Labels(map[string]string{
+			"ebpf_program":   ebpfProgram,
+			"version":        version,
+			"direction":      direction,
+			"interface_name": ifaceName,
+		}),
+	)
+	if err != nil {
+		log.Warn().Msgf("Metrics: unable to fetch gauge with fields: ebpf_program: %s, version: %s, direction: %s, interface_name: %s",
+			ebpfProgram, version, direction, ifaceName)
+		return
+	}
+	nfGauge.Set(value)
+}


Test patch: