diff options
author | 2022-05-24 14:36:36 +0200 | |
---|---|---|
committer | 2022-05-24 14:36:36 +0200 | |
commit | 91bcbc2e3ada7c034e0cca022a717871684dd5ca (patch) | |
tree | dca40addd6e613bba2cef090455fa08ca1330e4b /plugin/errors | |
parent | b7e4f05f08e761fc71d7e7d2c85afd3ee6ef3542 (diff) | |
download | coredns-91bcbc2e3ada7c034e0cca022a717871684dd5ca.tar.gz coredns-91bcbc2e3ada7c034e0cca022a717871684dd5ca.tar.zst coredns-91bcbc2e3ada7c034e0cca022a717871684dd5ca.zip |
recover from panic log including stacktrace to help finding the origin (#5392)
Diffstat (limited to 'plugin/errors')
-rw-r--r-- | plugin/errors/README.md | 3 | ||||
-rw-r--r-- | plugin/errors/setup.go | 31 | ||||
-rw-r--r-- | plugin/errors/setup_test.go | 53 |
3 files changed, 53 insertions, 34 deletions
diff --git a/plugin/errors/README.md b/plugin/errors/README.md index 0cb0b375d..27ba1058a 100644 --- a/plugin/errors/README.md +++ b/plugin/errors/README.md @@ -22,10 +22,13 @@ Extra knobs are available with an expanded syntax: ~~~ errors { + stacktrace consolidate DURATION REGEXP [LEVEL] } ~~~ +Option `stacktrace` will log a stacktrace during panic recovery. + 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 with log level, which is configurable by optional option **LEVEL**. Supported options for **LEVEL** option are `warning`,`error`,`info` and `debug`. ~~~ diff --git a/plugin/errors/setup.go b/plugin/errors/setup.go index 67a9fe653..c040e102f 100644 --- a/plugin/errors/setup.go +++ b/plugin/errors/setup.go @@ -52,38 +52,41 @@ func errorsParse(c *caddy.Controller) (*errorHandler, error) { } for c.NextBlock() { - if err := parseBlock(c, handler); err != nil { - return nil, err + switch c.Val() { + case "stacktrace": + dnsserver.GetConfig(c).Stacktrace = true + case "consolidate": + pattern, err := parseConsolidate(c) + if err != nil { + return nil, err + } + handler.patterns = append(handler.patterns, pattern) + default: + return handler, c.SyntaxErr("Unknown field " + c.Val()) } } } return handler, nil } -func parseBlock(c *caddy.Controller, h *errorHandler) error { - if c.Val() != "consolidate" { - return c.SyntaxErr("consolidate") - } - +func parseConsolidate(c *caddy.Controller) (*pattern, error) { args := c.RemainingArgs() if len(args) < 2 || len(args) > 3 { - return c.ArgErr() + return nil, c.ArgErr() } p, err := time.ParseDuration(args[0]) if err != nil { - return c.Err(err.Error()) + return nil, c.Err(err.Error()) } re, err := regexp.Compile(args[1]) if err != nil { - return c.Err(err.Error()) + return nil, c.Err(err.Error()) } lc, err := parseLogLevel(c, args) if err != nil { - return err + return nil, err } - h.patterns = append(h.patterns, &pattern{period: p, pattern: re, logCallback: lc}) - - return nil + return &pattern{period: p, pattern: re, logCallback: lc}, nil } func parseLogLevel(c *caddy.Controller, args []string) (func(format string, v ...interface{}), error) { diff --git a/plugin/errors/setup_test.go b/plugin/errors/setup_test.go index 72fdbcd0a..6af6aea57 100644 --- a/plugin/errors/setup_test.go +++ b/plugin/errors/setup_test.go @@ -7,55 +7,64 @@ import ( "testing" "github.com/coredns/caddy" + "github.com/coredns/coredns/core/dnsserver" clog "github.com/coredns/coredns/plugin/pkg/log" ) func TestErrorsParse(t *testing.T) { tests := []struct { - inputErrorsRules string - shouldErr bool - optCount int + inputErrorsRules string + shouldErr bool + optCount int + stacktrace bool }{ - {`errors`, false, 0}, - {`errors stdout`, false, 0}, - {`errors errors.txt`, true, 0}, - {`errors visible`, true, 0}, - {`errors { log visible }`, true, 0}, + {`errors`, false, 0, false}, + {`errors stdout`, false, 0, false}, + {`errors errors.txt`, true, 0, false}, + {`errors visible`, true, 0, false}, + {`errors { log visible }`, true, 0, false}, {`errors - errors `, true, 0}, - {`errors a b`, true, 0}, + errors `, true, 0, false}, + {`errors a b`, true, 0, false}, {`errors { consolidate - }`, true, 0}, + }`, true, 0, false}, {`errors { consolidate 1m - }`, true, 0}, + }`, true, 0, false}, {`errors { consolidate 1m .* extra - }`, true, 0}, + }`, true, 0, false}, {`errors { consolidate abc .* - }`, true, 0}, + }`, true, 0, false}, {`errors { consolidate 1 .* - }`, true, 0}, + }`, true, 0, false}, {`errors { consolidate 1m ()) - }`, true, 0}, + }`, true, 0, false}, + {`errors { + stacktrace + }`, false, 0, true}, {`errors { + stacktrace consolidate 1m ^exact$ - }`, false, 1}, + }`, false, 1, true}, + {`errors { + consolidate 1m ^exact$ + }`, false, 1, false}, {`errors { consolidate 1m error - }`, false, 1}, + }`, false, 1, false}, {`errors { consolidate 1m "format error" - }`, false, 1}, + }`, false, 1, false}, {`errors { consolidate 1m error1 consolidate 5s error2 - }`, false, 2}, + }`, false, 2, false}, } for i, test := range tests { c := caddy.NewTestController("dns", test.inputErrorsRules) @@ -69,6 +78,10 @@ func TestErrorsParse(t *testing.T) { t.Errorf("Test %d: pattern count mismatch, expected %d, got %d", i, test.optCount, len(h.patterns)) } + if dnsserver.GetConfig(c).Stacktrace != test.stacktrace { + t.Errorf("Test %d: stacktrace, expected %t, got %t", + i, test.stacktrace, dnsserver.GetConfig(c).Stacktrace) + } } } |