From d8714e64e400ef873c2adc4d929a07d7890727b9 Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Thu, 14 Sep 2017 09:36:06 +0100 Subject: Remove the word middleware (#1067) * Rename middleware to plugin first pass; mostly used 'sed', few spots where I manually changed text. This still builds a coredns binary. * fmt error * Rename AddMiddleware to AddPlugin * Readd AddMiddleware to remain backwards compat --- plugin/errors/errors.go | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 plugin/errors/errors.go (limited to 'plugin/errors/errors.go') diff --git a/plugin/errors/errors.go b/plugin/errors/errors.go new file mode 100644 index 000000000..a313f2e0d --- /dev/null +++ b/plugin/errors/errors.go @@ -0,0 +1,79 @@ +// Package errors implements an HTTP error handling plugin. +package errors + +import ( + "fmt" + "log" + "runtime" + "strings" + "time" + + "github.com/coredns/coredns/plugin" + "github.com/coredns/coredns/request" + + "github.com/miekg/dns" + "golang.org/x/net/context" +) + +// errorHandler handles DNS errors (and errors from other plugin). +type errorHandler struct { + Next plugin.Handler + LogFile string + Log *log.Logger +} + +// ServeDNS implements the plugin.Handler interface. +func (h errorHandler) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { + defer h.recovery(ctx, w, r) + + rcode, err := plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r) + + if err != nil { + state := request.Request{W: w, Req: r} + errMsg := fmt.Sprintf("%s [ERROR %d %s %s] %v", time.Now().Format(timeFormat), rcode, state.Name(), state.Type(), err) + + h.Log.Println(errMsg) + } + + return rcode, err +} + +func (h errorHandler) Name() string { return "errors" } + +func (h errorHandler) recovery(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) { + rec := recover() + if rec == nil { + return + } + + // Obtain source of panic + // From: https://gist.github.com/swdunlop/9629168 + var name, file string // function name, file name + var line int + var pc [16]uintptr + n := runtime.Callers(3, pc[:]) + for _, pc := range pc[:n] { + fn := runtime.FuncForPC(pc) + if fn == nil { + continue + } + file, line = fn.FileLine(pc) + name = fn.Name() + if !strings.HasPrefix(name, "runtime.") { + break + } + } + + // Trim file path + delim := "/coredns/" + pkgPathPos := strings.Index(file, delim) + if pkgPathPos > -1 && len(file) > pkgPathPos+len(delim) { + file = file[pkgPathPos+len(delim):] + } + + panicMsg := fmt.Sprintf("%s [PANIC %s %s] %s:%d - %v", time.Now().Format(timeFormat), r.Question[0].Name, dns.Type(r.Question[0].Qtype), file, line, rec) + // Currently we don't use the function name, since file:line is more conventional + h.Log.Printf(panicMsg) +} + +const timeFormat = "02/Jan/2006:15:04:05 -0700" -- cgit v1.2.3