Skip to content

Commit

Permalink
Fix recover print stack trace log level (#1604)
Browse files Browse the repository at this point in the history
* Fix recover print stack trace log level

* Add recover log level test

* Add default LogLevel to DefaultRecoverConfig
  • Loading branch information
178inaba authored Jul 6, 2020
1 parent de3a2d4 commit e125b2c
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 1 deletion.
22 changes: 21 additions & 1 deletion middleware/recover.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"runtime"

"github.com/labstack/echo/v4"
"github.com/labstack/gommon/log"
)

type (
Expand All @@ -25,6 +26,10 @@ type (
// DisablePrintStack disables printing stack trace.
// Optional. Default value as false.
DisablePrintStack bool `yaml:"disable_print_stack"`

// LogLevel is log level to printing stack trace.
// Optional. Default value 0 (Print).
LogLevel log.Lvl
}
)

Expand All @@ -35,6 +40,7 @@ var (
StackSize: 4 << 10, // 4 KB
DisableStackAll: false,
DisablePrintStack: false,
LogLevel: 0,
}
)

Expand Down Expand Up @@ -70,7 +76,21 @@ func RecoverWithConfig(config RecoverConfig) echo.MiddlewareFunc {
stack := make([]byte, config.StackSize)
length := runtime.Stack(stack, !config.DisableStackAll)
if !config.DisablePrintStack {
c.Logger().Printf("[PANIC RECOVER] %v %s\n", err, stack[:length])
msg := fmt.Sprintf("[PANIC RECOVER] %v %s\n", err, stack[:length])
switch config.LogLevel {
case log.DEBUG:
c.Logger().Debug(msg)
case log.INFO:
c.Logger().Info(msg)
case log.WARN:
c.Logger().Warn(msg)
case log.ERROR:
c.Logger().Error(msg)
case log.OFF:
// None.
default:
c.Logger().Print(msg)
}
}
c.Error(err)
}
Expand Down
57 changes: 57 additions & 0 deletions middleware/recover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package middleware

import (
"bytes"
"fmt"
"net/http"
"net/http/httptest"
"testing"

"github.com/labstack/echo/v4"
"github.com/labstack/gommon/log"
"github.com/stretchr/testify/assert"
)

Expand All @@ -24,3 +26,58 @@ func TestRecover(t *testing.T) {
assert.Equal(t, http.StatusInternalServerError, rec.Code)
assert.Contains(t, buf.String(), "PANIC RECOVER")
}

func TestRecoverWithConfig_LogLevel(t *testing.T) {
tests := []struct {
logLevel log.Lvl
levelName string
}{{
logLevel: log.DEBUG,
levelName: "DEBUG",
}, {
logLevel: log.INFO,
levelName: "INFO",
}, {
logLevel: log.WARN,
levelName: "WARN",
}, {
logLevel: log.ERROR,
levelName: "ERROR",
}, {
logLevel: log.OFF,
levelName: "OFF",
}}

for _, tt := range tests {
tt := tt
t.Run(tt.levelName, func(t *testing.T) {
e := echo.New()
e.Logger.SetLevel(log.DEBUG)

buf := new(bytes.Buffer)
e.Logger.SetOutput(buf)

req := httptest.NewRequest(http.MethodGet, "/", nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)

config := DefaultRecoverConfig
config.LogLevel = tt.logLevel
h := RecoverWithConfig(config)(echo.HandlerFunc(func(c echo.Context) error {
panic("test")
}))

h(c)

assert.Equal(t, http.StatusInternalServerError, rec.Code)

output := buf.String()
if tt.logLevel == log.OFF {
assert.Empty(t, output)
} else {
assert.Contains(t, output, "PANIC RECOVER")
assert.Contains(t, output, fmt.Sprintf(`"level":"%s"`, tt.levelName))
}
})
}
}

0 comments on commit e125b2c

Please sign in to comment.