{"id":1006,"library":"opentelemetry-instrumentation-threading","title":"OpenTelemetry Threading Instrumentation","description":"This library provides instrumentation for Python's built-in `threading` module, ensuring that OpenTelemetry trace context is correctly propagated across threads. It does not produce telemetry data on its own but facilitates the linking of spans across different threads. Currently in beta (version 0.61b0), it is part of the `opentelemetry-python-contrib` project, which maintains a frequent release cadence.","status":"active","version":"0.61b0","language":"python","source_language":"en","source_url":"https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-threading","tags":["opentelemetry","observability","tracing","threading","context propagation","instrumentation"],"install":[{"cmd":"pip install opentelemetry-instrumentation-threading opentelemetry-sdk opentelemetry-exporter-console","lang":"bash","label":"Install package and core OTel components"}],"dependencies":[{"reason":"Core OpenTelemetry API for tracing context.","package":"opentelemetry-api"},{"reason":"Base classes for OpenTelemetry instrumentations.","package":"opentelemetry-instrumentation"},{"reason":"Used for function wrapping and patching.","package":"wrapt"},{"reason":"Required to set up a TracerProvider and exporters for telemetry, though not a direct PyPI dependency of the instrumentation itself.","package":"opentelemetry-sdk","optional":true}],"imports":[{"symbol":"ThreadingInstrumentor","correct":"from opentelemetry.instrumentation.threading import ThreadingInstrumentor"}],"quickstart":{"code":"import threading\nfrom opentelemetry import trace\nfrom opentelemetry.sdk.resources import Resource\nfrom opentelemetry.sdk.trace import TracerProvider\nfrom opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor\nfrom opentelemetry.instrumentation.threading import ThreadingInstrumentor\n\n# 1. Set up OpenTelemetry TracerProvider\nresource = Resource.create({\"service.name\": \"my-threaded-app\"})\nprovider = TracerProvider(resource=resource)\nprocessor = SimpleSpanProcessor(ConsoleSpanExporter())\nprovider.add_span_processor(processor)\ntrace.set_tracer_provider(provider)\n\n# 2. Instrument the threading module\nThreadingInstrumentor().instrument()\n\ntracer = trace.get_tracer(__name__)\n\ndef threaded_task():\n    \"A function to be run in a separate thread.\"\n    with tracer.start_as_current_span(\"child-thread-span\") as child_span:\n        print(f\"Inside threaded_task. Active span: {child_span.context.span_id:x}\")\n        # Simulate work\n        import time\n        time.sleep(0.1)\n\nif __name__ == \"__main__\":\n    with tracer.start_as_current_span(\"main-thread-span\") as parent_span:\n        print(f\"Main thread. Active span: {parent_span.context.span_id:x}\")\n\n        my_thread = threading.Thread(target=threaded_task)\n        my_thread.start()\n        my_thread.join()\n\n    print(\"Application finished.\")\n\n# Ensure all spans are exported before exiting\nprovider.shutdown()\n","lang":"python","description":"This quickstart demonstrates how to initialize OpenTelemetry with console export, then apply the `ThreadingInstrumentor`. A parent span is created in the main thread, and a child span is created within a function executed by `threading.Thread`. The instrumentation ensures that the child span correctly references the parent span, illustrating proper context propagation across thread boundaries."},"warnings":[{"fix":"Ensure `opentelemetry.sdk.trace.TracerProvider` is configured and active, and use other instrumentations (e.g., `requests`, `flask`) or manual tracing to generate spans.","message":"This instrumentation only handles context propagation for `threading.Thread`. It does NOT automatically create spans or metrics. You must still configure a `TracerProvider` and create spans (either manually or via other instrumentations) to see any telemetry data. [5]","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always use `my_thread.start()` to begin thread execution after creating a `threading.Thread` instance. Avoid calling the `run()` method directly.","message":"Directly calling `Thread.run()` instead of `Thread.start()` after instrumentation can lead to an `AttributeError` (e.g., `AttributeError: 'Thread' object has no attribute '_otel_context'`) and broken context propagation. [4]","severity":"breaking","affected_versions":"0.60b1 and potentially subsequent beta versions"},{"fix":"Pin your dependency to a specific beta version (e.g., `opentelemetry-instrumentation-threading==0.61b0`) and carefully review the `CHANGELOG` before upgrading to a new beta release.","message":"This library is currently in beta (`0.61b0`). Beta packages may have unstable APIs, and breaking changes can occur between minor versions. Always consult release notes when upgrading.","severity":"gotcha","affected_versions":"All beta versions (e.g., 0.x.x.bY)"},{"fix":"If traces appear broken, debug context propagation. Tools like `opentelemetry.context.get_current()` and `opentelemetry.context.attach()` can be used for manual context management in problematic areas, though this instrumentation aims to automate it for `threading.Thread`.","message":"While this instrumentation aims to solve context propagation, complex multi-threading patterns (especially with `concurrent.futures.ThreadPoolExecutor` in older Python versions or custom thread pool implementations) might still experience broken context. Python 3.12+ `contextvars` improve `threading.Thread` propagation, but explicit context management might still be needed in some edge cases. [1, 6]","severity":"gotcha","affected_versions":"All versions"},{"fix":"Review your `pip` install commands and `requirements.txt` to ensure all OpenTelemetry packages are correctly named and available on PyPI. For console output, utilize the `ConsoleSpanExporter` class directly from `opentelemetry.sdk.trace.export` instead of trying to install a dedicated `opentelemetry-exporter-console` package.","message":"Attempting to install a non-existent or incorrectly named OpenTelemetry package, such as `opentelemetry-exporter-console`, will result in `pip` installation errors (e.g., `No matching distribution found`). The console exporter is typically provided directly by the `opentelemetry-sdk` and is not a separate PyPI package.","severity":"breaking","affected_versions":"All versions"},{"fix":"Ensure that `opentelemetry-exporter-console` is correctly specified in the test environment's `requirements.txt` or explicitly installed. Verify that the Python version and environment (e.g., Alpine Linux) are compatible with available distributions of the exporter, providing necessary build tools or using a Python version with pre-built wheels if applicable.","message":"The test environment failed to find or install `opentelemetry-exporter-console`. This package is frequently used for demonstrating or testing OpenTelemetry functionality, and its absence can prevent tests from executing or telemetry data from being exported and observed.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T22:31:30.976Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"Always call `thread.start()` to begin a thread's execution, which correctly invokes the instrumented `run()` method after context initialization. Do not call `thread.run()` directly.","cause":"This error occurs when a `threading.Thread`'s `run()` method is called directly instead of `start()` after `opentelemetry-instrumentation-threading` has instrumented the threading module. The instrumentation expects `start()` to be called to properly set up the OpenTelemetry context.","error":"AttributeError: 'Thread' object has no attribute '_otel_context'"},{"fix":"Install the package using pip: `pip install opentelemetry-instrumentation-threading`. Ensure that your application is running in the same Python environment where the package was installed.","cause":"This error indicates that the `opentelemetry-instrumentation-threading` package is either not installed, or Python cannot find it in the current environment's `PYTHONPATH`.","error":"ModuleNotFoundError: No module named 'opentelemetry.instrumentation.threading'"},{"fix":"Import `ThreadingInstrumentor` and then call its `instrument()` method to apply the instrumentation: `from opentelemetry.instrumentation.threading import ThreadingInstrumentor\n\nThreadingInstrumentor().instrument()`","cause":"Developers sometimes incorrectly try to import a function named `instrument` directly from the `opentelemetry.instrumentation.threading` module, when the correct approach is to instantiate `ThreadingInstrumentor` and then call its `instrument()` method.","error":"ImportError: cannot import name 'instrument' from 'opentelemetry.instrumentation.threading'"}],"ecosystem":"pypi","meta_description":null,"install_score":0,"install_tag":"stale","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"0.62b1","cli_name":"","install_checks":{"last_tested":"2026-05-12","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":"build_error","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":"build_error","install_time_s":1.7,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":"build_error","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":"build_error","install_time_s":1.5,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":"build_error","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":"build_error","install_time_s":1.4,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":"build_error","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":"build_error","install_time_s":1.4,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":"build_error","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":"build_error","install_time_s":1.8,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}