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:
Miek Gieben
2017-02-21 19:34:40 +00:00
committed by GitHub
parent 26242cef1b
commit 7c59d39834
3 changed files with 33 additions and 29 deletions

View File

@@ -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.

View File

@@ -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()

View File

@@ -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