You've already forked prometheus-fail2ban-exporter
feat: add new jail config metrics
Add new metrics around basic jail configuration. The new metrics expose the max retries, ban time, and find time for each jail. Update project README with the new metrics.
This commit is contained in:
@ -46,6 +46,21 @@ var (
|
||||
"Total number of IPs banned by this jail (includes expired bans)",
|
||||
[]string{"jail"}, nil,
|
||||
)
|
||||
metricJailBanTime = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "config", "jail_ban_time"),
|
||||
"How long an IP is banned for in this jail (in seconds)",
|
||||
[]string{"jail"}, nil,
|
||||
)
|
||||
metricJailFindTime = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "config", "jail_find_time"),
|
||||
"How far back will the filter look for failures in this jail (in seconds)",
|
||||
[]string{"jail"}, nil,
|
||||
)
|
||||
metricJailMaxRetry = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "config", "jail_max_retries"),
|
||||
"The number of failures allowed until the IP is banned by this jail",
|
||||
[]string{"jail"}, nil,
|
||||
)
|
||||
metricVersionInfo = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "version"),
|
||||
"Version of the exporter and fail2ban server",
|
||||
@ -98,6 +113,7 @@ func (c *Collector) collectJailMetrics(ch chan<- prometheus.Metric, s *socket.Fa
|
||||
|
||||
for i := range jails {
|
||||
c.collectJailStatsMetric(ch, s, jails[i])
|
||||
c.collectJailConfigMetrics(ch, s, jails[i])
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,6 +139,36 @@ func (c *Collector) collectJailStatsMetric(ch chan<- prometheus.Metric, s *socke
|
||||
)
|
||||
}
|
||||
|
||||
func (c *Collector) collectJailConfigMetrics(ch chan<- prometheus.Metric, s *socket.Fail2BanSocket, jail string) {
|
||||
banTime, err := s.GetJailBanTime(jail)
|
||||
if err != nil {
|
||||
c.socketRequestErrorCount++
|
||||
log.Printf("failed to get ban time for jail %s: %v", jail, err)
|
||||
} else {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
metricJailBanTime, prometheus.GaugeValue, float64(banTime), jail,
|
||||
)
|
||||
}
|
||||
findTime, err := s.GetJailFindTime(jail)
|
||||
if err != nil {
|
||||
c.socketRequestErrorCount++
|
||||
log.Printf("failed to get find time for jail %s: %v", jail, err)
|
||||
} else {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
metricJailFindTime, prometheus.GaugeValue, float64(findTime), jail,
|
||||
)
|
||||
}
|
||||
maxRetry, err := s.GetJailMaxRetries(jail)
|
||||
if err != nil {
|
||||
c.socketRequestErrorCount++
|
||||
log.Printf("failed to get max retries for jail %s: %v", jail, err)
|
||||
} else {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
metricJailMaxRetry, prometheus.GaugeValue, float64(maxRetry), jail,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Collector) collectVersionMetric(ch chan<- prometheus.Metric, s *socket.Fail2BanSocket) {
|
||||
var err error
|
||||
var fail2banVersion = ""
|
||||
|
@ -118,6 +118,21 @@ func (s *Fail2BanSocket) GetJailStats(jail string) (JailStats, error) {
|
||||
return stats, newBadFormatError(statusCommand, response)
|
||||
}
|
||||
|
||||
func (s *Fail2BanSocket) GetJailBanTime(jail string) (int, error) {
|
||||
command := fmt.Sprintf(banTimeCommandFmt, jail)
|
||||
return s.sendSimpleIntCommand(command)
|
||||
}
|
||||
|
||||
func (s *Fail2BanSocket) GetJailFindTime(jail string) (int, error) {
|
||||
command := fmt.Sprintf(findTimeCommandFmt, jail)
|
||||
return s.sendSimpleIntCommand(command)
|
||||
}
|
||||
|
||||
func (s *Fail2BanSocket) GetJailMaxRetries(jail string) (int, error) {
|
||||
command := fmt.Sprintf(maxRetriesCommandFmt, jail)
|
||||
return s.sendSimpleIntCommand(command)
|
||||
}
|
||||
|
||||
func (s *Fail2BanSocket) GetServerVersion() (string, error) {
|
||||
response, err := s.sendCommand([]string{versionCommand})
|
||||
if err != nil {
|
||||
@ -132,6 +147,22 @@ func (s *Fail2BanSocket) GetServerVersion() (string, error) {
|
||||
return "", newBadFormatError(versionCommand, response)
|
||||
}
|
||||
|
||||
// sendSimpleIntCommand sends a command to the fail2ban socket and parses the response to extract an int.
|
||||
// This command assumes that the response data is in the format of `(d, d)` where `d` is a number.
|
||||
func (s *Fail2BanSocket) sendSimpleIntCommand(command string) (int, error) {
|
||||
response, err := s.sendCommand(strings.Split(command, " "))
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
if lvl1, ok := response.(*types.Tuple); ok {
|
||||
if banTime, ok := lvl1.Get(1).(int); ok {
|
||||
return banTime, nil
|
||||
}
|
||||
}
|
||||
return -1, newBadFormatError(command, response)
|
||||
}
|
||||
|
||||
func newBadFormatError(command string, data interface{}) error {
|
||||
return fmt.Errorf("(%s) unexpected response format - cannot parse: %v", command, data)
|
||||
}
|
||||
|
@ -12,6 +12,9 @@ const (
|
||||
pingCommand = "ping"
|
||||
statusCommand = "status"
|
||||
versionCommand = "version"
|
||||
banTimeCommandFmt = "get %s bantime"
|
||||
findTimeCommandFmt = "get %s findtime"
|
||||
maxRetriesCommandFmt = "get %s maxretry"
|
||||
socketReadBufferSize = 1024
|
||||
)
|
||||
|
||||
|
Reference in New Issue
Block a user