From fba9ee280953f55d726aa22f77f1686132709d74 Mon Sep 17 00:00:00 2001 From: Hector Date: Fri, 10 Sep 2021 06:13:56 +0000 Subject: [PATCH] feat: export new version metric (#12) Add a new `f2b_version` metric that includes the version of the fail2ban server and the exporter. Add a new socket command to get back the fail2ban server version. --- src/exporter.go | 24 ++++++++++++++++++++++++ src/socket/fail2banSocket.go | 14 ++++++++++++++ src/socket/protocol.go | 1 + 3 files changed, 39 insertions(+) diff --git a/src/exporter.go b/src/exporter.go index 5ca325f..1cf422f 100644 --- a/src/exporter.go +++ b/src/exporter.go @@ -85,6 +85,11 @@ var ( "Total number of IPs banned by this jail (includes expired bans)", []string{"jail"}, nil, ) + metricVersionInfo = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "", "version"), + "Version of the exporter and fail2ban server", + []string{"exporter", "fail2ban"}, nil, + ) ) type Exporter struct { @@ -135,6 +140,9 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { if err == nil && s != nil { e.collectJailMetrics(ch, s) } + e.collectVersionMetric(ch, s) + } else { + e.collectVersionMetric(ch, nil) } e.collectErrorCountMetric(ch) } @@ -273,6 +281,22 @@ func (e *Exporter) collectJailStatsMetric(ch chan<- prometheus.Metric, s *socket ) } +func (e *Exporter) collectVersionMetric(ch chan<- prometheus.Metric, s *socket.Fail2BanSocket) { + var err error + var fail2banVersion = "" + if s != nil { + fail2banVersion, err = s.GetServerVersion() + if err != nil { + e.socketRequestErrorCount++ + log.Printf("failed to get fail2ban server version: %v", err) + } + } + + ch <- prometheus.MustNewConstMetric( + metricVersionInfo, prometheus.GaugeValue, float64(1), version, fail2banVersion, + ) +} + func printAppVersion() { fmt.Println(version) fmt.Printf(" build date: %s\r\n commit hash: %s\r\n built by: %s\r\n", date, commit, builtBy) diff --git a/src/socket/fail2banSocket.go b/src/socket/fail2banSocket.go index 4f720ad..78133e3 100644 --- a/src/socket/fail2banSocket.go +++ b/src/socket/fail2banSocket.go @@ -118,6 +118,20 @@ func (s *Fail2BanSocket) GetJailStats(jail string) (JailStats, error) { return stats, newBadFormatError(statusCommand, response) } +func (s *Fail2BanSocket) GetServerVersion() (string, error) { + response, err := s.sendCommand([]string{versionCommand}) + if err != nil { + return "", err + } + + if lvl1, ok := response.(*types.Tuple); ok { + if versionStr, ok := lvl1.Get(1).(string); ok { + return versionStr, nil + } + } + return "", newBadFormatError(versionCommand, response) +} + func newBadFormatError(command string, data interface{}) error { return fmt.Errorf("(%s) unexpected response format - cannot parse: %v", command, data) } diff --git a/src/socket/protocol.go b/src/socket/protocol.go index 5320f5b..d510af7 100644 --- a/src/socket/protocol.go +++ b/src/socket/protocol.go @@ -11,6 +11,7 @@ const ( commandTerminator = "" pingCommand = "ping" statusCommand = "status" + versionCommand = "version" socketReadBufferSize = 1024 )