-
Notifications
You must be signed in to change notification settings - Fork 167
Remove irrelevant frames from panic traces #774
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,7 @@ import ( | |
| "errors" | ||
| "fmt" | ||
| "log/slog" | ||
| "runtime/debug" | ||
| "runtime" | ||
| "time" | ||
|
|
||
| "github.com/riverqueue/river/internal/execution" | ||
|
|
@@ -131,7 +131,13 @@ func (e *JobExecutor) execute(ctx context.Context) (res *jobExecutorResult) { | |
| ) | ||
|
|
||
| res = &jobExecutorResult{ | ||
| PanicTrace: string(debug.Stack()), | ||
| // Skip the first 4 frames which are: | ||
| // | ||
| // 1. The `runtime.Callers` function. | ||
| // 2. The `captureStackTraceSkipFrames` function. | ||
| // 3. The current recovery defer function. | ||
| // 4. The `JobExecutor.execute` method working the job. | ||
| PanicTrace: captureStackTraceSkipFrames(4), | ||
| PanicVal: recovery, | ||
| } | ||
| } | ||
|
|
@@ -325,3 +331,25 @@ func (e *JobExecutor) reportError(ctx context.Context, res *jobExecutorResult) { | |
| e.Logger.ErrorContext(ctx, e.Name+": Failed to report error for job", logAttrs...) | ||
| } | ||
| } | ||
|
|
||
| // captureStackTrace returns a formatted stack trace string starting after | ||
| // skipping the specified number of frames. The skip parameter should be | ||
| // adjusted so that frames you want to hide (like the ones generated by the | ||
| // tracing functions themselves) are excluded. | ||
| func captureStackTraceSkipFrames(skip int) string { | ||
| // Allocate room for up to 100 callers; adjust as needed. | ||
| pcs := make([]uintptr, 100) | ||
| // Skip the specified number of frames. | ||
| n := runtime.Callers(skip, pcs) | ||
| frames := runtime.CallersFrames(pcs[:n]) | ||
|
|
||
| var stackTrace string | ||
| for { | ||
| frame, more := frames.Next() | ||
| stackTrace += fmt.Sprintf("%s\n\t%s:%d\n", frame.Function, frame.File, frame.Line) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume the formatting comes from what
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is actually quite a bit easier to grok than the stdlib 😬 : This is more similar to what pkg/errors does: |
||
| if !more { | ||
| break | ||
| } | ||
| } | ||
| return stackTrace | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oof, it's good there's a test for this because it'd be pretty shaky otherwise. The raw number "4" probably merits a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment to explain and further improved test coverage, thanks