mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-31 02:03:20 -04:00 
			
		
		
		
	Add prometheus metrics to the cache handler. This just used prometheus, if the metrics middleware does not setup the handler, there is nobody reading these metrics, but they are still reported. Seems the simplest solution while keeping the whole middleware separation in tact.
		
			
				
	
	
		
			87 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package metrics
 | |
| 
 | |
| import (
 | |
| 	"log"
 | |
| 	"net/http"
 | |
| 	"sync"
 | |
| 
 | |
| 	"github.com/miekg/coredns/middleware"
 | |
| 
 | |
| 	"github.com/prometheus/client_golang/prometheus"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	requestCount    *prometheus.CounterVec
 | |
| 	requestDuration *prometheus.HistogramVec
 | |
| 	responseSize    *prometheus.HistogramVec
 | |
| 	responseRcode   *prometheus.CounterVec
 | |
| )
 | |
| 
 | |
| const path = "/metrics"
 | |
| 
 | |
| // Metrics holds the prometheus configuration. The metrics' path is fixed to be /metrics
 | |
| type Metrics struct {
 | |
| 	Next      middleware.Handler
 | |
| 	Addr      string // where to we listen
 | |
| 	Once      sync.Once
 | |
| 	ZoneNames []string
 | |
| }
 | |
| 
 | |
| func (m *Metrics) Start() error {
 | |
| 	m.Once.Do(func() {
 | |
| 		define("")
 | |
| 
 | |
| 		prometheus.MustRegister(requestCount)
 | |
| 		prometheus.MustRegister(requestDuration)
 | |
| 		prometheus.MustRegister(responseSize)
 | |
| 		prometheus.MustRegister(responseRcode)
 | |
| 
 | |
| 		http.Handle(path, prometheus.Handler())
 | |
| 		go func() {
 | |
| 			if err := http.ListenAndServe(m.Addr, nil); err != nil {
 | |
| 				log.Printf("[ERROR] Failed to start prometheus handler: %s", err)
 | |
| 			}
 | |
| 		}()
 | |
| 	})
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func define(subsystem string) {
 | |
| 	requestCount = prometheus.NewCounterVec(prometheus.CounterOpts{
 | |
| 		Namespace: middleware.Namespace,
 | |
| 		Subsystem: subsystem,
 | |
| 		Name:      "request_count_total",
 | |
| 		Help:      "Counter of DNS requests made per zone and protocol.",
 | |
| 	}, []string{"zone", "proto"})
 | |
| 
 | |
| 	requestDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
 | |
| 		Namespace: middleware.Namespace,
 | |
| 		Subsystem: subsystem,
 | |
| 		Name:      "request_duration_seconds",
 | |
| 		Buckets:   append([]float64{.0001, .0005, .001, .0025}, prometheus.DefBuckets...),
 | |
| 		Help:      "Histogram of the time (in seconds) each request took.",
 | |
| 	}, []string{"zone"})
 | |
| 
 | |
| 	responseSize = prometheus.NewHistogramVec(prometheus.HistogramOpts{
 | |
| 		Namespace: middleware.Namespace,
 | |
| 		Subsystem: subsystem,
 | |
| 		Name:      "response_size_bytes",
 | |
| 		Help:      "Size of the returns response in bytes.",
 | |
| 		Buckets:   []float64{0, 100, 200, 300, 400, 511, 1023, 2047, 4095, 8291, 16e3, 32e3, 48e3, 64e3},
 | |
| 	}, []string{"zone"})
 | |
| 
 | |
| 	responseRcode = prometheus.NewCounterVec(prometheus.CounterOpts{
 | |
| 		Namespace: middleware.Namespace,
 | |
| 		Subsystem: subsystem,
 | |
| 		Name:      "response_rcode_count_total",
 | |
| 		Help:      "Counter of response status codes.",
 | |
| 	}, []string{"zone", "rcode"})
 | |
| }
 | |
| 
 | |
| const (
 | |
| 	// Dropped indicates we dropped the query before any handling. It has no closing dot, so it can not be a valid zone.
 | |
| 	Dropped = "dropped"
 | |
| 
 | |
| 	subsystem = "dns"
 | |
| )
 |