From 7e2ef4461116d500a46f6e41260a21900a903de2 Mon Sep 17 00:00:00 2001 From: Matt Quinn Date: Tue, 15 Sep 2026 16:53:30 -0400 Subject: [PATCH 1/2] fix(telemetry): Fix flamegraph endpoint span nesting Use `sentry.StartSpan(ctx, ...)` with the correct contexts so that spans are nested correctly. With this in place, the `*sentry.Span` argument to `GetFlamegraphFromCandidates` became unnecessary. --- cmd/vroom/flamegraph.go | 5 ++--- internal/flamegraph/flamegraph.go | 21 ++++++++++----------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/cmd/vroom/flamegraph.go b/cmd/vroom/flamegraph.go index f128c62b..2e439279 100644 --- a/cmd/vroom/flamegraph.go +++ b/cmd/vroom/flamegraph.go @@ -54,21 +54,20 @@ func (env *environment) postFlamegraph(w http.ResponseWriter, r *http.Request) { return } - s = sentry.StartSpan(ctx, "processing") + s = sentry.StartSpan(downloadContext, "processing") var ma *metrics.Aggregator if body.GenerateMetrics { agg := metrics.NewAggregator(maxUniqueFunctionsPerProfile, 5, minDepth) ma = &agg } speedscope, err := flamegraph.GetFlamegraphFromCandidates( - downloadContext, + s.Context(), env.storage, organizationID, body.Transaction, body.Continuous, readJobs, ma, - s, ) s.Finish() if err != nil { diff --git a/internal/flamegraph/flamegraph.go b/internal/flamegraph/flamegraph.go index b848e29d..809117f0 100644 --- a/internal/flamegraph/flamegraph.go +++ b/internal/flamegraph/flamegraph.go @@ -367,7 +367,6 @@ func GetFlamegraphFromCandidates( continuousProfileCandidates []examples.ContinuousProfileCandidate, jobs chan storageutil.ReadJob, ma *metrics.Aggregator, - span *sentry.Span, ) (speedscope.Output, error) { hub := sentry.GetHubFromContext(ctx) @@ -375,13 +374,14 @@ func GetFlamegraphFromCandidates( defer close(results) go func() { - dispatchSpan := span.StartChild("dispatch candidates") + dispatchSpan := sentry.StartSpan(ctx, "dispatch candidates") dispatchSpan.SetData("transaction_candidates", len(transactionProfileCandidates)) dispatchSpan.SetData("continuous_candidates", len(continuousProfileCandidates)) + defer dispatchSpan.Finish() for _, candidate := range transactionProfileCandidates { jobs <- profile.CallTreesReadJob{ - Ctx: ctx, + Ctx: dispatchSpan.Context(), OrganizationID: organizationID, ProjectID: candidate.ProjectID, ProfileID: candidate.ProfileID, @@ -392,7 +392,7 @@ func GetFlamegraphFromCandidates( for _, candidate := range continuousProfileCandidates { jobs <- chunk.CallTreesReadJob{ - Ctx: ctx, + Ctx: dispatchSpan.Context(), OrganizationID: organizationID, ProjectID: candidate.ProjectID, ProfilerID: candidate.ProfilerID, @@ -405,13 +405,11 @@ func GetFlamegraphFromCandidates( Result: results, } } - - dispatchSpan.Finish() }() var flamegraphTree []*nodetree.Node - flamegraphSpan := span.StartChild("processing candidates") + flamegraphSpan := sentry.StartSpan(ctx, "processing candidates") numCandidates := len(transactionProfileCandidates) + len(continuousProfileCandidates) @@ -439,7 +437,7 @@ func GetFlamegraphFromCandidates( } if result, ok := res.(profile.CallTreesReadJobResult); ok { - transactionProfileSpan := span.StartChild("calltree") + transactionProfileSpan := flamegraphSpan.StartChild("calltree") transactionProfileSpan.Description = "transaction profile" start, end := result.Profile.StartAndEndEpoch() @@ -463,7 +461,7 @@ func GetFlamegraphFromCandidates( transactionProfileSpan.Finish() } else if result, ok := res.(chunk.CallTreesReadJobResult); ok { - chunkProfileSpan := span.StartChild("calltree") + chunkProfileSpan := flamegraphSpan.StartChild("calltree") chunkProfileSpan.Description = "continuous profile" for threadID, callTree := range result.CallTrees { @@ -498,16 +496,17 @@ func GetFlamegraphFromCandidates( chunkProfileSpan.Finish() } else { // This should never happen + flamegraphSpan.Finish() return speedscope.Output{}, errors.New("unexpected result from storage") } } flamegraphSpan.Finish() - serializeSpan := span.StartChild("serialize") + serializeSpan := sentry.StartSpan(ctx, "serialize") defer serializeSpan.Finish() - sp := toSpeedscope(ctx, flamegraphTree, 1000, 0) + sp := toSpeedscope(serializeSpan.Context(), flamegraphTree, 1000, 0) if ma != nil { fm := ma.ToMetrics() sp.Metrics = &fm From f20cbfbe41621d815e53851c92b325257f972216 Mon Sep 17 00:00:00 2001 From: Matt Quinn Date: Wed, 16 Sep 2026 10:05:30 -0400 Subject: [PATCH 2/2] add changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7f62c9f..20212849 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## Unreleased + +**Features**: + +**Bug Fixes**: + +**Internal**: + +- Fix flamegraph endpoint span nesting. ([#677](https://github.com/getsentry/vroom/pull/677)) + ## 26.9.0 - No documented changes.