diff --git a/README.md b/README.md index a76302e..e85ed03 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,12 @@ writing CoreDNS plugins. example ~~~ +## Metrics + +If monitoring is enabled (via the *prometheus* directive) the following metric is exported: + +* `coredns_example_request_count_total{server}` - query count to the *example* plugin. + ## Examples In this configuration, we forward all queries to 9.9.9.9 and print "example" whenever we recieve @@ -26,3 +32,7 @@ a query. example } ``` + +## Also See + +See the [manual](https://coredns.io/manual). diff --git a/example.go b/example.go index 51c14b7..deaba86 100644 --- a/example.go +++ b/example.go @@ -1,4 +1,6 @@ -// The example plugin prints example to stdout on every packet received. +// Package example is a CoreDNS plugin that prints "example" to stdout on every packet received. +// +// It serves as an example CoreDNS plugin with numerous code comments. package example import ( @@ -7,6 +9,7 @@ import ( "os" "github.com/coredns/coredns/plugin" + "github.com/coredns/coredns/plugin/metrics" "github.com/miekg/dns" "golang.org/x/net/context" @@ -28,6 +31,9 @@ func (e Example) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) // Wrap. pw := NewResponsePrinter(w) + // Export metric with the server label set to the current server handling the request. + requestCount.WithLabelValues(metrics.WithServer(ctx)).Add(1) + // Call next plugin (if any). return plugin.NextOrFailure(e.Name(), e.Next, ctx, pw, r) } diff --git a/metrics.go b/metrics.go new file mode 100644 index 0000000..c40d0b7 --- /dev/null +++ b/metrics.go @@ -0,0 +1,20 @@ +package example + +import ( + "sync" + + "github.com/coredns/coredns/plugin" + + "github.com/prometheus/client_golang/prometheus" +) + +// requestCount exports a prometheus metric that is incremented every time +// a query is seen by the example plugin. +var requestCount = prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: plugin.Namespace, + Subsystem: "example", + Name: "request_count_total", + Help: "Counter of requests made.", +}, []string{"server"}) + +var once sync.Once diff --git a/setup.go b/setup.go index 09ca01f..4006c51 100644 --- a/setup.go +++ b/setup.go @@ -3,6 +3,7 @@ package example import ( "github.com/coredns/coredns/core/dnsserver" "github.com/coredns/coredns/plugin" + "github.com/coredns/coredns/plugin/metrics" "github.com/mholt/caddy" ) @@ -27,6 +28,22 @@ func setup(c *caddy.Controller) error { return plugin.Error("example", c.ArgErr()) } + // Add a startup function that will -- after all plugins have been loaded -- check if the + // prometheus plugin has been used - if so we will export metrics. We can only register + // this metric once, hence the "once.Do". + c.OnStartup(func() error { + once.Do(func() { + m := dnsserver.GetConfig(c).Handler("prometheus") + if m == nil { + return + } + if x, ok := m.(*metrics.Metrics); ok { + x.MustRegister(requestCount) + } + }) + return nil + }) + // Add the Plugin to CoreDNS, so Servers can use it in their plugin chain. dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler { return Example{Next: next}