[v8] Multiple roots detected with manual spans
Is there an existing issue for this?
- [X] I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
- [X] I have reviewed the documentation https://docs.sentry.io/
- [X] I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases
How do you use Sentry?
Sentry Saas (sentry.io)
Which SDK are you using?
@sentry/browser
SDK Version
8.2.1
Framework Version
No response
Link to Sentry event
https://codeocean.sentry.io/performance/trace/ee6b9b5549414a8f83fcd71f9f24d054/
SDK Setup
Sentry.init({
dsn: sentrySettings.data('dsn'),
attachStacktrace: true,
release: sentrySettings.data('release'),
environment: sentrySettings.data('environment'),
autoSessionTracking: true,
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.0,
replaysOnErrorSampleRate: 1.0,
integrations: [
Sentry.browserProfilingIntegration(),
Sentry.browserTracingIntegration(),
Sentry.extraErrorDataIntegration(),
Sentry.httpClientIntegration(),
Sentry.replayIntegration(),
Sentry.reportingObserverIntegration(),
Sentry.sessionTimingIntegration(),
],
profilesSampleRate: 1.0,
initialScope: scope =>{
if (current_user) {
scope.setUser(_.omit(current_user, 'displayname'));
}
return scope;
}
});
Steps to Reproduce
I am trying to add some custom transactions to my frontend code, allowing to gather further insights. With the previous v7 of the SDK, I was able to achieve that:
As shown, the "run" transaction might last several seconds, and I want to have it separate for further analysis. In v7 code, I was manually starting a transaction. With v8, I am about to migrate to Sentry.startSpanManual with no currently active parent span, so that something formally known as "transaction" should be created.
However, my new transactions always keep the same trace ID, even when trying the forceTransaction option (see screenshot in "actual result"):
const cause = initiator.data('cause') || initiator.prop('id');
Sentry.startSpanManual({ name: cause, op: "transaction", forceTransaction: true }, span => {
callback(span);
});
I already tried passing a new scope (similar to #12000), but without success either. Further, I am not sure what the actual expected behavior should be. When reading #11599, I got the impression that the newly observed behavior is expected ("All events happening within one route are associated with the trace from the propagation context."), but since the Sentry Saas UI still reports the "multiple root transactions" error, I am not sure about that.
Expected Result
Each transaction is shown in a dedicated trace and I can decide to start a new transaction as desired. Specifically, the "page load" and my various "run" transactions are not merged together. See my above screenshot for my expectation.
Actual Result
The initial page load and my custom transactions are grouped in the same trace. Simultaneously, I get a warning about "Multiple root transactions have been found with this trace ID.".
Hello,
This is "expected" behavior today, but I see what you mean.
You should be able to get the desired outcome like this - this is obv. not ideal but should be OK for now:
import * as Sentry from '@sentry/browser';
function isolatedThing() {
return Sentry.continueTrace({ sentryTrace: '', baggage: '' }, () => {
// inside of this we have a new trace!
return Sentry.withActiveSpan(null, () => {
// inside of this there is no parent span, no matter what!
return Sentry.startSpan({ name: 'my span' }, () => {
// do something....
});
});
});
}
does this work for you? We are looking into providing a nicer API for this in a soon to follow update!
Awesome, thank you! It took me a few days to integrate this change and finalize the upgrade to v8. Your code suggestion was very valuable to me, and indeed your code snippet solved the issue. With that method, I was able to get the desired output: A dedicated "transaction" (i.e., parent-level span) without the "Multiple root transactions" error.
Indeed, a nicer API would be well appreciated. For our use case, I extracted that part to a dedicated method, that consumes another function to be executed as a new span.
Since my question has been answered and a solution to my issue has been provided, implemented, and successfully deployed to production, I am closing this issue.
Awesome, thank you! It took me a few days to integrate this change and finalize the upgrade to v8. Your code suggestion was very valuable to me, and indeed your code snippet solved the issue. With that method, I was able to get the desired output: A dedicated "transaction" (i.e., parent-level span) without the "Multiple root transactions" error.
Indeed, a nicer API would be well appreciated. For our use case, I extracted that part to a dedicated method, that consumes another function to be executed as a new span.
Since my question has been answered and a solution to my issue has been provided, implemented, and successfully deployed to production, I am closing this issue.
Great to hear that works!
We'll soon ship a new API startNewTrace (https://github.com/getsentry/sentry-javascript/pull/12138) that should make this much easier/nicer:
myButton.addEventListener('click', async () => {
Sentry.startNewTrace(() => {
Sentry.startSpan({ op: 'ui.interaction.click', name: 'fetch click' }, async () => {
await fetch('http://example.com');
});
});
});
We'll soon ship a new API startNewTrace (https://github.com/getsentry/sentry-javascript/pull/12138) that should make this much easier/nicer
That's nice, indeed! I prepared a PR in our repo already, just waiting for the next release.