Metadata-Version: 2.4
Name: dash0-opentelemetry
Version: 0.3.1
Summary: Dash0 OpenTelemetry distribution for Python
Author: Dash0
License-Expression: Apache-2.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Requires-Dist: asgiref==3.12.1
Requires-Dist: dash0-opentelemetry-exporter-otlp-pyproto-grpc==1.44.0.post1
Requires-Dist: dash0-opentelemetry-exporter-otlp-pyproto-http==1.44.0.post1
Requires-Dist: opentelemetry-api==1.44.0
Requires-Dist: opentelemetry-instrumentation-aio-pika==0.65b0
Requires-Dist: opentelemetry-instrumentation-aiohttp-client==0.65b0
Requires-Dist: opentelemetry-instrumentation-aiohttp-server==0.65b0
Requires-Dist: opentelemetry-instrumentation-aiokafka==0.65b0
Requires-Dist: opentelemetry-instrumentation-aiopg==0.65b0
Requires-Dist: opentelemetry-instrumentation-asgi==0.65b0
Requires-Dist: opentelemetry-instrumentation-asyncclick==0.65b0
Requires-Dist: opentelemetry-instrumentation-asyncio==0.65b0
Requires-Dist: opentelemetry-instrumentation-asyncpg==0.65b0
Requires-Dist: opentelemetry-instrumentation-boto3sqs==0.65b0
Requires-Dist: opentelemetry-instrumentation-botocore==0.65b0
Requires-Dist: opentelemetry-instrumentation-cassandra==0.65b0
Requires-Dist: opentelemetry-instrumentation-celery==0.65b0
Requires-Dist: opentelemetry-instrumentation-click==0.65b0
Requires-Dist: opentelemetry-instrumentation-confluent-kafka==0.65b0
Requires-Dist: opentelemetry-instrumentation-dbapi==0.65b0
Requires-Dist: opentelemetry-instrumentation-django==0.65b0
Requires-Dist: opentelemetry-instrumentation-exceptions==0.65b0
Requires-Dist: opentelemetry-instrumentation-falcon==0.65b0
Requires-Dist: opentelemetry-instrumentation-fastapi==0.65b0
Requires-Dist: opentelemetry-instrumentation-flask==0.65b0
Requires-Dist: opentelemetry-instrumentation-grpc==0.65b0
Requires-Dist: opentelemetry-instrumentation-httpx==0.65b0
Requires-Dist: opentelemetry-instrumentation-jinja2==0.65b0
Requires-Dist: opentelemetry-instrumentation-kafka-python==0.65b0
Requires-Dist: opentelemetry-instrumentation-logging==0.65b0
Requires-Dist: opentelemetry-instrumentation-mysql==0.65b0
Requires-Dist: opentelemetry-instrumentation-mysqlclient==0.65b0
Requires-Dist: opentelemetry-instrumentation-openai-v2==2.3b0
Requires-Dist: opentelemetry-instrumentation-pika==0.65b0
Requires-Dist: opentelemetry-instrumentation-psycopg2==0.65b0
Requires-Dist: opentelemetry-instrumentation-psycopg==0.65b0
Requires-Dist: opentelemetry-instrumentation-pymemcache==0.65b0
Requires-Dist: opentelemetry-instrumentation-pymongo==0.65b0
Requires-Dist: opentelemetry-instrumentation-pymssql==0.65b0
Requires-Dist: opentelemetry-instrumentation-pymysql==0.65b0
Requires-Dist: opentelemetry-instrumentation-pyramid==0.65b0
Requires-Dist: opentelemetry-instrumentation-redis==0.65b0
Requires-Dist: opentelemetry-instrumentation-remoulade==0.65b0
Requires-Dist: opentelemetry-instrumentation-requests==0.65b0
Requires-Dist: opentelemetry-instrumentation-sqlalchemy==0.65b0
Requires-Dist: opentelemetry-instrumentation-sqlite3==0.65b0
Requires-Dist: opentelemetry-instrumentation-starlette==0.65b0
Requires-Dist: opentelemetry-instrumentation-structlog==0.65b0
Requires-Dist: opentelemetry-instrumentation-system-metrics==0.65b0
Requires-Dist: opentelemetry-instrumentation-threading==0.65b0
Requires-Dist: opentelemetry-instrumentation-tornado==0.65b0
Requires-Dist: opentelemetry-instrumentation-tortoiseorm==0.65b0
Requires-Dist: opentelemetry-instrumentation-urllib3==0.65b0
Requires-Dist: opentelemetry-instrumentation-urllib==0.65b0
Requires-Dist: opentelemetry-instrumentation-vertexai==2.2b0
Requires-Dist: opentelemetry-instrumentation-wsgi==0.65b0
Requires-Dist: opentelemetry-instrumentation==0.65b0
Requires-Dist: opentelemetry-propagator-aws-xray==1.0.2
Requires-Dist: opentelemetry-sdk==1.44.0
Requires-Dist: opentelemetry-semantic-conventions==0.65b0
Requires-Dist: opentelemetry-util-genai==0.2b0
Requires-Dist: opentelemetry-util-http==0.65b0
Requires-Dist: packaging==26.2
Requires-Dist: psutil==7.2.2
Requires-Dist: typing-extensions==4.16.0
Requires-Dist: wrapt==1.17.3
Description-Content-Type: text/x-rst

