Disable sending Spans with attribute Sampled=False
Problem Statement
Span attribute sampled is ignored and on Transaction finish all collected Spans inside Transaction will be send, if all transaction is Sampled.
I want to use feature-flags for disabling tracing of some parts of my code dynamically for reducing usage on production environment (for example when I've many fast request to another service).
Solution Brainstorm
Modify condition https://github.com/getsentry/sentry-python/blob/b7c0dc412a1505fff382732f567952c8a9572b60/sentry_sdk/tracing.py#L646 to
if span.timestamp is not None and (span.sampled == True or span.sampled is None)
@andrewchernyh how do you plan to use this even if we add this condition?
@sl0thentr0py
I'm using tracing decorators, and can easy add something like this
....
def wrappee(*args, **kwargs):
sampled = is_feature_enabled("tracing", context: { "op": decorator_self.op } )
with start_span(decorator_self.op, decorator_self.description, sampled=sampled):
return original_func(*args, **kwargs)
Another usage of unsampled spans is filtering them out on some condition, for example with duration less them 1ms
Right now sampling as a concept only exists on the transaction level. Changing APIs like this needs to be discussed internally and synced across SDKs, so we won't be moving fast on this but I'll bring it up. But it's not clear to me that this is a good idea and fits into the rest of the performance UX.
Second, modifying https://github.com/getsentry/sentry-python/blob/b7c0dc412a1505fff382732f567952c8a9572b60/sentry_sdk/tracing.py#L646 is after the span is recorded/instrumented already, so it doesn't really lower your overhead.
Third, if you already have that decorator, you could just move the sampling logic for spans to your decorator and do it yourself. This will probably unblock you sooner than waiting for us. For instance,
def wrappee(*args, **kwargs):
sampled = is_feature_enabled("tracing", context: { "op": decorator_self.op } )
if sampled:
with start_span(decorator_self.op, decorator_self.description):
return original_func(*args, **kwargs)
else:
return original_func(*args, *kwargs)
This issue has gone three weeks without activity. In another week, I will close it.
But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!
"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