Repository navigation
feat(go): report source context for recorded errors - #695
Merged
Merged
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
Vadman97
approved these changes
Jul 30, 2026
Vadman97
left a comment
Contributor
There was a problem hiding this comment.
long needed; let's get this deployed to our observability / gonfalon services to try out!
Recording a nil error reached span.RecordError, which ignores one, so it was harmless. Building a structured stack trace for every recorded error put an err.Error() in front of that and turned it into a panic. Guard at the entry point, as the Python SDK does, which also stops the no-span path starting a span for an error it is not going to record. Co-authored-by: Cursor <cursoragent@cursor.com>
abelonogov-ld
enabled auto-merge (squash)
July 30, 2026 02:56
abelonogov-ld
disabled auto-merge
July 30, 2026 02:58
Trimming walked runtime.CallersFrames to count the leading frames that belong to this SDK, then used that count to index the counter slice, and structuredFrames walked the counters again to build the trace. Dropping the frames as they are resolved needs no correspondence between the two and resolves the stack once instead of twice. runtime.Callers emits a counter per frame, inlined calls included, so the index was right in practice; runtime.CallersFrames documents that several frames can share a counter, so it was right only for as long as that holds. The drop stays on the record-time path: the stack an error carries was taken at the failure, and none of it is the recording. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit fa34d68. Configure here.
Merged
abelonogov-ld
pushed a commit
that referenced
this pull request
Jul 30, 2026
🤖 I have created a release *beep* *boop* --- <details><summary>go: 1.2.0</summary> ## [1.2.0](go/v1.1.1...go/v1.2.0) (2026-07-30) ### Features * **go:** report source context for recorded errors ([#695](#695)) ([34e3201](34e3201)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Version and changelog-only changes with no runtime logic in the diff; the underlying feature is additive error reporting metadata. > > **Overview** > **Release Please** bumps the Go observability SDK from **1.1.1** to **1.2.0** in `.release-please-manifest.json`, `go/internal/metadata/metadata.go` (`InstrumentationVersion`), and `go/CHANGELOG.md`. > > The changelog entry documents the shipped feature: **reporting source context for recorded errors** ([#695](#695)). This PR does not include that implementation—only version and release metadata. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 3e05c6e. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Go errors arrived in the errors UI as a bare text stacktrace with no source, and the frames on top belonged to the SDK rather than to the application, so the first thing you saw was
span.RecordError. This does for Go what #693 did for Python.RecordErrornow attachesexception.structured_stacktrace: function name, file, line and a window of source lines around each frame, read from the running host. Ingestion prefers this attribute over the text stacktrace.pkg/errors.Wraprecords a fresh stack where the wrapping happened, which meant the frames pointed at the handler that added context rather than at where the error came from. This applies to the text stacktrace too, not just the structured one.e2e/go-plugingained four routes that record a plain error, one with a stack, a wrapped one, and one raised from a closure inside a goroutine, plus README instructions for pointing the example at a backend running on localhost.The text stacktrace remains the fallback for errors recorded outside this path; the parsing of those on the backend is fixed separately in launchdarkly/observability#1596.
Test plan
go test ./...ingo/. Unit tests cover picking the innermost stack through bothpkg/errorsand standard wrapping, source windows clipped at the start and end of a file, a missing file, a line past the end of a file, long-line truncation, and function-name shortening.stacktrace_record_test.godrives a realRecordErrorfrom an external test package through an in-memory exporter and asserts the first frame is the caller, which is what proves the trimming works from outside the module.Made with Cursor