diff --git a/internal/logging/panic.go b/internal/logging/panic.go index 960d4f685..211a1231d 100644 --- a/internal/logging/panic.go +++ b/internal/logging/panic.go @@ -172,11 +172,22 @@ func (l *logPanicWrapper) Debug(msg string, args ...interface{}) { // output if this is the start of the traceback. An occasional false // positive shouldn't be a big deal, since this is only retrieved after an // error of some sort. - l.inPanic = l.inPanic || strings.HasPrefix(msg, "panic: ") || strings.HasPrefix(msg, "fatal error: ") + + panicPrefix := strings.HasPrefix(msg, "panic: ") || strings.HasPrefix(msg, "fatal error: ") + + l.inPanic = l.inPanic || panicPrefix if l.inPanic && l.panicRecorder != nil { l.panicRecorder(msg) } + // If we have logging turned on, we need to prevent panicwrap from seeing + // this as a core panic. This can be done by obfuscating the panic error + // line. + if panicPrefix { + colon := strings.Index(msg, ":") + msg = strings.ToUpper(msg[:colon]) + msg[colon:] + } + l.Logger.Debug(msg, args...) } diff --git a/internal/logging/panic_test.go b/internal/logging/panic_test.go index e83a0ba5a..d2eb7a90b 100644 --- a/internal/logging/panic_test.go +++ b/internal/logging/panic_test.go @@ -1,9 +1,12 @@ package logging import ( + "bytes" "fmt" "strings" "testing" + + "github.com/hashicorp/go-hclog" ) func TestPanicRecorder(t *testing.T) { @@ -49,3 +52,31 @@ func TestPanicLimit(t *testing.T) { } } } + +func TestLogPanicWrapper(t *testing.T) { + var buf bytes.Buffer + logger := hclog.NewInterceptLogger(&hclog.LoggerOptions{ + Name: "test", + Level: hclog.Debug, + Output: &buf, + DisableTime: true, + }) + + wrapped := (&logPanicWrapper{ + Logger: logger, + }).Named("test") + + wrapped.Debug("panic: invalid foo of bar") + wrapped.Debug("\tstack trace") + + expected := `[DEBUG] test.test: PANIC: invalid foo of bar +[DEBUG] test.test: stack trace +` + + got := buf.String() + + if expected != got { + t.Fatalf("Expected:\n%q\nGot:\n%q", expected, got) + } + +}