===================
dash0-opentelemetry
===================

The Dash0 OpenTelemetry distribution for Python. It is the Python counterpart of
the Dash0 Node.js distribution (``@dash0/opentelemetry``), adapted to Python's
distro/configurator machinery, and is meant to be injected into a process (for
example by the OpenTelemetry injector) with no code changes.

Entry points
============

``Dash0Distro`` (``opentelemetry_distro``)
    Runs first, before the configurator. It:

    * **Gates** the distribution: does nothing if ``DASH0_DISABLE=true`` or if
      ``DASH0_OTEL_COLLECTOR_BASE_URL`` is unset (nowhere to send telemetry). In
      either case it sets ``OTEL_SDK_DISABLED=true`` and skips instrumentation.
    * Defaults all three signals to the pure-Python OTLP/HTTP exporter
      (``otlp_proto_http``, ``http/protobuf``) and points
      ``OTEL_EXPORTER_OTLP_ENDPOINT`` at ``DASH0_OTEL_COLLECTOR_BASE_URL``. The
      pure-Python exporter has no native dependencies, which is what makes the
      distribution safe to inject onto an arbitrary process' ``PYTHONPATH``.
      When a signal's OTLP protocol does not match the transport the shared
      endpoint targets — its port is the *other* protocol's conventional
      default (``4317`` gRPC / ``4318`` HTTP) — a per-signal
      ``OTEL_EXPORTER_OTLP_<SIGNAL>_ENDPOINT`` is derived by rewriting the
      port (appending the ``v1/<signal>`` path for HTTP), so mixed-protocol
      setups and a base URL on the "wrong" default port still export
      correctly. Custom ports and explicit per-signal endpoints are always
      left untouched.
    * Injects detected **resource attributes** into ``OTEL_RESOURCE_ATTRIBUTES``/
      ``OTEL_SERVICE_NAME`` (see below) so the SDK's Resource picks them up.
    * Overrides ``load_instrumentor`` to activate each instrumentor
      **defensively** — a disabled or failing instrumentor is skipped and logged
      rather than aborting auto-instrumentation of the host process.

``Dash0Configurator`` (``opentelemetry_configurator``)
    Runs after the distro. Delegates to the standard OpenTelemetry SDK
    configurator to build the providers/exporters/Resource from the environment,
    then adds two behaviors from the Node.js distribution:

    * an optional **bootstrap span** emitted once at startup
      (``DASH0_BOOTSTRAP_SPAN=<name>``);
    * optional **graceful flush** on ``SIGTERM``/``SIGINT``
      (``DASH0_FLUSH_ON_SIGTERM_SIGINT=true``) — normal-exit flushing is already
      handled by the SDK's ``atexit`` provider shutdown.

Resource detectors (``opentelemetry_resource_detector``)
    The detected resource attributes (see below) as standard SDK resource
    detectors, one per concern so each can be used (or omitted) independently:

    * ``dash0_distribution`` — ``telemetry.distro.name``/``telemetry.distro.version``;
    * ``dash0_kubernetes`` — ``k8s.pod.uid``;
    * ``dash0_service_name`` — wraps the upstream service detection (a
      process-stable ``service.instance.id`` and ``service.name`` from
      ``OTEL_SERVICE_NAME``) and adds the distro's entrypoint-derived
      ``service.name`` fallback, so there is no need to also list the built-in
      ``service`` detector.

    They can be referenced via ``OTEL_EXPERIMENTAL_RESOURCE_DETECTORS``, or
    explicitly in a declarative config file under
    ``resource.detection/development.detectors``.

Instrumentations
================

The distribution depends on the full upstream auto-instrumentation set — every
package enumerated by the ``bootstrap_gen`` module of
``opentelemetry-instrumentation`` (the list behind ``opentelemetry-bootstrap``)
— pinned to a single contrib version, so injected processes need no bootstrap
step. Instrumentations only activate when their target library is present,
which makes carrying all of them safe.

