Skip to content

Commit

Permalink
Merge pull request #15 from infiniteloopcloud/limit-recoverer-result
Browse files Browse the repository at this point in the history
Add DebugStackLengthLimit to the RecovererLogStack
  • Loading branch information
PumpkinSeed authored Feb 28, 2024
2 parents a9f77e2 + 4924aa0 commit f098dc7
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
12 changes: 10 additions & 2 deletions middlewares/recoverer.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,14 +265,22 @@ func cW(w io.Writer, useColor bool, color []byte, s string, args ...interface{})
}
}

type RecovererLogStack struct{}
type RecovererLogStack struct {
DebugStackLengthLimit int
}

func (l RecovererLogStack) Parse(ctx context.Context, debugStack []byte, rvr interface{}) ([]byte, error) {
debugStackMsgWrapped := strings.Join(strings.Split(string(debugStack), "\n"), "|")
if l.DebugStackLengthLimit > 0 {
if lenDebugStack := len(debugStackMsgWrapped); lenDebugStack > l.DebugStackLengthLimit {
debugStackMsgWrapped = debugStackMsgWrapped[:l.DebugStackLengthLimit]
}
}
parsedLog := log.Parse(ctx, log.ErrorLevelString, "panic happen",
fmt.Errorf("panic happen: %v", rvr),
log.Field{
Key: "debug_stack",
Value: strings.Join(strings.Split(string(debugStack), "\n"), "|"),
Value: debugStackMsgWrapped,
})
return []byte(parsedLog), nil
}
40 changes: 40 additions & 0 deletions middlewares/recoverer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package middlewares
import (
"bytes"
"context"
"encoding/json"
"errors"
"io"
"net/http"
"net/http/httptest"
Expand All @@ -11,6 +13,8 @@ import (
"testing"

"github.com/go-chi/chi/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func panicingHandler(http.ResponseWriter, *http.Request) { panic("foo") }
Expand Down Expand Up @@ -98,6 +102,42 @@ func TestRecovererCustomParser(t *testing.T) {
t.Fatal("First func call line should be something like 'goroutine 18 [running]:'")
}

// TestRecovererLogStack_ParseDebugStackLimit is testing if the debug_stack string cut was successful
// if the limit is less than the length of the debug_stack
func TestRecovererLogStack_ParseDebugStackLimit(t *testing.T) {
ls := RecovererLogStack{DebugStackLengthLimit: 1024}
a1000 := strings.Repeat("a", 1000)
b1000 := strings.Repeat("b", 1000)
parse, err := ls.Parse(context.Background(), []byte(a1000+b1000), errors.New("some panic"))
require.NoError(t, err)
var labels map[string]interface{}
require.NoError(t, json.Unmarshal(parse, &labels))
debugStackI, ok := labels["debug_stack"]
require.True(t, ok, "missing debug stack field")
debugStackStr, ok := debugStackI.(string)
require.True(t, ok, "invalid debug stack type")
assert.Contains(t, debugStackStr, a1000)
assert.Contains(t, debugStackStr, strings.Repeat("b", 24))
}

// TestRecovererLogStack_ParseDebugStackLimit is testing if the debug_stack string cut was successful
// if the limit is greater than the length of the debug_stack
func TestRecovererLogStack_ParseDebugStackLimit2(t *testing.T) {
ls := RecovererLogStack{DebugStackLengthLimit: 1024}
a100 := strings.Repeat("a", 100)
b100 := strings.Repeat("b", 100)
parse, err := ls.Parse(context.Background(), []byte(a100+b100), errors.New("some panic"))
require.NoError(t, err)
var labels map[string]interface{}
require.NoError(t, json.Unmarshal(parse, &labels))
debugStackI, ok := labels["debug_stack"]
require.True(t, ok, "missing debug stack field")
debugStackStr, ok := debugStackI.(string)
require.True(t, ok, "invalid debug stack type")
assert.Contains(t, debugStackStr, a100)
assert.Contains(t, debugStackStr, b100)
}

type custom struct{}

func (c custom) Parse(_ context.Context, debugStack []byte, rvr interface{}) ([]byte, error) {
Expand Down

0 comments on commit f098dc7

Please sign in to comment.