sentry-python icon indicating copy to clipboard operation
sentry-python copied to clipboard

Add a way of ignoring/filtering child spans

Open J08nY opened this issue 2 years ago • 5 comments

Problem Statement

I currently run a celery task*, with some custom spans that divide a long running processing task. This processing task itself does a bunch of HTTP requests, subprocess invocations and other things that cause enabled integrations to create child spans. However, this task does so many requests that these child spans easily go over the maximum amount of spans (or transaction size) and get cut. This means not only the child spans are cut but also some of the later custom spans. In this particular task I do not care much about the child spans and would rather ignore them inside of the custom spans so that the custom spans do not get cut (but keep the integrations enabled for elsewhere in the app).

I do not really see a (non-nasty) way of accomplishing this with the current API. Perhaps by pushing a scope and setting the span of it to some custom Span subclass that ignores start_child?

*For an example see (but not really important to the issue): https://github.com/crocs-muni/sec-certs/blob/de4af2f9c68797ba5031c315602cab185ce04acc/sec_certs_page/cc/tasks.py#L86-L101

Solution Brainstorm

Something like start_span taking an argument to ignore child spans? Or a setting on the scope level to stop span creation?

J08nY avatar Feb 12 '23 15:02 J08nY

Came up with this workaround. When used as a context manager that is entered after the start_span one it suppresses further child spans.

from contextlib import contextmanager

from sentry_sdk import push_scope
from sentry_sdk.tracing import Span


class NoChildSpan(Span):
    def start_child(self, **kwargs):
        return super().start_child(sampled=False, **kwargs)


@contextmanager
def suppress_child_spans():
    with push_scope() as scope:
        scope.span = NoChildSpan()
        try:
            yield
        finally:
            pass

J08nY avatar Feb 12 '23 15:02 J08nY

thx @J08nY, we're gonna start a milestone with several performance API improvements / decorators and I'll make sure to include this use case there!

sl0thentr0py avatar Feb 13 '23 12:02 sl0thentr0py

Hey @J08nY, have you tried using a before_send_transaction to filter the child spans you wish to ignore? You can use before_send_transaction to directly modify the transaction event object before it gets sent to Sentry, so using before_send_transaction might be the easiest solution.

szokeasaurusrex avatar Jan 11 '24 13:01 szokeasaurusrex

Hmm, I am okay with my (albeit hacky) solution right now as it prevents the creation of unwanted child spans altogether and I think has better performance than allowing the creation of all of the spans and then filtering them before sending.

J08nY avatar Jan 11 '24 13:01 J08nY

Fair enough, @J08nY – we will look into how to best create an API which would support preventing the child spans from being created in the first place

szokeasaurusrex avatar Jan 11 '24 14:01 szokeasaurusrex