gqlgen's graphql.DefaultRecover prints a recovered resolver panic and debug.PrintStack() to stderr, so the log collector stores every stack line as a separate, level-less entry (~60 entries per panic in production).
Adds otelsetup.Recover (func(ctx context.Context, err any) error, a graphql.RecoverFunc for gqlgen v0.17.95):
logs the panic as one ERROR record via slog.Default().ErrorContext (the default logger services set up through logging.SetupLogger), with panic, stack (debug.Stack()) and path (GraphQL field path, when available) attributes
records the error on the active span (RecordError with stack trace, SetStatus(codes.Error))
returns the generic internal system error gqlerror to the client, without the panic text
Services install it with srv.SetRecoverFunc(otelsetup.Recover).
Test plan
TestRecover: error and non-error panic values; asserts the generic gqlerror, no panic text leak, exactly one ERROR log record with panic/stack attributes, and span status Error with an exception event carrying message and stacktrace (in-memory tracetest.SpanRecorder)
go test -race ./... passes, prek run --all-files passes
## Summary
gqlgen's `graphql.DefaultRecover` prints a recovered resolver panic and `debug.PrintStack()` to stderr, so the log collector stores every stack line as a separate, level-less entry (~60 entries per panic in production).
Adds `otelsetup.Recover` (`func(ctx context.Context, err any) error`, a `graphql.RecoverFunc` for gqlgen v0.17.95):
- logs the panic as **one** ERROR record via `slog.Default().ErrorContext` (the default logger services set up through `logging.SetupLogger`), with `panic`, `stack` (`debug.Stack()`) and `path` (GraphQL field path, when available) attributes
- records the error on the active span (`RecordError` with stack trace, `SetStatus(codes.Error)`)
- returns the generic `internal system error` gqlerror to the client, without the panic text
Services install it with `srv.SetRecoverFunc(otelsetup.Recover)`.
## Test plan
- `TestRecover`: error and non-error panic values; asserts the generic gqlerror, no panic text leak, exactly one ERROR log record with panic/stack attributes, and span status Error with an `exception` event carrying message and stacktrace (in-memory `tracetest.SpanRecorder`)
- `go test -race ./...` passes, `prek run --all-files` passes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01H6eVuR4Yt3m7TbDTDwyZJi
gqlgen's DefaultRecover prints the panic and debug.PrintStack() to stderr, so the log collector stores every stack line as a separate, level-less entry. Recover logs the panic as a single ERROR record via slog.Default() with panic, stack and path attributes, records it on the active span with status Error, and returns the generic "internal system error" without leaking the panic text. Install with srv.SetRecoverFunc(otelsetup.Recover).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H6eVuR4Yt3m7TbDTDwyZJi
argoyle
scheduled this pull request to auto merge when all checks succeed 2026-10-16 23:09:06 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
gqlgen's
graphql.DefaultRecoverprints a recovered resolver panic anddebug.PrintStack()to stderr, so the log collector stores every stack line as a separate, level-less entry (~60 entries per panic in production).Adds
otelsetup.Recover(func(ctx context.Context, err any) error, agraphql.RecoverFuncfor gqlgen v0.17.95):slog.Default().ErrorContext(the default logger services set up throughlogging.SetupLogger), withpanic,stack(debug.Stack()) andpath(GraphQL field path, when available) attributesRecordErrorwith stack trace,SetStatus(codes.Error))internal system errorgqlerror to the client, without the panic textServices install it with
srv.SetRecoverFunc(otelsetup.Recover).Test plan
TestRecover: error and non-error panic values; asserts the generic gqlerror, no panic text leak, exactly one ERROR log record with panic/stack attributes, and span status Error with anexceptionevent carrying message and stacktrace (in-memorytracetest.SpanRecorder)go test -race ./...passes,prek run --all-filespasses🤖 Generated with Claude Code
https://claude.ai/code/session_01H6eVuR4Yt3m7TbDTDwyZJi
Coverage Report
Total coverage: 37%