diff --git a/Gopkg.lock b/Gopkg.lock index d9e1c4b94..03b476bd6 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,7 +34,7 @@ version = "v3.5.1" [[projects]] - digest = "1:8f229e2b9f51a5f982f4a8cc500919cf5642eb69f5f06a36f172ff9cb7f2572d" + digest = "1:d6ee4ffea98d55414c11dacba60253cc81bd537c51f3972a7d5417124ce8d5af" name = "github.com/coredns/coredns" packages = [ "core/dnsserver", @@ -76,18 +76,18 @@ "request", ] pruneopts = "UT" - revision = "204537b3245bee2ed248ad587c83ba2cc4c129e9" - version = "v1.2.5" + revision = "756749c5cad4cd40453b82f70592bc19bb9ccb15" + version = "v1.2.6" [[projects]] - digest = "1:d46c6f1d6f4b07c6ef2bfe89a5ac9cda3f1772204d6a5ffb16dbd99c02d19ea1" + digest = "1:d2bf3686993c6674049180c5b3c608ceeae8fe99df6b9675594306fba9373b77" name = "github.com/coreos/etcd" packages = [ "client", "pkg/pathutil", "pkg/types", ] - pruneopts = "T" + pruneopts = "UT" revision = "61064a7be383053811e1535829a7b500feb7ef8f" version = "v3.1.0-rc.1-217-g61064a7be" diff --git a/Gopkg.toml b/Gopkg.toml index 77f4634a6..c8961f697 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -79,7 +79,7 @@ [[constraint]] name = "github.com/coredns/coredns" - version = "v1.2.5" + version = "v1.2.6" [[override]] name = "github.com/ugorji/go" diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/listen_go111.go b/vendor/github.com/coredns/coredns/core/dnsserver/listen_go111.go index 3d730df8e..d71c9292b 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/listen_go111.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/listen_go111.go @@ -8,19 +8,17 @@ import ( "net" "syscall" + "github.com/coredns/coredns/plugin/pkg/log" "golang.org/x/sys/unix" ) -const supportsReusePort = true - -func reuseportControl(network, address string, c syscall.RawConn) (opErr error) { - err := c.Control(func(fd uintptr) { - opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1) +func reuseportControl(network, address string, c syscall.RawConn) error { + c.Control(func(fd uintptr) { + if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil { + log.Warningf("Failed to set SO_REUSEPORT on socket: %s", err) + } }) - if err != nil { - return err - } - return opErr + return nil } func listen(network, addr string) (net.Listener, error) { diff --git a/vendor/github.com/coredns/coredns/coremain/run.go b/vendor/github.com/coredns/coredns/coremain/run.go index 033f60077..63ac6f354 100644 --- a/vendor/github.com/coredns/coredns/coremain/run.go +++ b/vendor/github.com/coredns/coredns/coremain/run.go @@ -62,7 +62,7 @@ func Run() { } log.SetOutput(os.Stdout) - log.SetFlags(log.LstdFlags) + log.SetFlags(0) // Set to 0 because we're doing our own time, with timezone if version { showVersion() diff --git a/vendor/github.com/coredns/coredns/coremain/version.go b/vendor/github.com/coredns/coredns/coremain/version.go index c6ff321b2..ae274821d 100644 --- a/vendor/github.com/coredns/coredns/coremain/version.go +++ b/vendor/github.com/coredns/coredns/coremain/version.go @@ -2,7 +2,7 @@ package coremain // Various CoreDNS constants. const ( - CoreVersion = "1.2.5" + CoreVersion = "1.2.6" coreName = "CoreDNS" serverType = "dns" ) diff --git a/vendor/github.com/coredns/coredns/plugin/cache/README.md b/vendor/github.com/coredns/coredns/plugin/cache/README.md index fcff72c58..ad2483ae9 100644 --- a/vendor/github.com/coredns/coredns/plugin/cache/README.md +++ b/vendor/github.com/coredns/coredns/plugin/cache/README.md @@ -24,8 +24,8 @@ cache [TTL] [ZONES...] * **ZONES** zones it should cache for. If empty, the zones from the configuration block are used. Each element in the cache is cached according to its TTL (with **TTL** as the max). -A cache is divided into 256 shards, each holding up to 512 items by default - for a total size -of 256 * 512 = 131,072 items. +A cache is divided into 256 shards, each holding up to 39 items by default - for a total size +of 256 * 39 = 9984 items. If you want more control: @@ -53,7 +53,8 @@ cache [TTL] [ZONES...] { ## Capacity and Eviction -If **CAPACITY** is not specified, the default cache size is 10,000 per cache. The minimum allowed cache size is 1024. +If **CAPACITY** _is not_ specified, the default cache size is 9984 per cache. The minimum allowed cache size is 1024. +If **CAPACITY** _is_ specified, the actual cache size used will be rounded down to the nearest number divisible by 256 (so all shards are equal in size). Eviction is done per shard. In effect, when a shard reaches capacity, items are evicted from that shard. Since shards don't fill up perfectly evenly, evictions will occur before the entire cache reaches full capacity. diff --git a/vendor/github.com/coredns/coredns/plugin/cache/cache.go b/vendor/github.com/coredns/coredns/plugin/cache/cache.go index 9ff43dac2..cd0fda505 100644 --- a/vendor/github.com/coredns/coredns/plugin/cache/cache.go +++ b/vendor/github.com/coredns/coredns/plugin/cache/cache.go @@ -2,7 +2,6 @@ package cache import ( - "encoding/binary" "hash/fnv" "net" "time" @@ -61,10 +60,10 @@ func New() *Cache { } } -// Return key under which we store the item, -1 will be returned if we don't store the -// message. +// key returns key under which we store the item, -1 will be returned if we don't store the message. // Currently we do not cache Truncated, errors zone transfers or dynamic update messages. -func key(m *dns.Msg, t response.Type, do bool) (bool, uint64) { +// qname holds the already lowercased qname. +func key(qname string, m *dns.Msg, t response.Type, do bool) (bool, uint64) { // We don't store truncated responses. if m.Truncated { return false, 0 @@ -74,7 +73,7 @@ func key(m *dns.Msg, t response.Type, do bool) (bool, uint64) { return false, 0 } - return true, hash(m.Question[0].Name, m.Question[0].Qtype, do) + return true, hash(qname, m.Question[0].Qtype, do) } var one = []byte("1") @@ -89,18 +88,9 @@ func hash(qname string, qtype uint16, do bool) uint64 { h.Write(zero) } - b := make([]byte, 2) - binary.BigEndian.PutUint16(b, qtype) - h.Write(b) - - for i := range qname { - c := qname[i] - if c >= 'A' && c <= 'Z' { - c += 'a' - 'A' - } - h.Write([]byte{c}) - } - + h.Write([]byte{byte(qtype >> 8)}) + h.Write([]byte{byte(qtype)}) + h.Write([]byte(qname)) return h.Sum64() } @@ -167,7 +157,7 @@ func (w *ResponseWriter) WriteMsg(res *dns.Msg) error { } // key returns empty string for anything we don't want to cache. - hasKey, key := key(res, mt, do) + hasKey, key := key(w.state.Name(), res, mt, do) msgTTL := dnsutil.MinimalTTL(res, mt) var duration time.Duration diff --git a/vendor/github.com/coredns/coredns/plugin/errors/README.md b/vendor/github.com/coredns/coredns/plugin/errors/README.md index f15b271f6..70ec3a2c3 100644 --- a/vendor/github.com/coredns/coredns/plugin/errors/README.md +++ b/vendor/github.com/coredns/coredns/plugin/errors/README.md @@ -6,16 +6,36 @@ ## Description -Any errors encountered during the query processing will be printed to standard output. +Any errors encountered during the query processing will be printed to standard output. The errors of particular type can be consolidated and printed once per some period of time. This plugin can only be used once per Server Block. ## Syntax +The basic syntax is: + ~~~ errors ~~~ +Extra knobs are available with an expanded syntax: + +~~~ +errors { + consolidate DURATION REGEXP +} +~~~ + +Option `consolidate` allows collecting several error messages matching the regular expression **REGEXP** during **DURATION**. After the **DURATION** since receiving the first such message, the consolidated message will be printed to standard output, e.g. + +~~~ +2 errors like '^read udp .* i/o timeout$' occurred in last 30s +~~~ + +Multiple `consolidate` options with different **DURATION** and **REGEXP** are allowed. In case if some error message corresponds to several defined regular expressions the message will be associated with the first appropriate **REGEXP**. + +For better performance, it's recomended to use the `^` or `$` metacharacters in regular expression when filtering error messages by prefix or suffix, e.g. `^failed to .*`, or `.* timeout$`. + ## Examples Use the *whoami* to respond to queries and Log errors to standard output. @@ -26,3 +46,15 @@ Use the *whoami* to respond to queries and Log errors to standard output. errors } ~~~ + +Use the *forward* to resolve queries via 8.8.8.8 and print consolidated error messages for errors with suffix " i/o timeout" or with prefix "Failed to ". + +~~~ corefile +. { + forward . 8.8.8.8 + errors { + consolidate 5m ".* i/o timeout$" + consolidate 30s "^Failed to .+" + } +} +~~~ diff --git a/vendor/github.com/coredns/coredns/plugin/errors/errors.go b/vendor/github.com/coredns/coredns/plugin/errors/errors.go index 88027b191..aa4b384b8 100644 --- a/vendor/github.com/coredns/coredns/plugin/errors/errors.go +++ b/vendor/github.com/coredns/coredns/plugin/errors/errors.go @@ -1,8 +1,12 @@ -// Package errors implements an HTTP error handling plugin. +// Package errors implements an error handling plugin. package errors import ( "context" + "regexp" + "sync/atomic" + "time" + "unsafe" "github.com/coredns/coredns/plugin" clog "github.com/coredns/coredns/plugin/pkg/log" @@ -11,19 +15,98 @@ import ( "github.com/miekg/dns" ) +var log = clog.NewWithPlugin("errors") + +type pattern struct { + ptimer unsafe.Pointer + count uint32 + period time.Duration + pattern *regexp.Regexp +} + +func (p *pattern) timer() *time.Timer { + return (*time.Timer)(atomic.LoadPointer(&p.ptimer)) +} + +func (p *pattern) setTimer(t *time.Timer) { + atomic.StorePointer(&p.ptimer, unsafe.Pointer(t)) +} + // errorHandler handles DNS errors (and errors from other plugin). -type errorHandler struct{ Next plugin.Handler } +type errorHandler struct { + patterns []*pattern + eLogger func(int, string, string, string) + cLogger func(uint32, string, time.Duration) + stopFlag uint32 + Next plugin.Handler +} + +func newErrorHandler() *errorHandler { + return &errorHandler{eLogger: errorLogger, cLogger: consLogger} +} + +func errorLogger(code int, qName, qType, err string) { + log.Errorf("%d %s %s: %s", code, qName, qType, err) +} + +func consLogger(cnt uint32, pattern string, p time.Duration) { + log.Errorf("%d errors like '%s' occured in last %s", cnt, pattern, p) +} + +func (h *errorHandler) logPattern(i int) { + cnt := atomic.SwapUint32(&h.patterns[i].count, 0) + if cnt > 0 { + h.cLogger(cnt, h.patterns[i].pattern.String(), h.patterns[i].period) + } +} + +func (h *errorHandler) inc(i int) bool { + if atomic.LoadUint32(&h.stopFlag) > 0 { + return false + } + if atomic.AddUint32(&h.patterns[i].count, 1) == 1 { + ind := i + t := time.AfterFunc(h.patterns[ind].period, func() { + h.logPattern(ind) + }) + h.patterns[ind].setTimer(t) + if atomic.LoadUint32(&h.stopFlag) > 0 && t.Stop() { + h.logPattern(ind) + } + } + return true +} + +func (h *errorHandler) stop() { + atomic.StoreUint32(&h.stopFlag, 1) + for i := range h.patterns { + t := h.patterns[i].timer() + if t != nil && t.Stop() { + h.logPattern(i) + } + } +} // ServeDNS implements the plugin.Handler interface. -func (h errorHandler) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { +func (h *errorHandler) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { rcode, err := plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r) if err != nil { + strErr := err.Error() + for i := range h.patterns { + if h.patterns[i].pattern.MatchString(strErr) { + if h.inc(i) { + return rcode, err + } + break + } + } state := request.Request{W: w, Req: r} - clog.Errorf("%d %s %s: %v", rcode, state.Name(), state.Type(), err) + h.eLogger(rcode, state.Name(), state.Type(), strErr) } return rcode, err } -func (h errorHandler) Name() string { return "errors" } +// Name implements the plugin.Handler interface. +func (h *errorHandler) Name() string { return "errors" } diff --git a/vendor/github.com/coredns/coredns/plugin/errors/setup.go b/vendor/github.com/coredns/coredns/plugin/errors/setup.go index d90928f74..42a5a40f5 100644 --- a/vendor/github.com/coredns/coredns/plugin/errors/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/errors/setup.go @@ -1,7 +1,8 @@ package errors import ( - "fmt" + "regexp" + "time" "github.com/coredns/coredns/core/dnsserver" "github.com/coredns/coredns/plugin" @@ -22,6 +23,11 @@ func setup(c *caddy.Controller) error { return plugin.Error("errors", err) } + c.OnShutdown(func() error { + handler.stop() + return nil + }) + dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler { handler.Next = next return handler @@ -30,13 +36,13 @@ func setup(c *caddy.Controller) error { return nil } -func errorsParse(c *caddy.Controller) (errorHandler, error) { - handler := errorHandler{} +func errorsParse(c *caddy.Controller) (*errorHandler, error) { + handler := newErrorHandler() i := 0 for c.Next() { if i > 0 { - return handler, plugin.ErrOnce + return nil, plugin.ErrOnce } i++ @@ -45,11 +51,39 @@ func errorsParse(c *caddy.Controller) (errorHandler, error) { case 0: case 1: if args[0] != "stdout" { - return handler, fmt.Errorf("invalid log file: %s", args[0]) + return nil, c.Errf("invalid log file: %s", args[0]) } default: - return handler, c.ArgErr() + return nil, c.ArgErr() + } + + for c.NextBlock() { + if err := parseBlock(c, handler); err != nil { + return nil, err + } } } return handler, nil } + +func parseBlock(c *caddy.Controller, h *errorHandler) error { + if c.Val() != "consolidate" { + return c.SyntaxErr("consolidate") + } + + args := c.RemainingArgs() + if len(args) != 2 { + return c.ArgErr() + } + p, err := time.ParseDuration(args[0]) + if err != nil { + return c.Err(err.Error()) + } + re, err := regexp.Compile(args[1]) + if err != nil { + return c.Err(err.Error()) + } + h.patterns = append(h.patterns, &pattern{period: p, pattern: re}) + + return nil +} diff --git a/vendor/github.com/coredns/coredns/plugin/log/README.md b/vendor/github.com/coredns/coredns/plugin/log/README.md index 65cca19c8..48e5acb6c 100644 --- a/vendor/github.com/coredns/coredns/plugin/log/README.md +++ b/vendor/github.com/coredns/coredns/plugin/log/README.md @@ -7,9 +7,10 @@ ## Description By just using *log* you dump all queries (and parts for the reply) on standard output. Options exist -to tweak the output a little. +to tweak the output a little. The date/time prefix on log lines is RFC3339 formatted with +milliseconds. -Note that for busy servers this will incur a performance hit. +Note that for busy servers logging will incur a performance hit. ## Syntax @@ -59,15 +60,14 @@ The following place holders are supported: * `{name}`: qname of the request * `{class}`: qclass of the request * `{proto}`: protocol used (tcp or udp) -* `{when}`: time of the query * `{remote}`: client's IP address, for IPv6 addresses these are enclosed in brackets: `[::1]` * `{size}`: request size in bytes * `{port}`: client's port * `{duration}`: response duration * `{rcode}`: response RCODE -* `{rsize}`: response size +* `{rsize}`: raw (uncompressed), response size (a client may receive a smaller response) * `{>rflags}`: response flags, each set flag will be displayed, e.g. "aa, tc". This includes the qr - bit as well. + bit as well * `{>bufsize}`: the EDNS0 buffer size advertised in the query * `{>do}`: is the EDNS0 DO (DNSSEC OK) bit set in the query * `{>id}`: query ID @@ -76,9 +76,15 @@ The following place holders are supported: The default Common Log Format is: ~~~ txt -`{remote}:{port} - [{when}] {>id} "{type} {class} {name} {proto} {size} {>do} {>bufsize}" {rcode} {>rflags} {rsize} {duration}` +`{remote}:{port} - {>id} "{type} {class} {name} {proto} {size} {>do} {>bufsize}" {rcode} {>rflags} {rsize} {duration}` ~~~ +Each of these logs will be outputted with `log.Infof`, so a typical example looks like this: + +~~~ txt +2018-10-30T19:10:07.547Z [INFO] [::1]:50759 - 29008 "A IN example.org. udp 41 false 4096" NOERROR qr,rd,ra,ad 68 0.037990251s +~~~~ + ## Examples Log all requests to stdout diff --git a/vendor/github.com/coredns/coredns/plugin/log/log.go b/vendor/github.com/coredns/coredns/plugin/log/log.go index f52a70344..685c55191 100644 --- a/vendor/github.com/coredns/coredns/plugin/log/log.go +++ b/vendor/github.com/coredns/coredns/plugin/log/log.go @@ -3,12 +3,12 @@ package log import ( "context" - "log" "time" "github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin/metrics/vars" "github.com/coredns/coredns/plugin/pkg/dnstest" + clog "github.com/coredns/coredns/plugin/pkg/log" "github.com/coredns/coredns/plugin/pkg/rcode" "github.com/coredns/coredns/plugin/pkg/replacer" "github.com/coredns/coredns/plugin/pkg/response" @@ -58,7 +58,7 @@ func (l Logger) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) // and we shouldn't have an empty rule.Class. if rule.Class[response.All] || rule.Class[class] { rep := replacer.New(r, rrw, CommonLogEmptyValue) - rule.Log.Println(rep.Replace(rule.Format)) + clog.Infof(rep.Replace(rule.Format)) } return rc, err @@ -75,12 +75,11 @@ type Rule struct { NameScope string Class map[response.Class]bool Format string - Log *log.Logger } const ( // CommonLogFormat is the common log format. - CommonLogFormat = `{remote}:{port} ` + CommonLogEmptyValue + ` [{when}] {>id} "{type} {class} {name} {proto} {size} {>do} {>bufsize}" {rcode} {>rflags} {rsize} {duration}` + CommonLogFormat = `{remote}:{port} ` + CommonLogEmptyValue + ` {>id} "{type} {class} {name} {proto} {size} {>do} {>bufsize}" {rcode} {>rflags} {rsize} {duration}` // CommonLogEmptyValue is the common empty log value. CommonLogEmptyValue = "-" // CombinedLogFormat is the combined log format. diff --git a/vendor/github.com/coredns/coredns/plugin/log/setup.go b/vendor/github.com/coredns/coredns/plugin/log/setup.go index 1f9501d68..c3c1af4ca 100644 --- a/vendor/github.com/coredns/coredns/plugin/log/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/log/setup.go @@ -1,9 +1,6 @@ package log import ( - "log" - "os" - "github.com/coredns/coredns/core/dnsserver" "github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin/pkg/response" @@ -25,15 +22,6 @@ func setup(c *caddy.Controller) error { return plugin.Error("log", err) } - // Open the log files for writing when the server starts - c.OnStartup(func() error { - for i := 0; i < len(rules); i++ { - rules[i].Log = log.New(os.Stdout, "", 0) - } - - return nil - }) - dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler { return Logger{Next: next, Rules: rules, ErrorFunc: dnsserver.DefaultErrorFunc} }) diff --git a/vendor/github.com/coredns/coredns/plugin/loop/loop.go b/vendor/github.com/coredns/coredns/plugin/loop/loop.go index 0624d3dd1..45bdc4267 100644 --- a/vendor/github.com/coredns/coredns/plugin/loop/loop.go +++ b/vendor/github.com/coredns/coredns/plugin/loop/loop.go @@ -77,6 +77,12 @@ func (l *Loop) inc() { l.i++ } +func (l *Loop) reset() { + l.Lock() + defer l.Unlock() + l.i = 0 +} + func (l *Loop) setDisabled() { l.Lock() defer l.Unlock() diff --git a/vendor/github.com/coredns/coredns/plugin/loop/setup.go b/vendor/github.com/coredns/coredns/plugin/loop/setup.go index 93a8bb13b..ba4681cb4 100644 --- a/vendor/github.com/coredns/coredns/plugin/loop/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/loop/setup.go @@ -42,6 +42,7 @@ func setup(c *caddy.Controller) error { for time.Now().Before(deadline) { if _, err := l.exchange(addr); err != nil { + l.reset() time.Sleep(1 * time.Second) continue } diff --git a/vendor/github.com/coredns/coredns/plugin/metrics/metrics.go b/vendor/github.com/coredns/coredns/plugin/metrics/metrics.go index 8efeff1e7..6b496cccc 100644 --- a/vendor/github.com/coredns/coredns/plugin/metrics/metrics.go +++ b/vendor/github.com/coredns/coredns/plugin/metrics/metrics.go @@ -57,7 +57,15 @@ func New(addr string) *Metrics { } // MustRegister wraps m.Reg.MustRegister. -func (m *Metrics) MustRegister(c prometheus.Collector) { m.Reg.MustRegister(c) } +func (m *Metrics) MustRegister(c prometheus.Collector) { + err := m.Reg.Register(c) + if err != nil { + // ignore any duplicate error, but fatal on any other kind of error + if _, ok := err.(prometheus.AlreadyRegisteredError); !ok { + log.Fatalf("Cannot register metrics collector: %s", err) + } + } +} // AddZone adds zone z to m. func (m *Metrics) AddZone(z string) { diff --git a/vendor/github.com/coredns/coredns/plugin/metrics/setup.go b/vendor/github.com/coredns/coredns/plugin/metrics/setup.go index c00f44a83..ffc0466f3 100644 --- a/vendor/github.com/coredns/coredns/plugin/metrics/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/metrics/setup.go @@ -31,6 +31,13 @@ func setup(c *caddy.Controller) error { return plugin.Error("prometheus", err) } + // register the metrics to its address (ensure only one active metrics per address) + obj := uniqAddr.Set(m.Addr, m.OnStartup, m) + //propagate the real active Registry to current metrics + if om, ok := obj.(*Metrics); ok { + m.Reg = om.Reg + } + dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler { m.Next = next return m @@ -55,10 +62,6 @@ func setup(c *caddy.Controller) error { func prometheusParse(c *caddy.Controller) (*Metrics, error) { var met = New(defaultAddr) - defer func() { - uniqAddr.Set(met.Addr, met.OnStartup) - }() - i := 0 for c.Next() { if i > 0 { diff --git a/vendor/github.com/coredns/coredns/plugin/pkg/log/log.go b/vendor/github.com/coredns/coredns/plugin/pkg/log/log.go index f05dce03a..2c8971e1d 100644 --- a/vendor/github.com/coredns/coredns/plugin/pkg/log/log.go +++ b/vendor/github.com/coredns/coredns/plugin/pkg/log/log.go @@ -1,11 +1,11 @@ // Package log implements a small wrapper around the std lib log package. -// It implements log levels by prefixing the logs with [INFO], [DEBUG], -// [WARNING] or [ERROR]. +// It implements log levels by prefixing the logs with the current time +// with in RFC3339Milli and [INFO], [DEBUG], [WARNING] or [ERROR]. // Debug logging is available and enabled if the *debug* plugin is used. // // log.Info("this is some logging"), will log on the Info level. // -// log.Debug("this is debug output"), will log in the Debug level. +// log.Debug("this is debug output"), will log in the Debug level, etc. package log import ( @@ -13,19 +13,24 @@ import ( "io/ioutil" golog "log" "os" + "time" ) // D controls whether we should output debug logs. If true, we do. var D bool +// RFC3339Milli doesn't exist, invent it here. +func clock() string { return time.Now().Format("2006-01-02T15:04:05.999Z07:00") } + // logf calls log.Printf prefixed with level. func logf(level, format string, v ...interface{}) { - s := level + fmt.Sprintf(format, v...) - golog.Print(s) + golog.Print(clock(), level, fmt.Sprintf(format, v...)) } // log calls log.Print prefixed with level. -func log(level string, v ...interface{}) { s := level + fmt.Sprint(v...); golog.Print(s) } +func log(level string, v ...interface{}) { + golog.Print(clock(), level, fmt.Sprint(v...)) +} // Debug is equivalent to log.Print(), but prefixed with "[DEBUG] ". It only outputs something // if D is true. @@ -75,9 +80,9 @@ func Fatalf(format string, v ...interface{}) { logf(fatal, format, v...); os.Exi func Discard() { golog.SetOutput(ioutil.Discard) } const ( - debug = "[DEBUG] " - err = "[ERROR] " - fatal = "[FATAL] " - info = "[INFO] " - warning = "[WARNING] " + debug = " [DEBUG] " + err = " [ERROR] " + fatal = " [FATAL] " + info = " [INFO] " + warning = " [WARNING] " ) diff --git a/vendor/github.com/coredns/coredns/plugin/pkg/replacer/replacer.go b/vendor/github.com/coredns/coredns/plugin/pkg/replacer/replacer.go index b9e1fcaa6..695e9e392 100644 --- a/vendor/github.com/coredns/coredns/plugin/pkg/replacer/replacer.go +++ b/vendor/github.com/coredns/coredns/plugin/pkg/replacer/replacer.go @@ -35,13 +35,11 @@ func New(r *dns.Msg, rr *dnstest.Recorder, emptyValue string) Replacer { req := request.Request{W: rr, Req: r} rep := replacer{ replacements: map[string]string{ - "{type}": req.Type(), - "{name}": req.Name(), - "{class}": req.Class(), - "{proto}": req.Proto(), - "{when}": func() string { - return time.Now().Format(timeFormat) - }(), + "{type}": req.Type(), + "{name}": req.Name(), + "{class}": req.Class(), + "{proto}": req.Proto(), + "{when}": "", // made a noop "{size}": strconv.Itoa(req.Len()), "{remote}": addrToRFC3986(req.IP()), "{port}": req.Port(), @@ -163,7 +161,4 @@ func addrToRFC3986(addr string) string { return addr } -const ( - timeFormat = "02/Jan/2006:15:04:05 -0700" - headerReplacer = "{>" -) +const headerReplacer = "{>" diff --git a/vendor/github.com/coredns/coredns/plugin/pkg/uniq/uniq.go b/vendor/github.com/coredns/coredns/plugin/pkg/uniq/uniq.go index 6dd74883d..f4b4f54a6 100644 --- a/vendor/github.com/coredns/coredns/plugin/pkg/uniq/uniq.go +++ b/vendor/github.com/coredns/coredns/plugin/pkg/uniq/uniq.go @@ -10,6 +10,7 @@ type U struct { type item struct { state int // either todo or done f func() error // function to be executed. + obj interface{} // any object to return when needed } // New returns a new initialized U. @@ -17,30 +18,21 @@ func New() U { return U{u: make(map[string]item)} } // Set sets function f in U under key. If the key already exists // it is not overwritten. -func (u U) Set(key string, f func() error) { - if _, ok := u.u[key]; ok { - return +func (u U) Set(key string, f func() error, o interface{}) interface{} { + if item, ok := u.u[key]; ok { + return item.obj } - u.u[key] = item{todo, f} + u.u[key] = item{todo, f, o} + return o } -// Unset removes the 'todo' associated with a key +// Unset removes the key. func (u U) Unset(key string) { if _, ok := u.u[key]; ok { delete(u.u, key) } } -// SetTodo sets key to 'todo' again. -func (u U) SetTodo(key string) { - v, ok := u.u[key] - if !ok { - return - } - v.state = todo - u.u[key] = v -} - // ForEach iterates for u executes f for each element that is 'todo' and sets it to 'done'. func (u U) ForEach() error { for k, v := range u.u { diff --git a/vendor/github.com/coredns/coredns/request/request.go b/vendor/github.com/coredns/coredns/request/request.go index f560612c8..260d73f5e 100644 --- a/vendor/github.com/coredns/coredns/request/request.go +++ b/vendor/github.com/coredns/coredns/request/request.go @@ -250,18 +250,16 @@ func (r *Request) Scrub(reply *dns.Msg) *dns.Msg { } // Account for the OPT record that gets added in SizeAndDo(), subtract that length. - sub := 0 + re := len(reply.Extra) if r.Req.IsEdns0() != nil { - sub = optLen + size -= optLen + // re can never be 0 because we have an OPT RR. + re-- } - // subtract to make spaces for re-added EDNS0 OPT RR. - re := len(reply.Extra) - sub - size -= sub - l, m := 0, 0 origExtra := reply.Extra - for l < re { + for l <= re { m = (l + re) / 2 reply.Extra = origExtra[:m] rl = reply.Len() @@ -278,13 +276,18 @@ func (r *Request) Scrub(reply *dns.Msg) *dns.Msg { } } - // We may come out of this loop with one rotation too many, m makes it too large, but m-1 works. + // The binary search only breaks on an exact match, which will be + // pretty rare. Normally, the loop will exit when l > re, meaning that + // in the previous iteration either: + // rl < size: no need to do anything. + // rl > size: the final size is too large, and if m > 0, the preceeding + // iteration the size was too small. Select that preceeding size. if rl > size && m > 0 { reply.Extra = origExtra[:m-1] rl = reply.Len() } - if rl < size { + if rl <= size { r.SizeAndDo(reply) return reply } @@ -292,7 +295,7 @@ func (r *Request) Scrub(reply *dns.Msg) *dns.Msg { ra := len(reply.Answer) l, m = 0, 0 origAnswer := reply.Answer - for l < ra { + for l <= ra { m = (l + ra) / 2 reply.Answer = origAnswer[:m] rl = reply.Len() @@ -309,7 +312,12 @@ func (r *Request) Scrub(reply *dns.Msg) *dns.Msg { } } - // We may come out of this loop with one rotation too many, m makes it too large, but m-1 works. + // The binary search only breaks on an exact match, which will be + // pretty rare. Normally, the loop will exit when l > ra, meaning that + // in the previous iteration either: + // rl < size: no need to do anything. + // rl > size: the final size is too large, and if m > 0, the preceeding + // iteration the size was too small. Select that preceeding size. if rl > size && m > 0 { reply.Answer = origAnswer[:m-1] // No need to recalc length, as we don't use it. We set truncated anyway. Doing