Deviations from the upstream list:

* ``opentelemetry-propagator-aws-xray`` is shipped although upstream's
  bootstrap list only covers instrumentations (the Dash0 operator's
  instrumentation image always carried it).
* ``opentelemetry-exporter-prometheus``,
  ``opentelemetry-propagator-ot-trace``, and
  ``opentelemetry-instrumentation-aws-lambda`` are deliberately not shipped.

``tests/test_instrumentations.py`` cross-checks the dependency block against
the installed upstream list, so a contrib version bump that adds or removes
instrumentations fails CI until the block is re-synced. Dependabot keeps the
pins themselves moving (all ``opentelemetry-*`` packages are grouped into one
update, since the contrib instrumentations only resolve when they share one
contrib version).

Resource detection
==================

Ported from the Node.js distribution's custom detectors:

* **Kubernetes pod UID** (``k8s.pod.uid``): confirms it is running in Kubernetes
  (via ``/etc/hosts``), then extracts the pod UID from cgroup v1
  (``/proc/self/mountinfo``) or cgroup v2 (``/proc/self/cgroup``).
* **Service-name fallback**: if ``OTEL_SERVICE_NAME`` / ``service.name`` are not
  set (and ``DASH0_AUTOMATIC_SERVICE_NAME`` is not ``false``), derives a name
  from the entrypoint script. (Node.js reads ``package.json``; Python has no
  universal equivalent, so this is a best-effort analog.)
* **Distribution attributes**: ``telemetry.distro.name=dash0-python`` and
  ``telemetry.distro.version``.

Existing attributes are never overridden.

Dependency policy
=================

The distribution ships a curated set of upstream OpenTelemetry packages, pinned
exactly in its ``pyproject.toml``: each release is validated against precisely
those versions, and the code assumes them. Version bumps are deliberate,
standalone changes. The pins cover the *entire* installed tree: every package
the distribution pulls in transitively is also declared directly with an exact
pin, so no version is left to transitive resolution. CI enforces both rules via
``scripts/check_pinned_dependencies.py`` (in-repo workspace members are exempt,
as their version is fixed by the checkout).

Injector bootstrap (``sitecustomize.py``)
=========================================

The wheel ships the bootstrap script used for ``PYTHONPATH``-based injection at
``dash0/opentelemetry/injector/sitecustomize.py``. It is not meant to be
imported from that location (importing it executes it); instead, a consumer
building an injectable tree — such as the dash0-operator's instrumentation
image —

1. installs the distribution into a self-contained directory:
   ``pip install --target <dir> dash0-opentelemetry``;
2. copies the script to ``<dir>/sitecustomize.py``;
3. generates ``<dir>/all-dependencies.txt``, a flattened list of every
   requirement of the installed tree (one PEP 508 requirement per line).

The `OpenTelemetry injector
<https://github.com/open-telemetry/opentelemetry-injector>`_ then prepends
``<dir>`` to the ``PYTHONPATH`` of the processes to instrument, so Python's
``site`` machinery runs the script on interpreter startup. The script
initializes the auto-instrumentation only after a set of safety checks —
supported interpreter version, no OpenTelemetry packages already shipped with
the application (double instrumentation), no version conflicts between the
application's dependencies and ``all-dependencies.txt`` — and otherwise
deactivates the injection gracefully, for the current process and its children.
It also bridges ``OTEL_EXPORTER_OTLP_ENDPOINT`` to
``DASH0_OTEL_COLLECTOR_BASE_URL`` when only the former is set. The script stays
valid Python 2.7+ so it can self-deactivate instead of crashing on interpreters
the distribution does not support.

Environment variables
=====================

============================================  ====================================================
Variable                                      Effect
============================================  ====================================================
``DASH0_OTEL_COLLECTOR_BASE_URL`` (required)  Collector base URL; also sets the OTLP endpoint.
``DASH0_DISABLE``                             ``true`` disables the distribution entirely.
``DASH0_AUTOMATIC_SERVICE_NAME``              ``false`` opts out of the service-name fallback.
``DASH0_BOOTSTRAP_SPAN``                      Emit one span with this name at startup.
``DASH0_FLUSH_ON_SIGTERM_SIGINT``             ``true`` flushes telemetry on SIGTERM/SIGINT.
============================================  ====================================================

Status
======

Prototype. The ``otlp_proto_http`` exporter is resolved from the in-repo pyproto
workspace member, published as ``dash0-opentelemetry-exporter-otlp-pyproto-http``
on the Dash0 package index and on public PyPI. Not yet done: the injector's
per-``libc`` packaging and the integration/injection test matrix. Unit tests do
not require a running collector.
