mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-30 17:53:21 -04:00 
			
		
		
		
	middleware/metrics: survive restart (#542)
* middleware/metrics: survive restart Keep the handler running during restart. Stopping and starting the handler results in "address in use" - sometimes, meaning the reload will be flaky. In turn this behavior means any changes to the monitor stanza are not picked up. * remove resync
This commit is contained in:
		| @@ -27,6 +27,7 @@ Extra labels used are: | |||||||
| If monitoring is enabled, queries that do not enter the middleware chain are exported under the fake | If monitoring is enabled, queries that do not enter the middleware chain are exported under the fake | ||||||
| name "dropped" (without a closing dot - this is never a valid domain name). | name "dropped" (without a closing dot - this is never a valid domain name). | ||||||
|  |  | ||||||
|  |  | ||||||
| ## Syntax | ## Syntax | ||||||
|  |  | ||||||
| ~~~ | ~~~ | ||||||
| @@ -45,3 +46,8 @@ Use an alternative address: | |||||||
| ~~~ | ~~~ | ||||||
| prometheus localhost:9253 | prometheus localhost:9253 | ||||||
| ~~~ | ~~~ | ||||||
|  |  | ||||||
|  | # Bugs | ||||||
|  |  | ||||||
|  | When reloading, we keep the handler running, meaning that any changes to the handler aren't picked | ||||||
|  | up. You'll need to restart CoreDNS for that to happen. | ||||||
|   | |||||||
| @@ -13,13 +13,23 @@ import ( | |||||||
| 	"github.com/prometheus/client_golang/prometheus" | 	"github.com/prometheus/client_golang/prometheus" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	prometheus.MustRegister(vars.RequestCount) | ||||||
|  | 	prometheus.MustRegister(vars.RequestDuration) | ||||||
|  | 	prometheus.MustRegister(vars.RequestSize) | ||||||
|  | 	prometheus.MustRegister(vars.RequestDo) | ||||||
|  | 	prometheus.MustRegister(vars.RequestType) | ||||||
|  |  | ||||||
|  | 	prometheus.MustRegister(vars.ResponseSize) | ||||||
|  | 	prometheus.MustRegister(vars.ResponseRcode) | ||||||
|  | } | ||||||
|  |  | ||||||
| // Metrics holds the prometheus configuration. The metrics' path is fixed to be /metrics | // Metrics holds the prometheus configuration. The metrics' path is fixed to be /metrics | ||||||
| type Metrics struct { | type Metrics struct { | ||||||
| 	Next middleware.Handler | 	Next middleware.Handler | ||||||
| 	Addr string | 	Addr string | ||||||
| 	ln   net.Listener | 	ln   net.Listener | ||||||
| 	mux  *http.ServeMux | 	mux  *http.ServeMux | ||||||
| 	Once sync.Once |  | ||||||
|  |  | ||||||
| 	zoneNames []string | 	zoneNames []string | ||||||
| 	zoneMap   map[string]bool | 	zoneMap   map[string]bool | ||||||
| @@ -52,38 +62,25 @@ func (m *Metrics) ZoneNames() []string { | |||||||
|  |  | ||||||
| // OnStartup sets up the metrics on startup. | // OnStartup sets up the metrics on startup. | ||||||
| func (m *Metrics) OnStartup() error { | func (m *Metrics) OnStartup() error { | ||||||
| 	m.Once.Do(func() { |  | ||||||
|  |  | ||||||
| 	ln, err := net.Listen("tcp", m.Addr) | 	ln, err := net.Listen("tcp", m.Addr) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Printf("[ERROR] Failed to start metrics handler: %s", err) | 		log.Printf("[ERROR] Failed to start metrics handler: %s", err) | ||||||
| 			return | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	m.ln = ln | 	m.ln = ln | ||||||
| 	ListenAddr = m.ln.Addr().String() | 	ListenAddr = m.ln.Addr().String() | ||||||
|  |  | ||||||
| 	m.mux = http.NewServeMux() | 	m.mux = http.NewServeMux() | ||||||
|  |  | ||||||
| 		prometheus.MustRegister(vars.RequestCount) |  | ||||||
| 		prometheus.MustRegister(vars.RequestDuration) |  | ||||||
| 		prometheus.MustRegister(vars.RequestSize) |  | ||||||
| 		prometheus.MustRegister(vars.RequestDo) |  | ||||||
| 		prometheus.MustRegister(vars.RequestType) |  | ||||||
|  |  | ||||||
| 		prometheus.MustRegister(vars.ResponseSize) |  | ||||||
| 		prometheus.MustRegister(vars.ResponseRcode) |  | ||||||
|  |  | ||||||
| 	m.mux.Handle("/metrics", prometheus.Handler()) | 	m.mux.Handle("/metrics", prometheus.Handler()) | ||||||
|  |  | ||||||
| 	go func() { | 	go func() { | ||||||
| 		http.Serve(m.ln, m.mux) | 		http.Serve(m.ln, m.mux) | ||||||
| 	}() | 	}() | ||||||
| 	}) |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // OnShutdown tears down the metrics on shutdown. | // OnShutdown tears down the metrics on shutdown and restart. | ||||||
| func (m *Metrics) OnShutdown() error { | func (m *Metrics) OnShutdown() error { | ||||||
| 	if m.ln != nil { | 	if m.ln != nil { | ||||||
| 		return m.ln.Close() | 		return m.ln.Close() | ||||||
|   | |||||||
| @@ -28,9 +28,10 @@ func setup(c *caddy.Controller) error { | |||||||
| 		return m | 		return m | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
|  | 	// During restarts we will keep this handler running. | ||||||
| 	metricsOnce.Do(func() { | 	metricsOnce.Do(func() { | ||||||
| 		c.OnStartup(m.OnStartup) | 		c.OncePerServerBlock(m.OnStartup) | ||||||
| 		c.OnShutdown(m.OnShutdown) | 		c.OnFinalShutdown(m.OnShutdown) | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user