diff --git a/pkg/ticker/ticker.go b/pkg/ticker/ticker.go index 566fc03f8b..94fc9ab2fb 100644 --- a/pkg/ticker/ticker.go +++ b/pkg/ticker/ticker.go @@ -29,6 +29,8 @@ package ticker import ( "context" "fmt" + "runtime/debug" + "strings" "sync" "time" @@ -78,7 +80,14 @@ func SecondsFromUint64(d uint64) time.Duration { func (t *Ticker) Run(ctx context.Context) (err error) { defer func() { if r := recover(); r != nil { - err = fmt.Errorf("panic during ticker run: %v", r) + stack := string(debug.Stack()) + lines := strings.Split(stack, "\n") + line := "" + // 8th line should be the actual line, see the unit tests + if len(lines) > 8 { + line = strings.TrimSpace(lines[8]) + } + err = fmt.Errorf("panic during ticker run: %v at %s", r, line) } }() diff --git a/pkg/ticker/ticker_test.go b/pkg/ticker/ticker_test.go index 671091c71f..4d890bf051 100644 --- a/pkg/ticker/ticker_test.go +++ b/pkg/ticker/ticker_test.go @@ -147,6 +147,33 @@ func TestTicker(t *testing.T) { // ASSERT assert.ErrorContains(t, err, "panic during ticker run: oops") + // assert that we get error with the correct line number + assert.ErrorContains(t, err, "ticker_test.go:142") + }) + + t.Run("Nil panic", func(t *testing.T) { + // ARRANGE + // Given a context + ctx := context.Background() + + // And a ticker + ticker := New(durSmall, func(_ context.Context, _ *Ticker) error { + var a func() + a() + return nil + }) + + // ACT + err := ticker.Run(ctx) + + // ASSERT + assert.ErrorContains( + t, + err, + "panic during ticker run: runtime error: invalid memory address or nil pointer dereference", + ) + // assert that we get error with the correct line number + assert.ErrorContains(t, err, "ticker_test.go:162") }) t.Run("Run as a single call", func(t *testing.T) {