From fc19ac5d295d0d260863fe0778650c0129874e1a Mon Sep 17 00:00:00 2001 From: Galorhallen Date: Fri, 10 Dec 2021 15:39:22 +0100 Subject: [PATCH] Better /metrics handling --- config/configuration.go | 15 +++++++++++++++ internal/pihole/client.go | 21 ++++++++------------- internal/pihole/model.go | 2 +- internal/server/server.go | 20 +++++++++++++++++--- main.go | 19 +++++++++++++------ 5 files changed, 54 insertions(+), 23 deletions(-) diff --git a/config/configuration.go b/config/configuration.go index f26b272..0e41d03 100644 --- a/config/configuration.go +++ b/config/configuration.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "reflect" + "strings" "time" "github.com/heetch/confita" @@ -64,6 +65,20 @@ func Load() (*EnvConfig, []Config) { return cfg, cfg.Split() } +func (c *Config) String() string { + ref := reflect.ValueOf(c) + fields := ref.Elem() + + buffer := make([]string, fields.NumField(), fields.NumField()) + for i := 0; i < fields.NumField(); i++ { + valueField := fields.Field(i) + typeField := fields.Type().Field(i) + buffer[i] = fmt.Sprintf("%s=%v", typeField.Name, valueField.Interface()) + } + + return fmt.Sprintf("", &c, strings.Join(buffer, ", ")) +} + //Validate check if the config is valid func (c Config) Validate() error { if c.PIHoleProtocol != "http" && c.PIHoleProtocol != "https" { diff --git a/internal/pihole/client.go b/internal/pihole/client.go index 38c7a7d..c46bd53 100644 --- a/internal/pihole/client.go +++ b/internal/pihole/client.go @@ -14,7 +14,6 @@ import ( "github.com/eko/pihole-exporter/config" "github.com/eko/pihole-exporter/internal/metrics" - "github.com/prometheus/client_golang/prometheus/promhttp" ) // Client struct is a PI-Hole client to request an instance of a PI-Hole ad blocker. @@ -34,7 +33,7 @@ func NewClient(config *config.Config) *Client { fmt.Printf("Creating client with config %s\n", config) - client := &Client{ + return &Client{ config: config, httpClient: http.Client{ CheckRedirect: func(req *http.Request, via []*http.Request) error { @@ -42,16 +41,13 @@ func NewClient(config *config.Config) *Client { }, }, } - - fmt.Printf("Client created with config %s\n", client) - - return client } func (c *Client) String() string { return c.config.PIHoleHostname } +/* // Metrics scrapes pihole and sets them func (c *Client) Metrics() http.HandlerFunc { return func(writer http.ResponseWriter, request *http.Request) { @@ -66,19 +62,18 @@ func (c *Client) Metrics() http.HandlerFunc { log.Printf("New tick of statistics: %s", stats.ToString()) promhttp.Handler().ServeHTTP(writer, request) } -} +}*/ + +func (c *Client) CollectMetrics(writer http.ResponseWriter, request *http.Request) error { -func (c *Client) CollectMetrics(writer http.ResponseWriter, request *http.Request) { stats, err := c.getStatistics() if err != nil { - writer.WriteHeader(http.StatusBadRequest) - _, _ = writer.Write([]byte(err.Error())) - return + return err } c.setMetrics(stats) - log.Printf("New tick of statistics: %s", stats.ToString()) - promhttp.Handler().ServeHTTP(writer, request) + log.Printf("New tick of statistics from %s: %s", c, stats) + return nil } func (c *Client) GetHostname() string { diff --git a/internal/pihole/model.go b/internal/pihole/model.go index d800d0b..8067085 100644 --- a/internal/pihole/model.go +++ b/internal/pihole/model.go @@ -31,6 +31,6 @@ type Stats struct { } // ToString method returns a string of the current statistics struct. -func (s *Stats) ToString() string { +func (s *Stats) String() string { return fmt.Sprintf("%d ads blocked / %d total DNS queries", s.AdsBlockedToday, s.DNSQueriesAllTypes) } diff --git a/internal/server/server.go b/internal/server/server.go index b33bd9e..41d651a 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -5,9 +5,11 @@ import ( "log" "net/http" "strconv" + "strings" "time" "github.com/eko/pihole-exporter/internal/pihole" + "github.com/prometheus/client_golang/prometheus/promhttp" "golang.org/x/net/context" ) @@ -33,10 +35,22 @@ func NewServer(port uint16, clients []*pihole.Client) *Server { mux.HandleFunc("/metrics", func(writer http.ResponseWriter, request *http.Request) { - for i, client := range clients { - fmt.Printf("Idx: %d, Hostname: %s\n", i, client) - client.CollectMetrics(writer, request) + errors := make([]string, 0) + + for _, client := range clients { + if err := client.CollectMetrics(writer, request); err != nil { + errors = append(errors, err.Error()) + fmt.Printf("Error %s\n", err) + } } + + if len(errors) == len(clients) { + writer.WriteHeader(http.StatusBadRequest) + body := strings.Join(errors, "\n") + _, _ = writer.Write([]byte(body)) + } + + promhttp.Handler().ServeHTTP(writer, request) }, ) diff --git a/main.go b/main.go index 8ea80d0..ea8e7a9 100644 --- a/main.go +++ b/main.go @@ -16,12 +16,8 @@ func main() { metrics.Init() serverDead := make(chan struct{}) - clients := make([]*pihole.Client, 0, len(clientConfigs)) - for i, _ := range clientConfigs { - client := pihole.NewClient(&clientConfigs[i]) - clients = append(clients, client) - fmt.Printf("Append client %s\n", clients) - } + + clients := buildClients(clientConfigs) s := server.NewServer(envConf.Port, clients) go func() { @@ -43,3 +39,14 @@ func main() { fmt.Println("pihole-exporter HTTP server stopped") } + +func buildClients(clientConfigs []config.Config) []*pihole.Client { + clients := make([]*pihole.Client, 0, len(clientConfigs)) + for i := range clientConfigs { + clientConfig := &clientConfigs[i] + + client := pihole.NewClient(clientConfig) + clients = append(clients, client) + } + return clients +}