diff --git a/core/setup/metrics.go b/core/setup/metrics.go new file mode 100644 index 000000000..84fdadb29 --- /dev/null +++ b/core/setup/metrics.go @@ -0,0 +1,74 @@ +package setup + +import ( + "sync" + + "github.com/miekg/coredns/middleware" + "github.com/miekg/coredns/middleware/metrics" +) + +const ( + path = "/metrics" + addr = "localhost:9135" // 9153 is occupied by bind_exporter +) + +var once sync.Once + +func Prometheus(c *Controller) (middleware.Middleware, error) { + met, err := parsePrometheus(c) + if err != nil { + return nil, err + } + + once.Do(func() { + c.Startup = append(c.Startup, met.Start) + }) + + return func(next middleware.Handler) middleware.Handler { + met.Next = next + return met + }, nil +} + +func parsePrometheus(c *Controller) (metrics.Metrics, error) { + var ( + met metrics.Metrics + err error + ) + + for c.Next() { + if len(met.ZoneNames) > 0 { + return metrics.Metrics{}, c.Err("metrics: can only have one metrics module per server") + } + met = metrics.Metrics{ZoneNames: c.ServerBlockHosts} + for i, _ := range met.ZoneNames { + met.ZoneNames[i] = middleware.Host(met.ZoneNames[i]).Normalize() + } + args := c.RemainingArgs() + + switch len(args) { + case 0: + case 1: + met.Addr = args[0] + default: + return metrics.Metrics{}, c.ArgErr() + } + for c.NextBlock() { + switch c.Val() { + case "address": + args = c.RemainingArgs() + if len(args) != 1 { + return metrics.Metrics{}, c.ArgErr() + } + met.Addr = args[0] + default: + return metrics.Metrics{}, c.Errf("metrics: unknown item: %s", c.Val()) + } + + } + } + if met.Addr == "" { + met.Addr = addr + } + return met, err +} diff --git a/core/setup/prometheus.go b/core/setup/prometheus.go deleted file mode 100644 index 9ab68b6a5..000000000 --- a/core/setup/prometheus.go +++ /dev/null @@ -1,74 +0,0 @@ -package setup - -import ( - "sync" - - "github.com/miekg/coredns/middleware" - prom "github.com/miekg/coredns/middleware/prometheus" -) - -const ( - path = "/metrics" - addr = "localhost:9135" // 9153 is occupied by bind_exporter -) - -var once sync.Once - -func Prometheus(c *Controller) (middleware.Middleware, error) { - metrics, err := parsePrometheus(c) - if err != nil { - return nil, err - } - - once.Do(func() { - c.Startup = append(c.Startup, metrics.Start) - }) - - return func(next middleware.Handler) middleware.Handler { - metrics.Next = next - return metrics - }, nil -} - -func parsePrometheus(c *Controller) (prom.Metrics, error) { - var ( - metrics prom.Metrics - err error - ) - - for c.Next() { - if len(metrics.ZoneNames) > 0 { - return prom.Metrics{}, c.Err("prometheus: can only have one metrics module per server") - } - metrics = prom.Metrics{ZoneNames: c.ServerBlockHosts} - for i, _ := range metrics.ZoneNames { - metrics.ZoneNames[i] = middleware.Host(metrics.ZoneNames[i]).Normalize() - } - args := c.RemainingArgs() - - switch len(args) { - case 0: - case 1: - metrics.Addr = args[0] - default: - return prom.Metrics{}, c.ArgErr() - } - for c.NextBlock() { - switch c.Val() { - case "address": - args = c.RemainingArgs() - if len(args) != 1 { - return prom.Metrics{}, c.ArgErr() - } - metrics.Addr = args[0] - default: - return prom.Metrics{}, c.Errf("prometheus: unknown item: %s", c.Val()) - } - - } - } - if metrics.Addr == "" { - metrics.Addr = addr - } - return metrics, err -} diff --git a/middleware/chaos/chaos.go b/middleware/chaos/chaos.go index f1725495f..506298de4 100644 --- a/middleware/chaos/chaos.go +++ b/middleware/chaos/chaos.go @@ -43,6 +43,7 @@ func (c Chaos) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) ( } m.Answer = []dns.RR{&dns.TXT{Hdr: hdr, Txt: []string{trim(hostname)}}} } + state.SizeAndDo(m) w.WriteMsg(m) return 0, nil } diff --git a/middleware/edns.go b/middleware/edns.go index aaab502e0..c60bbc44d 100644 --- a/middleware/edns.go +++ b/middleware/edns.go @@ -32,3 +32,14 @@ func Edns0Version(req *dns.Msg) (*dns.Msg, error) { return m, errors.New("EDNS0 BADVERS") } + +// edns0Size returns a normalized size based on proto. +func edns0Size(proto string, size int) int { + if proto == "tcp" { + return dns.MaxMsgSize + } + if size < dns.MinMsgSize { + return dns.MinMsgSize + } + return size +} diff --git a/middleware/errors/errors.go b/middleware/errors/errors.go index dbef5770a..0639aadbf 100644 --- a/middleware/errors/errors.go +++ b/middleware/errors/errors.go @@ -37,6 +37,7 @@ func (h ErrorHandler) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns answer := debugMsg(rcode, r) txt, _ := dns.NewRR(". IN 0 TXT " + errMsg) answer.Answer = append(answer.Answer, txt) + state.SizeAndDo(answer) w.WriteMsg(answer) return 0, err } @@ -52,6 +53,7 @@ func (h ErrorHandler) recovery(ctx context.Context, w dns.ResponseWriter, r *dns return } + state := middleware.State{W: w, Req: r} // Obtain source of panic // From: https://gist.github.com/swdunlop/9629168 var name, file string // function name, file name @@ -86,6 +88,7 @@ func (h ErrorHandler) recovery(ctx context.Context, w dns.ResponseWriter, r *dns // add stack buf in TXT, limited to 255 chars for now. txt, _ := dns.NewRR(". IN 0 TXT " + string(stack[:255])) answer.Answer = append(answer.Answer, txt) + state.SizeAndDo(answer) w.WriteMsg(answer) } else { // Currently we don't use the function name, since file:line is more conventional diff --git a/middleware/etcd/handler.go b/middleware/etcd/handler.go index 0292049cd..6488e7549 100644 --- a/middleware/etcd/handler.go +++ b/middleware/etcd/handler.go @@ -66,46 +66,40 @@ func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i return 0, nil } if isEtcdNameError(err) { - m := new(dns.Msg) - m.SetRcode(state.Req, dns.RcodeNameError) - m.Ns = []dns.RR{e.SOA(zone, state)} - state.W.WriteMsg(m) - return dns.RcodeNameError, nil + return e.Err(zone, dns.RcodeNameError, state) } if err != nil { return dns.RcodeServerFailure, err } if len(records) == 0 { - // NODATE function, see below - m := new(dns.Msg) - m.SetReply(state.Req) - m.Ns = []dns.RR{e.SOA(zone, state)} - state.W.WriteMsg(m) - return dns.RcodeSuccess, nil - } - if len(records) > 0 { - m.Answer = append(m.Answer, records...) - } - if len(extra) > 0 { - m.Extra = append(m.Extra, extra...) + return e.Err(zone, dns.RcodeSuccess, state) } + m.Answer = append(m.Answer, records...) + m.Extra = append(m.Extra, extra...) + m = dedup(m) + state.SizeAndDo(m) m, _ = state.Scrub(m) - state.W.WriteMsg(m) - return 0, nil + w.WriteMsg(m) + return dns.RcodeSuccess, nil } // NoData write a nodata response to the client. -func (e Etcd) NoData(zone string, state middleware.State) { - // TODO(miek): write it +func (e Etcd) Err(zone string, rcode int, state middleware.State) (int, error) { + m := new(dns.Msg) + m.SetRcode(state.Req, rcode) + m.Ns = []dns.RR{e.SOA(zone, state)} + state.SizeAndDo(m) + state.W.WriteMsg(m) + return rcode, nil } func dedup(m *dns.Msg) *dns.Msg { - ma := make(map[string]dns.RR) - m.Answer = dns.Dedup(m.Answer, ma) - m.Ns = dns.Dedup(m.Ns, ma) - m.Extra = dns.Dedup(m.Extra, ma) + // TODO(miek): expensive! + m.Answer = dns.Dedup(m.Answer, nil) + m.Ns = dns.Dedup(m.Ns, nil) + m.Extra = dns.Dedup(m.Extra, nil) return m } diff --git a/middleware/etcd/stub_handler.go b/middleware/etcd/stub_handler.go index 9e8facf15..44a2f9ce8 100644 --- a/middleware/etcd/stub_handler.go +++ b/middleware/etcd/stub_handler.go @@ -22,14 +22,15 @@ func (s Stub) ServeDNS(ctx context.Context, w dns.ResponseWriter, req *dns.Msg) if !ok { // somebody made a mistake.. return dns.RcodeServerFailure, nil } - state := middleware.State{W: w, Req: req} - m1, e1 := proxy.Forward(state) - if e1 != nil { - return dns.RcodeServerFailure, e1 + state := middleware.State{W: w, Req: req} + m, e := proxy.Forward(state) + if e != nil { + return dns.RcodeServerFailure, e } - m1.RecursionAvailable, m1.Compress = true, true - state.W.WriteMsg(m1) + m.RecursionAvailable, m.Compress = true, true + state.SizeAndDo(m) + w.WriteMsg(m) return dns.RcodeSuccess, nil } diff --git a/middleware/file/dnssec_test.go b/middleware/file/dnssec_test.go index d00866f38..f7e641d7f 100644 --- a/middleware/file/dnssec_test.go +++ b/middleware/file/dnssec_test.go @@ -20,6 +20,7 @@ var dnssecTestCases = []coretest.Case{ coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="), coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), }, + Extra: []dns.RR{coretest.OPT(4096, true)}, }, { Qname: "miek.nl.", Qtype: dns.TypeAAAA, Do: true, @@ -27,6 +28,7 @@ var dnssecTestCases = []coretest.Case{ coretest.AAAA("miek.nl. 1800 IN AAAA 2a01:7e00::f03c:91ff:fef1:6735"), coretest.RRSIG("miek.nl. 1800 IN RRSIG AAAA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. SsRT="), }, + Extra: []dns.RR{coretest.OPT(4096, true)}, }, { Qname: "miek.nl.", Qtype: dns.TypeMX, Do: true, @@ -38,6 +40,7 @@ var dnssecTestCases = []coretest.Case{ coretest.MX("miek.nl. 1800 IN MX 5 alt2.aspmx.l.google.com."), coretest.RRSIG("miek.nl. 1800 IN RRSIG MX 8 2 1800 20160426031301 20160327031301 12051 miek.nl. kLqG+iOr="), }, + Extra: []dns.RR{coretest.OPT(4096, true)}, }, { Qname: "www.miek.nl.", Qtype: dns.TypeA, Do: true, @@ -46,6 +49,7 @@ var dnssecTestCases = []coretest.Case{ }, Extra: []dns.RR{ + coretest.OPT(4096, true), coretest.A("a.miek.nl. 1800 IN A 139.162.196.78"), coretest.RRSIG("a.miek.nl. 1800 IN RRSIG A 8 3 1800 20160426031301 20160327031301 12051 miek.nl. lxLotCjWZ3kihTxk="), }, @@ -59,6 +63,7 @@ var dnssecTestCases = []coretest.Case{ coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="), coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), }, + Extra: []dns.RR{coretest.OPT(4096, true)}, }, { Qname: "b.miek.nl.", Qtype: dns.TypeA, Do: true, @@ -71,6 +76,7 @@ var dnssecTestCases = []coretest.Case{ coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="), coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), }, + Extra: []dns.RR{coretest.OPT(4096, true)}, }, { Qname: "b.blaat.miek.nl.", Qtype: dns.TypeA, Do: true, @@ -83,6 +89,7 @@ var dnssecTestCases = []coretest.Case{ coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="), coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), }, + Extra: []dns.RR{coretest.OPT(4096, true)}, }, { Qname: "b.a.miek.nl.", Qtype: dns.TypeA, Do: true, @@ -94,6 +101,7 @@ var dnssecTestCases = []coretest.Case{ coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="), coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), }, + Extra: []dns.RR{coretest.OPT(4096, true)}, }, } diff --git a/middleware/file/ent_test.go b/middleware/file/ent_test.go index 8059390fe..38455b2b5 100644 --- a/middleware/file/ent_test.go +++ b/middleware/file/ent_test.go @@ -27,6 +27,7 @@ var entTestCases = []coretest.Case{ coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160502144311 20160402144311 12051 miek.nl. KegoBxA3Tbrhlc4cEdkRiteIkOfsq"), coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), }, + Extra: []dns.RR{coretest.OPT(4096, true)}, }, } diff --git a/middleware/file/file.go b/middleware/file/file.go index fcb1ce6e2..a81858211 100644 --- a/middleware/file/file.go +++ b/middleware/file/file.go @@ -25,6 +25,7 @@ type ( func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { state := middleware.State{W: w, Req: r} + if state.QClass() != dns.ClassINET { return dns.RcodeServerFailure, fmt.Errorf("can only deal with ClassINET") } @@ -45,6 +46,7 @@ func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i m := new(dns.Msg) m.SetReply(r) m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true + state.SizeAndDo(m) w.WriteMsg(m) log.Printf("[INFO] Notify from %s for %s: checking transfer", state.IP(), zone) @@ -93,6 +95,8 @@ func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i case ServerFailure: return dns.RcodeServerFailure, nil } + + state.SizeAndDo(m) m, _ = state.Scrub(m) w.WriteMsg(m) return dns.RcodeSuccess, nil diff --git a/middleware/file/wildcard_test.go b/middleware/file/wildcard_test.go index 9d0e614aa..703938a4e 100644 --- a/middleware/file/wildcard_test.go +++ b/middleware/file/wildcard_test.go @@ -25,6 +25,7 @@ var wildcardTestCases = []coretest.Case{ coretest.RRSIG("wild.dnssex.nl. 1800 IN RRSIG TXT 8 2 1800 20160428190224 20160329190224 14460 dnssex.nl. FUZSTyvZfeuuOpCm"), coretest.TXT(`wild.dnssex.nl. 1800 IN TXT "Doing It Safe Is Better"`), }, + Extra: []dns.RR{coretest.OPT(4096, true)}, }, // nodata reponse /* diff --git a/middleware/log/log.go b/middleware/log/log.go index ba5dba40c..1e0656fc7 100644 --- a/middleware/log/log.go +++ b/middleware/log/log.go @@ -3,11 +3,13 @@ package log import ( "log" - - "golang.org/x/net/context" + "time" "github.com/miekg/coredns/middleware" + "github.com/miekg/coredns/middleware/metrics" + "github.com/miekg/dns" + "golang.org/x/net/context" ) // Logger is a basic request logging middleware. @@ -30,9 +32,13 @@ func (l Logger) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) if l.ErrorFunc != nil { l.ErrorFunc(responseRecorder, r, rcode) } else { - // Default failover error handler + rc := middleware.RcodeToString(rcode) + answer := new(dns.Msg) answer.SetRcode(r, rcode) + state.SizeAndDo(answer) + + metrics.Report(metrics.Dropped, state.Type(), rc, answer.Len(), time.Now()) w.WriteMsg(answer) } rcode = 0 diff --git a/middleware/prometheus/README.md b/middleware/metrics/README.md similarity index 100% rename from middleware/prometheus/README.md rename to middleware/metrics/README.md diff --git a/middleware/prometheus/handler.go b/middleware/metrics/handler.go similarity index 100% rename from middleware/prometheus/handler.go rename to middleware/metrics/handler.go diff --git a/middleware/prometheus/metrics.go b/middleware/metrics/metrics.go similarity index 94% rename from middleware/prometheus/metrics.go rename to middleware/metrics/metrics.go index 8e40d6d7d..7a3c46f2e 100644 --- a/middleware/prometheus/metrics.go +++ b/middleware/metrics/metrics.go @@ -81,3 +81,6 @@ func define(subsystem string) { Help: "Counter of response status codes.", }, []string{"zone", "rcode", "qtype"}) } + +// Dropped indicates we dropped the query before any handling. It has no closing dot, so it can not be a valid zone. +const Dropped = "dropped" diff --git a/middleware/proxy/lookup.go b/middleware/proxy/lookup.go index 7aa4824e7..a401705f2 100644 --- a/middleware/proxy/lookup.go +++ b/middleware/proxy/lookup.go @@ -52,16 +52,13 @@ func New(hosts []string) Proxy { return p } -// Lookup will use name and tpe to forge a new message and will send that upstream. It will +// Lookup will use name and type to forge a new message and will send that upstream. It will // set any EDNS0 options correctly so that downstream will be able to process the reply. -// Lookup is not suitable for forwarding request. So Forward for that. +// Lookup is not suitable for forwarding request. Ssee for that. func (p Proxy) Lookup(state middleware.State, name string, tpe uint16) (*dns.Msg, error) { req := new(dns.Msg) req.SetQuestion(name, tpe) - - opt := state.SizeAndDo() - req.Extra = []dns.RR{opt} - + state.SizeAndDo(req) return p.lookup(state, req) } diff --git a/middleware/state.go b/middleware/state.go index fb324d780..9a368390b 100644 --- a/middleware/state.go +++ b/middleware/state.go @@ -110,43 +110,41 @@ func (s *State) Size() int { return s.size } - if s.Proto() == "tcp" { - s.size = dns.MaxMsgSize - return dns.MaxMsgSize - } + size := 0 if o := s.Req.IsEdns0(); o != nil { if o.Do() == true { s.do = doTrue } else { s.do = doFalse } - - size := o.UDPSize() - if size < dns.MinMsgSize { - size = dns.MinMsgSize - } - s.size = int(size) - return int(size) + size = int(o.UDPSize()) } - s.size = dns.MinMsgSize - return dns.MinMsgSize + size = edns0Size(s.Proto(), size) + s.size = size + return size } -// SizeAndDo returns a ready made OPT record that the reflects the intent from -// state. This can be added to upstream requests that will then hopefully -// return a message that is fits the buffer in the client. -func (s *State) SizeAndDo() *dns.OPT { +// SizeAndDo adds an OPT record that the reflects the intent from state. +// The returned bool indicated if an record was added. +func (s *State) SizeAndDo(m *dns.Msg) bool { + o := s.Req.IsEdns0() // TODO(miek): speed this up + if o == nil { + return false + } + size := s.Size() Do := s.Do() - o := new(dns.OPT) o.Hdr.Name = "." o.Hdr.Rrtype = dns.TypeOPT + o.SetVersion(0) o.SetUDPSize(uint16(size)) if Do { o.SetDo() } - return o + // TODO(miek): test how this works with stub forwarding in etcd middleware. + m.Extra = append(m.Extra, o) + return true } // Result is the result of Scrub. @@ -170,9 +168,11 @@ func (s *State) Scrub(reply *dns.Msg) (*dns.Msg, Result) { if size >= l { return reply, ScrubIgnored } - // If not delegation, drop additional section. // TODO(miek): check for delegation + + // If not delegation, drop additional section. reply.Extra = nil + s.SizeAndDo(reply) l = reply.Len() if size >= l { return reply, ScrubDone diff --git a/middleware/testing/helpers.go b/middleware/testing/helpers.go index e2b098cc7..49264ea1c 100644 --- a/middleware/testing/helpers.go +++ b/middleware/testing/helpers.go @@ -57,6 +57,18 @@ func MX(rr string) *dns.MX { r, _ := dns.NewRR(rr); return r.(*dns.MX) } func RRSIG(rr string) *dns.RRSIG { r, _ := dns.NewRR(rr); return r.(*dns.RRSIG) } func NSEC(rr string) *dns.NSEC { r, _ := dns.NewRR(rr); return r.(*dns.NSEC) } +func OPT(bufsize int, do bool) *dns.OPT { + o := new(dns.OPT) + o.Hdr.Name = "." + o.Hdr.Rrtype = dns.TypeOPT + o.SetVersion(0) + o.SetUDPSize(uint16(bufsize)) + if do { + o.SetDo() + } + return o +} + func Header(t *testing.T, tc Case, resp *dns.Msg) bool { if resp.Rcode != tc.Rcode { t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode]) @@ -192,6 +204,16 @@ func Section(t *testing.T, tc Case, sect Sect, rr []dns.RR) bool { t.Errorf("NS nameserver should be %q, but is %q", x.Ns, tt.Ns) return false } + case *dns.OPT: + tt := section[i].(*dns.OPT) + if x.Do() != tt.Do() { + t.Errorf("OPT DO should be %q, but is %q", x.Do(), tt.Do()) + return false + } + if x.UDPSize() != tt.UDPSize() { + t.Errorf("OPT UDPSize should be %q, but is %q", x.UDPSize(), tt.UDPSize()) + return false + } } } return true diff --git a/server/server.go b/server/server.go index 7ea931daa..ddf4e5dc3 100644 --- a/server/server.go +++ b/server/server.go @@ -17,7 +17,7 @@ import ( "github.com/miekg/coredns/middleware" "github.com/miekg/coredns/middleware/chaos" - "github.com/miekg/coredns/middleware/prometheus" + "github.com/miekg/coredns/middleware/metrics" "github.com/miekg/dns" "golang.org/x/net/context" @@ -282,7 +282,7 @@ func (s *Server) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { if m, err := middleware.Edns0Version(r); err != nil { // Wrong EDNS version, return at once. qtype := dns.Type(r.Question[0].Qtype).String() rc := middleware.RcodeToString(dns.RcodeBadVers) - metrics.Report(dropped, qtype, rc, m.Len(), time.Now()) + metrics.Report(metrics.Dropped, qtype, rc, m.Len(), time.Now()) w.WriteMsg(m) return } @@ -336,17 +336,16 @@ func (s *Server) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { log.Printf("[INFO] %s - No such zone at %s (Remote: %s)", q, s.Addr, remoteHost) } -// DefaultErrorFunc responds to an HTTP request with a simple description -// of the specified HTTP status code. +// DefaultErrorFunc responds to an DNS request with an error. func DefaultErrorFunc(w dns.ResponseWriter, r *dns.Msg, rcode int) { - qtype := dns.Type(r.Question[0].Qtype).String() + state := middleware.State{W: w, Req: r} rc := middleware.RcodeToString(rcode) answer := new(dns.Msg) answer.SetRcode(r, rcode) - // Default zone to dropped (without closing dot, so no zone) here to not blow up this metric. - metrics.Report(dropped, qtype, rc, answer.Len(), time.Now()) + state.SizeAndDo(answer) + metrics.Report(metrics.Dropped, state.Type(), rc, answer.Len(), time.Now()) w.WriteMsg(answer) } @@ -459,5 +458,3 @@ func RcodeNoClientWrite(rcode int) bool { } return false } - -const dropped = "dropped"