ipld-eth-server/vendor/gopkg.in/DataDog/dd-trace-go.v1/contrib/miekg/dns/dns.go
Rob Mulholand 560305f601 Update dependencies
- uses newer version of go-ethereum required for go1.11
2018-09-13 16:14:35 -05:00

112 lines
3.4 KiB
Go

package dns
import (
"context"
"errors"
"net"
"time"
"github.com/miekg/dns"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)
// ListenAndServe calls dns.ListenAndServe with a wrapped Handler.
func ListenAndServe(addr string, network string, handler dns.Handler) error {
return dns.ListenAndServe(addr, network, WrapHandler(handler))
}
// ListenAndServeTLS calls dns.ListenAndServeTLS with a wrapped Handler.
func ListenAndServeTLS(addr, certFile, keyFile string, handler dns.Handler) error {
return dns.ListenAndServeTLS(addr, certFile, keyFile, WrapHandler(handler))
}
// A Handler wraps a DNS Handler so that requests are traced.
type Handler struct {
dns.Handler
}
// WrapHandler creates a new, wrapped DNS handler.
func WrapHandler(handler dns.Handler) *Handler {
return &Handler{
Handler: handler,
}
}
// ServeDNS dispatches requests to the underlying Handler. All requests will be
// traced.
func (h *Handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
span, _ := startSpan(context.Background(), r.Opcode)
rw := &responseWriter{ResponseWriter: w}
h.Handler.ServeDNS(rw, r)
span.Finish(tracer.WithError(rw.err))
}
type responseWriter struct {
dns.ResponseWriter
err error
}
// WriteMsg writes the message to the response writer. If a non-success rcode is
// set the error in the struct will be non-nil.
func (rw *responseWriter) WriteMsg(msg *dns.Msg) error {
if msg.Rcode != dns.RcodeSuccess {
rw.err = errors.New(dns.RcodeToString[msg.Rcode])
}
return rw.ResponseWriter.WriteMsg(msg)
}
// Exchange calls dns.Exchange and traces the request.
func Exchange(m *dns.Msg, addr string) (r *dns.Msg, err error) {
span, _ := startSpan(context.Background(), m.Opcode)
r, err = dns.Exchange(m, addr)
span.Finish(tracer.WithError(err))
return r, err
}
// ExchangeConn calls dns.ExchangeConn and traces the request.
func ExchangeConn(c net.Conn, m *dns.Msg) (r *dns.Msg, err error) {
span, _ := startSpan(context.Background(), m.Opcode)
r, err = dns.ExchangeConn(c, m)
span.Finish(tracer.WithError(err))
return r, err
}
// ExchangeContext calls dns.ExchangeContext and traces the request.
func ExchangeContext(ctx context.Context, m *dns.Msg, addr string) (r *dns.Msg, err error) {
span, ctx := startSpan(ctx, m.Opcode)
r, err = dns.ExchangeContext(ctx, m, addr)
span.Finish(tracer.WithError(err))
return r, err
}
// A Client wraps a DNS Client so that requests are traced.
type Client struct {
*dns.Client
}
// Exchange calls the underlying Client.Exchange and traces the request.
func (c *Client) Exchange(m *dns.Msg, addr string) (r *dns.Msg, rtt time.Duration, err error) {
span, _ := startSpan(context.Background(), m.Opcode)
r, rtt, err = c.Client.Exchange(m, addr)
span.Finish(tracer.WithError(err))
return r, rtt, err
}
// ExchangeContext calls the underlying Client.ExchangeContext and traces the request.
func (c *Client) ExchangeContext(ctx context.Context, m *dns.Msg, addr string) (r *dns.Msg, rtt time.Duration, err error) {
span, ctx := startSpan(ctx, m.Opcode)
r, rtt, err = c.Client.ExchangeContext(ctx, m, addr)
span.Finish(tracer.WithError(err))
return r, rtt, err
}
func startSpan(ctx context.Context, opcode int) (ddtrace.Span, context.Context) {
return tracer.StartSpanFromContext(ctx, "dns.request",
tracer.ServiceName("dns"),
tracer.ResourceName(dns.OpcodeToString[opcode]),
tracer.SpanType(ext.SpanTypeDNS))
}