You've already forked prometheus-fail2ban-exporter
							
							implement new collector for textfile metrics
This commit is contained in:
		@@ -46,8 +46,11 @@ func (settings *AppSettings) validateFlags() {
 | 
				
			|||||||
				minServerPort, maxServerPort, settings.MetricsPort)
 | 
									minServerPort, maxServerPort, settings.MetricsPort)
 | 
				
			||||||
			flagsValid = false
 | 
								flagsValid = false
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if settings.FileCollectorPath != "" {
 | 
				
			||||||
 | 
								settings.FileCollectorEnabled = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if settings.FileCollectorEnabled && settings.FileCollectorPath == "" {
 | 
							if settings.FileCollectorEnabled && settings.FileCollectorPath == "" {
 | 
				
			||||||
			fmt.Printf("file collector directory must not be empty if collector enabled\n")
 | 
								fmt.Printf("file collector directory path must not be empty if collector enabled\n")
 | 
				
			||||||
			flagsValid = false
 | 
								flagsValid = false
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package main
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fail2ban-prometheus-exporter/cfg"
 | 
						"fail2ban-prometheus-exporter/cfg"
 | 
				
			||||||
	"fail2ban-prometheus-exporter/export"
 | 
						"fail2ban-prometheus-exporter/export"
 | 
				
			||||||
 | 
						"fail2ban-prometheus-exporter/textfile"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
@@ -43,6 +44,11 @@ func rootHtmlHandler(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func metricHandler(w http.ResponseWriter, r *http.Request, collector *textfile.Collector) {
 | 
				
			||||||
 | 
						promhttp.Handler().ServeHTTP(w, r)
 | 
				
			||||||
 | 
						collector.WriteTextFileMetrics(w, r)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	appSettings := cfg.Parse()
 | 
						appSettings := cfg.Parse()
 | 
				
			||||||
	if appSettings.VersionMode {
 | 
						if appSettings.VersionMode {
 | 
				
			||||||
@@ -55,8 +61,13 @@ func main() {
 | 
				
			|||||||
		exporter := export.NewExporter(appSettings, version)
 | 
							exporter := export.NewExporter(appSettings, version)
 | 
				
			||||||
		prometheus.MustRegister(exporter)
 | 
							prometheus.MustRegister(exporter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							textFileCollector := textfile.NewCollector(appSettings)
 | 
				
			||||||
 | 
							prometheus.MustRegister(textFileCollector)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		http.HandleFunc("/", rootHtmlHandler)
 | 
							http.HandleFunc("/", rootHtmlHandler)
 | 
				
			||||||
		http.Handle(metricsPath, promhttp.Handler())
 | 
							http.HandleFunc(metricsPath, func(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
								metricHandler(w, r, textFileCollector)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
		log.Printf("metrics available at '%s'", metricsPath)
 | 
							log.Printf("metrics available at '%s'", metricsPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		svrErr := make(chan error)
 | 
							svrErr := make(chan error)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								src/textfile/collector.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/textfile/collector.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					package textfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fail2ban-prometheus-exporter/cfg"
 | 
				
			||||||
 | 
						"github.com/prometheus/client_golang/prometheus"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Collector struct {
 | 
				
			||||||
 | 
						enabled bool
 | 
				
			||||||
 | 
						folderPath string
 | 
				
			||||||
 | 
						fileMap map[string]fileMetrics
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type fileMetrics struct {
 | 
				
			||||||
 | 
						readErrors int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewCollector(appSettings *cfg.AppSettings) *Collector {
 | 
				
			||||||
 | 
						return &Collector{
 | 
				
			||||||
 | 
							enabled:    appSettings.FileCollectorEnabled,
 | 
				
			||||||
 | 
							folderPath: appSettings.FileCollectorPath,
 | 
				
			||||||
 | 
							fileMap:    make(map[string]fileMetrics),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Collector) Describe(ch chan<- *prometheus.Desc) {
 | 
				
			||||||
 | 
						if c.enabled {
 | 
				
			||||||
 | 
							ch <- metricReadError
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Collector) Collect(ch chan<- prometheus.Metric) {
 | 
				
			||||||
 | 
						if c.enabled {
 | 
				
			||||||
 | 
							c.collectFileErrors(ch)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										21
									
								
								src/textfile/file.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/textfile/file.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					package textfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/prometheus/client_golang/prometheus"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const namespace = "textfile"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						metricReadError = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, "", "error"),
 | 
				
			||||||
 | 
							"Checks for errors while reading text files",
 | 
				
			||||||
 | 
							[]string{"path"}, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Collector) collectFileErrors(ch chan<- prometheus.Metric) {
 | 
				
			||||||
 | 
						for fileName, metrics := range c.fileMap {
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(
 | 
				
			||||||
 | 
								metricReadError, prometheus.GaugeValue, float64(metrics.readErrors), fileName,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										54
									
								
								src/textfile/writer.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/textfile/writer.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					package textfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Collector) WriteTextFileMetrics(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						files, err := ioutil.ReadDir(c.folderPath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.appendErrorForPath(c.folderPath)
 | 
				
			||||||
 | 
							log.Printf("error reading directory '%s': %v", c.folderPath, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, file := range files {
 | 
				
			||||||
 | 
							fileName := file.Name()
 | 
				
			||||||
 | 
							if !strings.HasSuffix(fileName, ".prom") {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							c.setErrorCountForPath(fileName, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fullPath := filepath.Join(c.folderPath, file.Name())
 | 
				
			||||||
 | 
							content, err := ioutil.ReadFile(fullPath)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								c.appendErrorForPath(fileName)
 | 
				
			||||||
 | 
								log.Printf("error reading contents of file '%s': %v", fileName, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							_, err = w.Write(content)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								c.appendErrorForPath(fileName)
 | 
				
			||||||
 | 
								log.Printf("error writing file contents to response writer '%s': %v", fileName, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Collector) appendErrorForPath(path string) {
 | 
				
			||||||
 | 
						if _, ok := c.fileMap[path]; !ok {
 | 
				
			||||||
 | 
							c.setErrorCountForPath(path, 1)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							c.setErrorCountForPath(path, c.fileMap[path].readErrors + 1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Collector) setErrorCountForPath(path string, count int) {
 | 
				
			||||||
 | 
						c.fileMap[path] = fileMetrics{
 | 
				
			||||||
 | 
							readErrors: count,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user