middleware/proxy: add request duration monitoring (#362)
Add a separate request duration metrics specially for proxying requests upstream. Fixes #259
This commit is contained in:
parent
ba26f47d5c
commit
54964653d1
5 changed files with 52 additions and 2 deletions
|
@ -48,6 +48,15 @@ There are three load-balancing policies available:
|
||||||
All polices implement randomly spraying packets to backend hosts when *no healthy* hosts are
|
All polices implement randomly spraying packets to backend hosts when *no healthy* hosts are
|
||||||
available. This is to preeempt the case where the healthchecking (as a mechanism) fails.
|
available. This is to preeempt the case where the healthchecking (as a mechanism) fails.
|
||||||
|
|
||||||
|
## Metrics
|
||||||
|
|
||||||
|
If monitoring is enabled (via the *prometheus* directive) then the following metric is exported:
|
||||||
|
|
||||||
|
* coredns_proxy_request_count_total{zone, proto, family}
|
||||||
|
|
||||||
|
This has some overlap with `coredns_dns_request_count_total{zone, proto, family}`, but allows for
|
||||||
|
specifics on upstream query resolving. See the *prometheus* documentation for more details.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
Proxy all requests within example.org. to a backend system:
|
Proxy all requests within example.org. to a backend system:
|
||||||
|
|
32
middleware/proxy/metrics.go
Normal file
32
middleware/proxy/metrics.go
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/miekg/coredns/middleware"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Metrics the proxy middleware exports.
|
||||||
|
var (
|
||||||
|
RequestDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||||
|
Namespace: middleware.Namespace,
|
||||||
|
Subsystem: subsystem,
|
||||||
|
Name: "request_duration_milliseconds",
|
||||||
|
Buckets: append(prometheus.DefBuckets, []float64{50, 100, 200, 500, 1000, 2000, 3000, 4000, 5000, 10000}...),
|
||||||
|
Help: "Histogram of the time (in milliseconds) each request took.",
|
||||||
|
}, []string{"zone"})
|
||||||
|
)
|
||||||
|
|
||||||
|
// OnStartup sets up the metrics on startup.
|
||||||
|
func OnStartup() error {
|
||||||
|
metricsOnce.Do(func() {
|
||||||
|
prometheus.MustRegister(RequestDuration)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var metricsOnce sync.Once
|
||||||
|
|
||||||
|
const subsystem = "proxy"
|
|
@ -74,6 +74,9 @@ func (p Proxy) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
|
||||||
for time.Now().Sub(start) < tryDuration {
|
for time.Now().Sub(start) < tryDuration {
|
||||||
host := upstream.Select()
|
host := upstream.Select()
|
||||||
if host == nil {
|
if host == nil {
|
||||||
|
|
||||||
|
RequestDuration.WithLabelValues(upstream.From()).Observe(float64(time.Since(start) / time.Millisecond))
|
||||||
|
|
||||||
return dns.RcodeServerFailure, errUnreachable
|
return dns.RcodeServerFailure, errUnreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +88,9 @@ func (p Proxy) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
|
||||||
|
|
||||||
if backendErr == nil {
|
if backendErr == nil {
|
||||||
w.WriteMsg(reply)
|
w.WriteMsg(reply)
|
||||||
|
|
||||||
|
RequestDuration.WithLabelValues(upstream.From()).Observe(float64(time.Since(start) / time.Millisecond))
|
||||||
|
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
timeout := host.FailTimeout
|
timeout := host.FailTimeout
|
||||||
|
@ -97,6 +103,9 @@ func (p Proxy) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
|
||||||
atomic.AddInt32(&host.Fails, -1)
|
atomic.AddInt32(&host.Fails, -1)
|
||||||
}(host, timeout)
|
}(host, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RequestDuration.WithLabelValues(upstream.From()).Observe(float64(time.Since(start) / time.Millisecond))
|
||||||
|
|
||||||
return dns.RcodeServerFailure, errUnreachable
|
return dns.RcodeServerFailure, errUnreachable
|
||||||
}
|
}
|
||||||
return p.Next.ServeDNS(ctx, w, r)
|
return p.Next.ServeDNS(ctx, w, r)
|
||||||
|
|
|
@ -23,5 +23,7 @@ func setup(c *caddy.Controller) error {
|
||||||
return Proxy{Next: next, Client: newClient(), Upstreams: upstreams}
|
return Proxy{Next: next, Client: newClient(), Upstreams: upstreams}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
c.OnStartup(OnStartup)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,6 @@ import (
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This tests uses the exampleOrg zone as defined in proxy_test.go
|
|
||||||
|
|
||||||
func TestLookupCache(t *testing.T) {
|
func TestLookupCache(t *testing.T) {
|
||||||
// Start auth. CoreDNS holding the auth zone.
|
// Start auth. CoreDNS holding the auth zone.
|
||||||
name, rm, err := test.TempFile(".", exampleOrg)
|
name, rm, err := test.TempFile(".", exampleOrg)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue