Skip to content

opentelemetry.tracer crashes with TypeError in transaction with high number of spans #2245

Description

@kozako2

Describe the bug:

Using opentelemetry bridge crashes with TypeError: 'NoneType' object does not support item assignment exception when number of spans in transaction is higher than ELASTIC_APM_TRANSACTION_MAX_SPANS

File ~/.pyenv/versions/3.11.11/envs/test/lib/python3.11/site-packages/elasticapm/contrib/opentelemetry/trace.py:169, in Tracer.start_span(self, name, context, kind, attributes, links, start_time, record_exception, set_status_on_exception)
    167     span.set_attributes(attributes)
    168 spankind = get_span_kind(kind)
--> 169 elastic_span.context["otel_spankind"] = spankind
    171 return span

.
Debugger shows that elastic_span inside is DroppedSpan. Increasing nr of ELASTIC_APM_TRANSACTION_MAX_SPANS "fixes" problem as shown in code below.

To Reproduce

from elasticapm.contrib.opentelemetry import trace
from elasticapm import Client, capture_span

import os

# Reduce number of spans required to reproduce the issue
ELASTIC_APM_TRANSACTION_MAX_SPANS = 10
STEPS_ABOVE = ELASTIC_APM_TRANSACTION_MAX_SPANS + 1 
STEPS_BELLOW = ELASTIC_APM_TRANSACTION_MAX_SPANS - 1 
os.environ["ELASTIC_APM_TRANSACTION_MAX_SPANS"] = str(ELASTIC_APM_TRANSACTION_MAX_SPANS)

apm_client = Client()
tracer = trace.get_tracer(__name__)

# Simulate deep nested spans
def capture_span_elasticapm(steps=10):
     if steps == 0:
        return
     
     with capture_span():
        capture_span_elasticapm(steps-1)

def capture_span_opentelemetry(steps=10):
     if steps == 0:
        return
     
     with tracer.start_as_current_span("test"):
        capture_span_opentelemetry(steps-1)


# TEST

# Works - Expected
transaction = apm_client.begin_transaction('processors')
capture_span_elasticapm(STEPS_BELLOW)
apm_client.end_transaction('myapp.billing_process')

# Works - Expected
transaction = apm_client.begin_transaction('processors')
capture_span_opentelemetry(STEPS_BELLOW)
apm_client.end_transaction('myapp.billing_process')

# Works - Expected
transaction = apm_client.begin_transaction('processors')
capture_span_elasticapm(STEPS_ABOVE)
apm_client.end_transaction('myapp.billing_process')

# Crashes - Unexpected 
# TypeError: 'NoneType' object does not support item assignment
transaction = apm_client.begin_transaction('processors')
capture_span_opentelemetry(STEPS_ABOVE)
apm_client.end_transaction('myapp.billing_process')

Environment (please complete the following information)

  • OS: [e.g. Linux] Linux Mint 22.1 Cinnamon
  • Python version: 3.11.11
  • Framework and version [e.g. Django 2.1]: N/A
  • APM Server version: N/A
  • Agent version: elastic-apm==6.23.0

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions