diff --git a/handlers/paniccheck.go b/handlers/paniccheck.go index 482f54b0..e95e530a 100644 --- a/handlers/paniccheck.go +++ b/handlers/paniccheck.go @@ -4,7 +4,7 @@ import ( "fmt" "log/slog" "net/http" - "runtime" + "runtime/debug" "github.com/urfave/negroni/v3" @@ -41,7 +41,7 @@ func (p *panicCheck) ServeHTTP(rw http.ResponseWriter, r *http.Request, next htt err = fmt.Errorf("%v", rec) } logger := LoggerWithTraceInfo(p.logger, r) - logger.Error("panic-check", slog.String("host", r.Host), log.ErrAttr(err), slog.Any("stacktrace", runtime.StartTrace())) + logger.Error("panic-check", slog.String("host", r.Host), log.ErrAttr(err), slog.String("stacktrace", string(debug.Stack()))) rw.Header().Set(router_http.CfRouterError, "unknown_failure") rw.WriteHeader(http.StatusBadGateway) diff --git a/handlers/paniccheck_test.go b/handlers/paniccheck_test.go index d44550d4..1474ff65 100644 --- a/handlers/paniccheck_test.go +++ b/handlers/paniccheck_test.go @@ -4,6 +4,7 @@ import ( "errors" "net/http" "net/http/httptest" + "regexp" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -57,6 +58,9 @@ var _ = Describe("Paniccheck", func() { Eventually(logger).Should(gbytes.Say("somehost.com")) Eventually(logger).Should(gbytes.Say("we expect this panic")) Eventually(logger).Should(gbytes.Say("stacktrace")) + + // check that the stack trace is there and mentions the panicCheck handler. + Eventually(logger).Should(gbytes.Say(regexp.QuoteMeta("handlers.(*panicCheck)"))) }) }) diff --git a/logger/logger.go b/logger/logger.go index 9b4d6a20..6cee94da 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -126,7 +126,11 @@ func initializeLogger() *slog.Logger { conf.level, ) - zapHandler := zapslog.NewHandler(zapCore, zapslog.WithCaller(true)) + // Disable adding the stack trace to all error messages automatically. + // The stack trace in the panic handler is added manually and remains in effect. + disableErrorStacktrace := zapslog.AddStacktraceAt(slog.LevelError + 1) + + zapHandler := zapslog.NewHandler(zapCore, zapslog.WithCaller(true), disableErrorStacktrace) slogFrontend := slog.New(zapHandler) return slogFrontend } diff --git a/logger/logger_test.go b/logger/logger_test.go index f0617e8e..2c7bb5ed 100644 --- a/logger/logger_test.go +++ b/logger/logger_test.go @@ -167,6 +167,25 @@ var _ = Describe("Logger", func() { }) }) + Describe("Error", func() { + Context("when an error is logged with 'Error' level", func() { + JustBeforeEach(func() { + logger = log.CreateLogger() + }) + It("outputs an error log message without stack trace", func() { + Expect(func() { logger.Error(action) }).NotTo(Panic()) + + Expect(testSink.Lines()).To(HaveLen(1)) + Expect(testSink.Lines()[0]).To(MatchRegexp( + `{"log_level":3,"timestamp":[0-9]+[.][0-9]+,"message":"%s"`, + action, + )) + Expect(testSink.Lines()[0]).NotTo(ContainSubstring("stack_trace")) + Expect(testSink.Lines()[0]).NotTo(ContainSubstring("logger_test")) + }) + }) + }) + Describe("ErrAttr", func() { Context("when appending an error created by ErrAttr ", func() { JustBeforeEach(func() {