Skip to content

Add __deepcopy__ support to Span and BoundedAttributes #4928

@ibbykhazanchi

Description

@ibbykhazanchi

Is your feature request related to a problem?

I need to export a span to two different collectors, with each collector receiving different attributes (e.g., dropping certain attributes for one collector). Since multiple SpanProcessors receive the same span instance, mutating the span in one processor affects all others.

I attempted to deepcopy the span so the processor with mutating logic works with an independent copy:

def on_end(self, span: ReadableSpan) -> None:
    span_copy = copy.deepcopy(span)
    # mutate span_copy safely
    self.exporter.export((span_copy,))

However, this fails with:

TypeError: cannot pickle '_thread.RLock' object

Root Cause

BoundedAttributes contains a threading.RLock. Since locks cannot be pickled or deep copied, copy.deepcopy() fails on any span object.

Describe the solution you'd like

Add __deepcopy__ methods to BoundedAttributes and Span/ReadableSpan that create new lock instances instead of attempting to copy the existing ones.

Describe alternatives you've considered

For the time being, I've switched to using a SimpleSpanProcessor for one of our collector's exports, but I'd prefer the async benefits of using a BatchSpanProcessor if this feature were added.

Additional Context

No response

Would you like to implement a fix?

Yes

Tip

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions