open-telemetry / open-telemetry/opentelemetry-python

Parent IDs are null for spawned spans with gevent auto-instrumentation

Open
#4,379 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
2.6k
Forks
1k
Avg merge
4d 15h
Merged PRs (30d)
19

Description

Describe your environment

OS: MacOS
Python version: 3.12.4
telemetry.sdk.version: 1.28.2
telemetry.auto.version: 0.49b2

What happened?

I'm trying to use auto-instrument with gevent, but the parent ids are null for spawned spans. Am I missing anything or do you have any suggestion?

image
Steps to Reproduce

Server Code

from gevent import monkey

monkey.patch_all()

from flask import Flask, request

app = Flask(__name__)


@app.route("/server_request")
def server_request():
    print(request.args.get("param"))
    return "served"


if __name__ == "__main__":
    app.run(port=8082)

  • Run with:
    opentelemetry-instrument --traces_exporter console --metrics_exporter none python server_automatic.py

Client Code

import gevent

from sys import argv

from requests import get

from opentelemetry import trace
from opentelemetry.propagate import inject
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
    BatchSpanProcessor,
    ConsoleSpanExporter,
)
from opentelemetry.instrumentation.requests import RequestsInstrumentor

RequestsInstrumentor().instrument()

trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer_provider().get_tracer(__name__)

trace.get_tracer_provider().add_span_processor(
    BatchSpanProcessor(ConsoleSpanExporter())
)

assert len(argv) == 2


def make_http_call(n=None):
    headers = {}
    inject(headers)
    return get(
        "http://localhost:8082/server_request",
        params={"param": argv[1]},
        headers=headers,
    )


def spawn_calls():
    with tracer.start_as_current_span("spawn_calls"):
        jobs = []
        jobs.append(gevent.spawn(make_http_call))
        jobs.append(gevent.spawn(make_http_call))
        jobs.append(gevent.spawn(make_http_call))
        gevent.joinall(jobs, timeout=2)


def launch_gevent_chain():
    with tracer.start_as_current_span("test"):
        gevent.spawn(spawn_calls).join()


gevent.spawn(launch_gevent_chain)

gevent.sleep(2)

  • Run with:
    python client.py otel-flask-gevent-testing
Expected Result

I was expecting to see spawn_calls's span id as spawned spans' pids.

Actual Result

Parent IDs in the results are null

Additional context

No response

Would you like to implement a fix?

None

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the server and client snippets in the issue and reproduce them using the two provided opentelemetry-instrument and python commands. Trace the interaction between gevent.spawn, RequestsInstrumentor, and context injection; done means the spawned request spans have the expected parent IDs instead of null values.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
observability-sre
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.