#Child Span scoping in Javascript SDK

13 messages · Page 1 of 1 (latest)

spring kiln
#

Hi all, hoping someone can shine a light on how the scoping of spans works in javascript? I'm using Angular 11, and instrumenting some actions that aren't synchronous. E.g. an event gets dispatched via rxjs and I have to store the span object so I can end it in my success event handler.
I've noticed a few different times where a child span either isn't captured, or is captured directly as a child of the pageload, and not an action it should be scoped underneath.

I'm sure it's something to do with how callbacks and js scoping work because there are times the SDK doesn't think there's an active span when there is, but would appreciate if someone could explain how that works so I can figure out if there's something I can do around this 😅

#

as an example, this is a trace during page load. my ui.action, 1. happens during pageload, and 2. happens as part of that operation, but is not nested under it.

  1. can also happen after pageload, but 2 is set to onlyIfParent. And it fails to appear in the trace when 1. is the root transaction
void ginkgo
#

I share a similar problem. I use NestJS, almost everything is an observable. Wrapping a global middleware and a global interceptor with Sentry.startSpanManual does not maintain the hierarchy in spans eventhough their lifetimes are correct in relation to each other. I assumed it would work if I use Sentry.runWithAsyncContext which makes use of node js async local storage.

I did not try yet, but my current guess is that you need to specifically cascade Sentry.startSpans.

I would at least like to manually specify id of parent span at span creation, I can manage that with async local strage. The current StartSpanOptions situation is like this:

/**
 * @deprecated Use `scope` instead.
 */
parentSpanId?: string;

but scopes share the same problem

river prawn
#

so on the browser there is no async context, so there is a risk of the parent child relationship being wrong. We don't have much we can do to make this better unfortunately

#

Sentry.runWithAsyncContext should make this work for Node.js environments! But there is still risk of the wrong scope because v7 of the sdk uses a stack of scopes, which can break when forking async context.

this behaviour is fixed with v8 (and we added an official nestjs integration as well)

#

in v8 for the browser we decided to abandon the idea of correct parent-child relationship in browser environments because of the issue with async context, and just attach every child span to the root span (unless you explicitly override it)

spring kiln
#

Thanks @river prawn ! To be honest i don't mind so much what's happening in the diagram because they're still both under the pageload. However when 1. is the root transaction, 2. is not captured at all. timing wise based on logging 2. is definitely finishing before 1. does so I was hoping to understand a bit about how it works under the hood because I know js is not multi threaded.

void ginkgo
river prawn
#

I just wrote them yesterday 🙂

spring kiln
#

@river prawn I know I didn't give a lot to go on on my original issue but do you have any thoughts there? I tried to create a simplified repro but annoyingly it worked there! So I'm trying to work my way backwards.

spring kiln
#

@river prawn I persisted and I can reproduce it now! It's the "Observable Action" button that fails to capture the http call. It's actually anything the observable subscription it doesn't like. I also saw someone mention a similar issue here: https://discord.com/channels/621778831602221064/1203719695224545350 but not sure what they did in the end.

Is the next step just to raise this in github?