Better /metrics handling

This commit is contained in:
Galorhallen 2021-12-10 15:39:22 +01:00
parent fdbd1a678f
commit fc19ac5d29
5 changed files with 54 additions and 23 deletions

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"log" "log"
"reflect" "reflect"
"strings"
"time" "time"
"github.com/heetch/confita" "github.com/heetch/confita"
@ -64,6 +65,20 @@ func Load() (*EnvConfig, []Config) {
return cfg, cfg.Split() 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("<Config@%X %s>", &c, strings.Join(buffer, ", "))
}
//Validate check if the config is valid //Validate check if the config is valid
func (c Config) Validate() error { func (c Config) Validate() error {
if c.PIHoleProtocol != "http" && c.PIHoleProtocol != "https" { if c.PIHoleProtocol != "http" && c.PIHoleProtocol != "https" {

View File

@ -14,7 +14,6 @@ import (
"github.com/eko/pihole-exporter/config" "github.com/eko/pihole-exporter/config"
"github.com/eko/pihole-exporter/internal/metrics" "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. // 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) fmt.Printf("Creating client with config %s\n", config)
client := &Client{ return &Client{
config: config, config: config,
httpClient: http.Client{ httpClient: http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error { 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 { func (c *Client) String() string {
return c.config.PIHoleHostname return c.config.PIHoleHostname
} }
/*
// Metrics scrapes pihole and sets them // Metrics scrapes pihole and sets them
func (c *Client) Metrics() http.HandlerFunc { func (c *Client) Metrics() http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) { 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()) log.Printf("New tick of statistics: %s", stats.ToString())
promhttp.Handler().ServeHTTP(writer, request) 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() stats, err := c.getStatistics()
if err != nil { if err != nil {
writer.WriteHeader(http.StatusBadRequest) return err
_, _ = writer.Write([]byte(err.Error()))
return
} }
c.setMetrics(stats) c.setMetrics(stats)
log.Printf("New tick of statistics: %s", stats.ToString()) log.Printf("New tick of statistics from %s: %s", c, stats)
promhttp.Handler().ServeHTTP(writer, request) return nil
} }
func (c *Client) GetHostname() string { func (c *Client) GetHostname() string {

View File

@ -31,6 +31,6 @@ type Stats struct {
} }
// ToString method returns a string of the current statistics 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) return fmt.Sprintf("%d ads blocked / %d total DNS queries", s.AdsBlockedToday, s.DNSQueriesAllTypes)
} }

View File

@ -5,9 +5,11 @@ import (
"log" "log"
"net/http" "net/http"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/eko/pihole-exporter/internal/pihole" "github.com/eko/pihole-exporter/internal/pihole"
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
@ -33,10 +35,22 @@ func NewServer(port uint16, clients []*pihole.Client) *Server {
mux.HandleFunc("/metrics", mux.HandleFunc("/metrics",
func(writer http.ResponseWriter, request *http.Request) { func(writer http.ResponseWriter, request *http.Request) {
for i, client := range clients { errors := make([]string, 0)
fmt.Printf("Idx: %d, Hostname: %s\n", i, client)
client.CollectMetrics(writer, request) 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)
}, },
) )

19
main.go
View File

@ -16,12 +16,8 @@ func main() {
metrics.Init() metrics.Init()
serverDead := make(chan struct{}) serverDead := make(chan struct{})
clients := make([]*pihole.Client, 0, len(clientConfigs))
for i, _ := range clientConfigs { clients := buildClients(clientConfigs)
client := pihole.NewClient(&clientConfigs[i])
clients = append(clients, client)
fmt.Printf("Append client %s\n", clients)
}
s := server.NewServer(envConf.Port, clients) s := server.NewServer(envConf.Port, clients)
go func() { go func() {
@ -43,3 +39,14 @@ func main() {
fmt.Println("pihole-exporter HTTP server stopped") 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
}