dash0-opentelemetry 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,26 @@
1
+ # Byte-compiled / optimized
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ .eggs/
11
+
12
+ # Test / coverage
13
+ .pytest_cache/
14
+ .coverage
15
+ htmlcov/
16
+ .tox/
17
+
18
+ # Environments
19
+ .venv/
20
+ venv/
21
+ .env
22
+
23
+ # Editor / OS
24
+ .idea/
25
+ .vscode/
26
+ .DS_Store
@@ -0,0 +1,253 @@
1
+ Metadata-Version: 2.4
2
+ Name: dash0-opentelemetry
3
+ Version: 0.3.1
4
+ Summary: Dash0 OpenTelemetry distribution for Python
5
+ Author: Dash0
6
+ License-Expression: Apache-2.0
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: asgiref==3.12.1
18
+ Requires-Dist: dash0-opentelemetry-exporter-otlp-pyproto-grpc==1.44.0.post1
19
+ Requires-Dist: dash0-opentelemetry-exporter-otlp-pyproto-http==1.44.0.post1
20
+ Requires-Dist: opentelemetry-api==1.44.0
21
+ Requires-Dist: opentelemetry-instrumentation-aio-pika==0.65b0
22
+ Requires-Dist: opentelemetry-instrumentation-aiohttp-client==0.65b0
23
+ Requires-Dist: opentelemetry-instrumentation-aiohttp-server==0.65b0
24
+ Requires-Dist: opentelemetry-instrumentation-aiokafka==0.65b0
25
+ Requires-Dist: opentelemetry-instrumentation-aiopg==0.65b0
26
+ Requires-Dist: opentelemetry-instrumentation-asgi==0.65b0
27
+ Requires-Dist: opentelemetry-instrumentation-asyncclick==0.65b0
28
+ Requires-Dist: opentelemetry-instrumentation-asyncio==0.65b0
29
+ Requires-Dist: opentelemetry-instrumentation-asyncpg==0.65b0
30
+ Requires-Dist: opentelemetry-instrumentation-boto3sqs==0.65b0
31
+ Requires-Dist: opentelemetry-instrumentation-botocore==0.65b0
32
+ Requires-Dist: opentelemetry-instrumentation-cassandra==0.65b0
33
+ Requires-Dist: opentelemetry-instrumentation-celery==0.65b0
34
+ Requires-Dist: opentelemetry-instrumentation-click==0.65b0
35
+ Requires-Dist: opentelemetry-instrumentation-confluent-kafka==0.65b0
36
+ Requires-Dist: opentelemetry-instrumentation-dbapi==0.65b0
37
+ Requires-Dist: opentelemetry-instrumentation-django==0.65b0
38
+ Requires-Dist: opentelemetry-instrumentation-exceptions==0.65b0
39
+ Requires-Dist: opentelemetry-instrumentation-falcon==0.65b0
40
+ Requires-Dist: opentelemetry-instrumentation-fastapi==0.65b0
41
+ Requires-Dist: opentelemetry-instrumentation-flask==0.65b0
42
+ Requires-Dist: opentelemetry-instrumentation-grpc==0.65b0
43
+ Requires-Dist: opentelemetry-instrumentation-httpx==0.65b0
44
+ Requires-Dist: opentelemetry-instrumentation-jinja2==0.65b0
45
+ Requires-Dist: opentelemetry-instrumentation-kafka-python==0.65b0
46
+ Requires-Dist: opentelemetry-instrumentation-logging==0.65b0
47
+ Requires-Dist: opentelemetry-instrumentation-mysql==0.65b0
48
+ Requires-Dist: opentelemetry-instrumentation-mysqlclient==0.65b0
49
+ Requires-Dist: opentelemetry-instrumentation-openai-v2==2.3b0
50
+ Requires-Dist: opentelemetry-instrumentation-pika==0.65b0
51
+ Requires-Dist: opentelemetry-instrumentation-psycopg2==0.65b0
52
+ Requires-Dist: opentelemetry-instrumentation-psycopg==0.65b0
53
+ Requires-Dist: opentelemetry-instrumentation-pymemcache==0.65b0
54
+ Requires-Dist: opentelemetry-instrumentation-pymongo==0.65b0
55
+ Requires-Dist: opentelemetry-instrumentation-pymssql==0.65b0
56
+ Requires-Dist: opentelemetry-instrumentation-pymysql==0.65b0
57
+ Requires-Dist: opentelemetry-instrumentation-pyramid==0.65b0
58
+ Requires-Dist: opentelemetry-instrumentation-redis==0.65b0
59
+ Requires-Dist: opentelemetry-instrumentation-remoulade==0.65b0
60
+ Requires-Dist: opentelemetry-instrumentation-requests==0.65b0
61
+ Requires-Dist: opentelemetry-instrumentation-sqlalchemy==0.65b0
62
+ Requires-Dist: opentelemetry-instrumentation-sqlite3==0.65b0
63
+ Requires-Dist: opentelemetry-instrumentation-starlette==0.65b0
64
+ Requires-Dist: opentelemetry-instrumentation-structlog==0.65b0
65
+ Requires-Dist: opentelemetry-instrumentation-system-metrics==0.65b0
66
+ Requires-Dist: opentelemetry-instrumentation-threading==0.65b0
67
+ Requires-Dist: opentelemetry-instrumentation-tornado==0.65b0
68
+ Requires-Dist: opentelemetry-instrumentation-tortoiseorm==0.65b0
69
+ Requires-Dist: opentelemetry-instrumentation-urllib3==0.65b0
70
+ Requires-Dist: opentelemetry-instrumentation-urllib==0.65b0
71
+ Requires-Dist: opentelemetry-instrumentation-vertexai==2.2b0
72
+ Requires-Dist: opentelemetry-instrumentation-wsgi==0.65b0
73
+ Requires-Dist: opentelemetry-instrumentation==0.65b0
74
+ Requires-Dist: opentelemetry-propagator-aws-xray==1.0.2
75
+ Requires-Dist: opentelemetry-sdk==1.44.0
76
+ Requires-Dist: opentelemetry-semantic-conventions==0.65b0
77
+ Requires-Dist: opentelemetry-util-genai==0.2b0
78
+ Requires-Dist: opentelemetry-util-http==0.65b0
79
+ Requires-Dist: packaging==26.2
80
+ Requires-Dist: psutil==7.2.2
81
+ Requires-Dist: typing-extensions==4.16.0
82
+ Requires-Dist: wrapt==1.17.3
83
+ Description-Content-Type: text/x-rst
84
+
85
+ ===================
86
+ dash0-opentelemetry
87
+ ===================
88
+
89
+ The Dash0 OpenTelemetry distribution for Python. It is the Python counterpart of
90
+ the Dash0 Node.js distribution (``@dash0/opentelemetry``), adapted to Python's
91
+ distro/configurator machinery, and is meant to be injected into a process (for
92
+ example by the OpenTelemetry injector) with no code changes.
93
+
94
+ Entry points
95
+ ============
96
+
97
+ ``Dash0Distro`` (``opentelemetry_distro``)
98
+ Runs first, before the configurator. It:
99
+
100
+ * **Gates** the distribution: does nothing if ``DASH0_DISABLE=true`` or if
101
+ ``DASH0_OTEL_COLLECTOR_BASE_URL`` is unset (nowhere to send telemetry). In
102
+ either case it sets ``OTEL_SDK_DISABLED=true`` and skips instrumentation.
103
+ * Defaults all three signals to the pure-Python OTLP/HTTP exporter
104
+ (``otlp_proto_http``, ``http/protobuf``) and points
105
+ ``OTEL_EXPORTER_OTLP_ENDPOINT`` at ``DASH0_OTEL_COLLECTOR_BASE_URL``. The
106
+ pure-Python exporter has no native dependencies, which is what makes the
107
+ distribution safe to inject onto an arbitrary process' ``PYTHONPATH``.
108
+ When a signal's OTLP protocol does not match the transport the shared
109
+ endpoint targets — its port is the *other* protocol's conventional
110
+ default (``4317`` gRPC / ``4318`` HTTP) — a per-signal
111
+ ``OTEL_EXPORTER_OTLP_<SIGNAL>_ENDPOINT`` is derived by rewriting the
112
+ port (appending the ``v1/<signal>`` path for HTTP), so mixed-protocol
113
+ setups and a base URL on the "wrong" default port still export
114
+ correctly. Custom ports and explicit per-signal endpoints are always
115
+ left untouched.
116
+ * Injects detected **resource attributes** into ``OTEL_RESOURCE_ATTRIBUTES``/
117
+ ``OTEL_SERVICE_NAME`` (see below) so the SDK's Resource picks them up.
118
+ * Overrides ``load_instrumentor`` to activate each instrumentor
119
+ **defensively** — a disabled or failing instrumentor is skipped and logged
120
+ rather than aborting auto-instrumentation of the host process.
121
+
122
+ ``Dash0Configurator`` (``opentelemetry_configurator``)
123
+ Runs after the distro. Delegates to the standard OpenTelemetry SDK
124
+ configurator to build the providers/exporters/Resource from the environment,
125
+ then adds two behaviors from the Node.js distribution:
126
+
127
+ * an optional **bootstrap span** emitted once at startup
128
+ (``DASH0_BOOTSTRAP_SPAN=<name>``);
129
+ * optional **graceful flush** on ``SIGTERM``/``SIGINT``
130
+ (``DASH0_FLUSH_ON_SIGTERM_SIGINT=true``) — normal-exit flushing is already
131
+ handled by the SDK's ``atexit`` provider shutdown.
132
+
133
+ Resource detectors (``opentelemetry_resource_detector``)
134
+ The detected resource attributes (see below) as standard SDK resource
135
+ detectors, one per concern so each can be used (or omitted) independently:
136
+
137
+ * ``dash0_distribution`` — ``telemetry.distro.name``/``telemetry.distro.version``;
138
+ * ``dash0_kubernetes`` — ``k8s.pod.uid``;
139
+ * ``dash0_service_name`` — wraps the upstream service detection (a
140
+ process-stable ``service.instance.id`` and ``service.name`` from
141
+ ``OTEL_SERVICE_NAME``) and adds the distro's entrypoint-derived
142
+ ``service.name`` fallback, so there is no need to also list the built-in
143
+ ``service`` detector.
144
+
145
+ They can be referenced via ``OTEL_EXPERIMENTAL_RESOURCE_DETECTORS``, or
146
+ explicitly in a declarative config file under
147
+ ``resource.detection/development.detectors``.
148
+
149
+ Instrumentations
150
+ ================
151
+
152
+ The distribution depends on the full upstream auto-instrumentation set — every
153
+ package enumerated by the ``bootstrap_gen`` module of
154
+ ``opentelemetry-instrumentation`` (the list behind ``opentelemetry-bootstrap``)
155
+ — pinned to a single contrib version, so injected processes need no bootstrap
156
+ step. Instrumentations only activate when their target library is present,
157
+ which makes carrying all of them safe.
158
+
159
+ Deviations from the upstream list:
160
+
161
+ * ``opentelemetry-propagator-aws-xray`` is shipped although upstream's
162
+ bootstrap list only covers instrumentations (the Dash0 operator's
163
+ instrumentation image always carried it).
164
+ * ``opentelemetry-exporter-prometheus``,
165
+ ``opentelemetry-propagator-ot-trace``, and
166
+ ``opentelemetry-instrumentation-aws-lambda`` are deliberately not shipped.
167
+
168
+ ``tests/test_instrumentations.py`` cross-checks the dependency block against
169
+ the installed upstream list, so a contrib version bump that adds or removes
170
+ instrumentations fails CI until the block is re-synced. Dependabot keeps the
171
+ pins themselves moving (all ``opentelemetry-*`` packages are grouped into one
172
+ update, since the contrib instrumentations only resolve when they share one
173
+ contrib version).
174
+
175
+ Resource detection
176
+ ==================
177
+
178
+ Ported from the Node.js distribution's custom detectors:
179
+
180
+ * **Kubernetes pod UID** (``k8s.pod.uid``): confirms it is running in Kubernetes
181
+ (via ``/etc/hosts``), then extracts the pod UID from cgroup v1
182
+ (``/proc/self/mountinfo``) or cgroup v2 (``/proc/self/cgroup``).
183
+ * **Service-name fallback**: if ``OTEL_SERVICE_NAME`` / ``service.name`` are not
184
+ set (and ``DASH0_AUTOMATIC_SERVICE_NAME`` is not ``false``), derives a name
185
+ from the entrypoint script. (Node.js reads ``package.json``; Python has no
186
+ universal equivalent, so this is a best-effort analog.)
187
+ * **Distribution attributes**: ``telemetry.distro.name=dash0-python`` and
188
+ ``telemetry.distro.version``.
189
+
190
+ Existing attributes are never overridden.
191
+
192
+ Dependency policy
193
+ =================
194
+
195
+ The distribution ships a curated set of upstream OpenTelemetry packages, pinned
196
+ exactly in its ``pyproject.toml``: each release is validated against precisely
197
+ those versions, and the code assumes them. Version bumps are deliberate,
198
+ standalone changes. The pins cover the *entire* installed tree: every package
199
+ the distribution pulls in transitively is also declared directly with an exact
200
+ pin, so no version is left to transitive resolution. CI enforces both rules via
201
+ ``scripts/check_pinned_dependencies.py`` (in-repo workspace members are exempt,
202
+ as their version is fixed by the checkout).
203
+
204
+ Injector bootstrap (``sitecustomize.py``)
205
+ =========================================
206
+
207
+ The wheel ships the bootstrap script used for ``PYTHONPATH``-based injection at
208
+ ``dash0/opentelemetry/injector/sitecustomize.py``. It is not meant to be
209
+ imported from that location (importing it executes it); instead, a consumer
210
+ building an injectable tree — such as the dash0-operator's instrumentation
211
+ image —
212
+
213
+ 1. installs the distribution into a self-contained directory:
214
+ ``pip install --target <dir> dash0-opentelemetry``;
215
+ 2. copies the script to ``<dir>/sitecustomize.py``;
216
+ 3. generates ``<dir>/all-dependencies.txt``, a flattened list of every
217
+ requirement of the installed tree (one PEP 508 requirement per line).
218
+
219
+ The `OpenTelemetry injector
220
+ <https://github.com/open-telemetry/opentelemetry-injector>`_ then prepends
221
+ ``<dir>`` to the ``PYTHONPATH`` of the processes to instrument, so Python's
222
+ ``site`` machinery runs the script on interpreter startup. The script
223
+ initializes the auto-instrumentation only after a set of safety checks —
224
+ supported interpreter version, no OpenTelemetry packages already shipped with
225
+ the application (double instrumentation), no version conflicts between the
226
+ application's dependencies and ``all-dependencies.txt`` — and otherwise
227
+ deactivates the injection gracefully, for the current process and its children.
228
+ It also bridges ``OTEL_EXPORTER_OTLP_ENDPOINT`` to
229
+ ``DASH0_OTEL_COLLECTOR_BASE_URL`` when only the former is set. The script stays
230
+ valid Python 2.7+ so it can self-deactivate instead of crashing on interpreters
231
+ the distribution does not support.
232
+
233
+ Environment variables
234
+ =====================
235
+
236
+ ============================================ ====================================================
237
+ Variable Effect
238
+ ============================================ ====================================================
239
+ ``DASH0_OTEL_COLLECTOR_BASE_URL`` (required) Collector base URL; also sets the OTLP endpoint.
240
+ ``DASH0_DISABLE`` ``true`` disables the distribution entirely.
241
+ ``DASH0_AUTOMATIC_SERVICE_NAME`` ``false`` opts out of the service-name fallback.
242
+ ``DASH0_BOOTSTRAP_SPAN`` Emit one span with this name at startup.
243
+ ``DASH0_FLUSH_ON_SIGTERM_SIGINT`` ``true`` flushes telemetry on SIGTERM/SIGINT.
244
+ ============================================ ====================================================
245
+
246
+ Status
247
+ ======
248
+
249
+ Prototype. The ``otlp_proto_http`` exporter is resolved from the in-repo pyproto
250
+ workspace member, published as ``dash0-opentelemetry-exporter-otlp-pyproto-http``
251
+ on the Dash0 package index and on public PyPI. Not yet done: the injector's
252
+ per-``libc`` packaging and the integration/injection test matrix. Unit tests do
253
+ not require a running collector.
@@ -0,0 +1,169 @@
1
+ ===================
2
+ dash0-opentelemetry
3
+ ===================
4
+
5
+ The Dash0 OpenTelemetry distribution for Python. It is the Python counterpart of
6
+ the Dash0 Node.js distribution (``@dash0/opentelemetry``), adapted to Python's
7
+ distro/configurator machinery, and is meant to be injected into a process (for
8
+ example by the OpenTelemetry injector) with no code changes.
9
+
10
+ Entry points
11
+ ============
12
+
13
+ ``Dash0Distro`` (``opentelemetry_distro``)
14
+ Runs first, before the configurator. It:
15
+
16
+ * **Gates** the distribution: does nothing if ``DASH0_DISABLE=true`` or if
17
+ ``DASH0_OTEL_COLLECTOR_BASE_URL`` is unset (nowhere to send telemetry). In
18
+ either case it sets ``OTEL_SDK_DISABLED=true`` and skips instrumentation.
19
+ * Defaults all three signals to the pure-Python OTLP/HTTP exporter
20
+ (``otlp_proto_http``, ``http/protobuf``) and points
21
+ ``OTEL_EXPORTER_OTLP_ENDPOINT`` at ``DASH0_OTEL_COLLECTOR_BASE_URL``. The
22
+ pure-Python exporter has no native dependencies, which is what makes the
23
+ distribution safe to inject onto an arbitrary process' ``PYTHONPATH``.
24
+ When a signal's OTLP protocol does not match the transport the shared
25
+ endpoint targets — its port is the *other* protocol's conventional
26
+ default (``4317`` gRPC / ``4318`` HTTP) — a per-signal
27
+ ``OTEL_EXPORTER_OTLP_<SIGNAL>_ENDPOINT`` is derived by rewriting the
28
+ port (appending the ``v1/<signal>`` path for HTTP), so mixed-protocol
29
+ setups and a base URL on the "wrong" default port still export
30
+ correctly. Custom ports and explicit per-signal endpoints are always
31
+ left untouched.
32
+ * Injects detected **resource attributes** into ``OTEL_RESOURCE_ATTRIBUTES``/
33
+ ``OTEL_SERVICE_NAME`` (see below) so the SDK's Resource picks them up.
34
+ * Overrides ``load_instrumentor`` to activate each instrumentor
35
+ **defensively** — a disabled or failing instrumentor is skipped and logged
36
+ rather than aborting auto-instrumentation of the host process.
37
+
38
+ ``Dash0Configurator`` (``opentelemetry_configurator``)
39
+ Runs after the distro. Delegates to the standard OpenTelemetry SDK
40
+ configurator to build the providers/exporters/Resource from the environment,
41
+ then adds two behaviors from the Node.js distribution:
42
+
43
+ * an optional **bootstrap span** emitted once at startup
44
+ (``DASH0_BOOTSTRAP_SPAN=<name>``);
45
+ * optional **graceful flush** on ``SIGTERM``/``SIGINT``
46
+ (``DASH0_FLUSH_ON_SIGTERM_SIGINT=true``) — normal-exit flushing is already
47
+ handled by the SDK's ``atexit`` provider shutdown.
48
+
49
+ Resource detectors (``opentelemetry_resource_detector``)
50
+ The detected resource attributes (see below) as standard SDK resource
51
+ detectors, one per concern so each can be used (or omitted) independently:
52
+
53
+ * ``dash0_distribution`` — ``telemetry.distro.name``/``telemetry.distro.version``;
54
+ * ``dash0_kubernetes`` — ``k8s.pod.uid``;
55
+ * ``dash0_service_name`` — wraps the upstream service detection (a
56
+ process-stable ``service.instance.id`` and ``service.name`` from
57
+ ``OTEL_SERVICE_NAME``) and adds the distro's entrypoint-derived
58
+ ``service.name`` fallback, so there is no need to also list the built-in
59
+ ``service`` detector.
60
+
61
+ They can be referenced via ``OTEL_EXPERIMENTAL_RESOURCE_DETECTORS``, or
62
+ explicitly in a declarative config file under
63
+ ``resource.detection/development.detectors``.
64
+
65
+ Instrumentations
66
+ ================
67
+
68
+ The distribution depends on the full upstream auto-instrumentation set — every
69
+ package enumerated by the ``bootstrap_gen`` module of
70
+ ``opentelemetry-instrumentation`` (the list behind ``opentelemetry-bootstrap``)
71
+ — pinned to a single contrib version, so injected processes need no bootstrap
72
+ step. Instrumentations only activate when their target library is present,
73
+ which makes carrying all of them safe.
74
+
75
+ Deviations from the upstream list:
76
+
77
+ * ``opentelemetry-propagator-aws-xray`` is shipped although upstream's
78
+ bootstrap list only covers instrumentations (the Dash0 operator's
79
+ instrumentation image always carried it).
80
+ * ``opentelemetry-exporter-prometheus``,
81
+ ``opentelemetry-propagator-ot-trace``, and
82
+ ``opentelemetry-instrumentation-aws-lambda`` are deliberately not shipped.
83
+
84
+ ``tests/test_instrumentations.py`` cross-checks the dependency block against
85
+ the installed upstream list, so a contrib version bump that adds or removes
86
+ instrumentations fails CI until the block is re-synced. Dependabot keeps the
87
+ pins themselves moving (all ``opentelemetry-*`` packages are grouped into one
88
+ update, since the contrib instrumentations only resolve when they share one
89
+ contrib version).
90
+
91
+ Resource detection
92
+ ==================
93
+
94
+ Ported from the Node.js distribution's custom detectors:
95
+
96
+ * **Kubernetes pod UID** (``k8s.pod.uid``): confirms it is running in Kubernetes
97
+ (via ``/etc/hosts``), then extracts the pod UID from cgroup v1
98
+ (``/proc/self/mountinfo``) or cgroup v2 (``/proc/self/cgroup``).
99
+ * **Service-name fallback**: if ``OTEL_SERVICE_NAME`` / ``service.name`` are not
100
+ set (and ``DASH0_AUTOMATIC_SERVICE_NAME`` is not ``false``), derives a name
101
+ from the entrypoint script. (Node.js reads ``package.json``; Python has no
102
+ universal equivalent, so this is a best-effort analog.)
103
+ * **Distribution attributes**: ``telemetry.distro.name=dash0-python`` and
104
+ ``telemetry.distro.version``.
105
+
106
+ Existing attributes are never overridden.
107
+
108
+ Dependency policy
109
+ =================
110
+
111
+ The distribution ships a curated set of upstream OpenTelemetry packages, pinned
112
+ exactly in its ``pyproject.toml``: each release is validated against precisely
113
+ those versions, and the code assumes them. Version bumps are deliberate,
114
+ standalone changes. The pins cover the *entire* installed tree: every package
115
+ the distribution pulls in transitively is also declared directly with an exact
116
+ pin, so no version is left to transitive resolution. CI enforces both rules via
117
+ ``scripts/check_pinned_dependencies.py`` (in-repo workspace members are exempt,
118
+ as their version is fixed by the checkout).
119
+
120
+ Injector bootstrap (``sitecustomize.py``)
121
+ =========================================
122
+
123
+ The wheel ships the bootstrap script used for ``PYTHONPATH``-based injection at
124
+ ``dash0/opentelemetry/injector/sitecustomize.py``. It is not meant to be
125
+ imported from that location (importing it executes it); instead, a consumer
126
+ building an injectable tree — such as the dash0-operator's instrumentation
127
+ image —
128
+
129
+ 1. installs the distribution into a self-contained directory:
130
+ ``pip install --target <dir> dash0-opentelemetry``;
131
+ 2. copies the script to ``<dir>/sitecustomize.py``;
132
+ 3. generates ``<dir>/all-dependencies.txt``, a flattened list of every
133
+ requirement of the installed tree (one PEP 508 requirement per line).
134
+
135
+ The `OpenTelemetry injector
136
+ <https://github.com/open-telemetry/opentelemetry-injector>`_ then prepends
137
+ ``<dir>`` to the ``PYTHONPATH`` of the processes to instrument, so Python's
138
+ ``site`` machinery runs the script on interpreter startup. The script
139
+ initializes the auto-instrumentation only after a set of safety checks —
140
+ supported interpreter version, no OpenTelemetry packages already shipped with
141
+ the application (double instrumentation), no version conflicts between the
142
+ application's dependencies and ``all-dependencies.txt`` — and otherwise
143
+ deactivates the injection gracefully, for the current process and its children.
144
+ It also bridges ``OTEL_EXPORTER_OTLP_ENDPOINT`` to
145
+ ``DASH0_OTEL_COLLECTOR_BASE_URL`` when only the former is set. The script stays
146
+ valid Python 2.7+ so it can self-deactivate instead of crashing on interpreters
147
+ the distribution does not support.
148
+
149
+ Environment variables
150
+ =====================
151
+
152
+ ============================================ ====================================================
153
+ Variable Effect
154
+ ============================================ ====================================================
155
+ ``DASH0_OTEL_COLLECTOR_BASE_URL`` (required) Collector base URL; also sets the OTLP endpoint.
156
+ ``DASH0_DISABLE`` ``true`` disables the distribution entirely.
157
+ ``DASH0_AUTOMATIC_SERVICE_NAME`` ``false`` opts out of the service-name fallback.
158
+ ``DASH0_BOOTSTRAP_SPAN`` Emit one span with this name at startup.
159
+ ``DASH0_FLUSH_ON_SIGTERM_SIGINT`` ``true`` flushes telemetry on SIGTERM/SIGINT.
160
+ ============================================ ====================================================
161
+
162
+ Status
163
+ ======
164
+
165
+ Prototype. The ``otlp_proto_http`` exporter is resolved from the in-repo pyproto
166
+ workspace member, published as ``dash0-opentelemetry-exporter-otlp-pyproto-http``
167
+ on the Dash0 package index and on public PyPI. Not yet done: the injector's
168
+ per-``libc`` packaging and the integration/injection test matrix. Unit tests do
169
+ not require a running collector.
@@ -0,0 +1,147 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "dash0-opentelemetry"
7
+ dynamic = ["version"]
8
+ description = "Dash0 OpenTelemetry distribution for Python"
9
+ readme = "README.rst"
10
+ requires-python = ">=3.10"
11
+ license = "Apache-2.0"
12
+ authors = [{ name = "Dash0" }]
13
+ classifiers = [
14
+ "Development Status :: 3 - Alpha",
15
+ "Intended Audience :: Developers",
16
+ "License :: OSI Approved :: Apache Software License",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.9",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ ]
24
+ # The distribution ships a curated, exactly-pinned set of upstream packages:
25
+ # every release is validated against precisely these versions, and the code
26
+ # assumes them. Bump them together, deliberately, in a dedicated change.
27
+ dependencies = [
28
+ # --- OpenTelemetry packages ---
29
+ "opentelemetry-api == 1.44.0",
30
+ "opentelemetry-sdk == 1.44.0",
31
+ "opentelemetry-instrumentation == 0.65b0",
32
+ "opentelemetry-semantic-conventions == 0.65b0",
33
+ # Pure-Python OTLP exporters (no native dependencies), vendored in this
34
+ # workspace from open-telemetry/opentelemetry-packaging under Dash0-owned
35
+ # distribution names (import paths and entry points stay upstream-shaped).
36
+ # Published on both the Dash0 package index and public PyPI.
37
+ "dash0-opentelemetry-exporter-otlp-pyproto-http == 1.44.0.post1",
38
+ "dash0-opentelemetry-exporter-otlp-pyproto-grpc == 1.44.0.post1",
39
+
40
+ # --- Curated instrumentation set ---
41
+ # The full upstream auto-instrumentation list (the bootstrap_gen module of
42
+ # opentelemetry-instrumentation), shipped as regular dependencies so injected
43
+ # processes need no `opentelemetry-bootstrap` step. Instrumentations only
44
+ # activate when their target library is present, so carrying all of them is
45
+ # safe. tests/test_instrumentations.py fails when this block drifts from the
46
+ # upstream list of the pinned opentelemetry-instrumentation release.
47
+ # Deliberately not shipped: opentelemetry-exporter-prometheus,
48
+ # opentelemetry-propagator-ot-trace, and
49
+ # opentelemetry-instrumentation-aws-lambda.
50
+ "opentelemetry-instrumentation-aio-pika == 0.65b0",
51
+ "opentelemetry-instrumentation-aiohttp-client == 0.65b0",
52
+ "opentelemetry-instrumentation-aiohttp-server == 0.65b0",
53
+ "opentelemetry-instrumentation-aiokafka == 0.65b0",
54
+ "opentelemetry-instrumentation-aiopg == 0.65b0",
55
+ "opentelemetry-instrumentation-asgi == 0.65b0",
56
+ "opentelemetry-instrumentation-asyncclick == 0.65b0",
57
+ "opentelemetry-instrumentation-asyncio == 0.65b0",
58
+ "opentelemetry-instrumentation-asyncpg == 0.65b0",
59
+ "opentelemetry-instrumentation-boto3sqs == 0.65b0",
60
+ "opentelemetry-instrumentation-botocore == 0.65b0",
61
+ "opentelemetry-instrumentation-cassandra == 0.65b0",
62
+ "opentelemetry-instrumentation-celery == 0.65b0",
63
+ "opentelemetry-instrumentation-click == 0.65b0",
64
+ "opentelemetry-instrumentation-confluent-kafka == 0.65b0",
65
+ "opentelemetry-instrumentation-dbapi == 0.65b0",
66
+ "opentelemetry-instrumentation-django == 0.65b0",
67
+ "opentelemetry-instrumentation-exceptions == 0.65b0",
68
+ "opentelemetry-instrumentation-falcon == 0.65b0",
69
+ "opentelemetry-instrumentation-fastapi == 0.65b0",
70
+ "opentelemetry-instrumentation-flask == 0.65b0",
71
+ "opentelemetry-instrumentation-grpc == 0.65b0",
72
+ "opentelemetry-instrumentation-httpx == 0.65b0",
73
+ "opentelemetry-instrumentation-jinja2 == 0.65b0",
74
+ "opentelemetry-instrumentation-kafka-python == 0.65b0",
75
+ "opentelemetry-instrumentation-logging == 0.65b0",
76
+ "opentelemetry-instrumentation-mysql == 0.65b0",
77
+ "opentelemetry-instrumentation-mysqlclient == 0.65b0",
78
+ "opentelemetry-instrumentation-pika == 0.65b0",
79
+ "opentelemetry-instrumentation-psycopg == 0.65b0",
80
+ "opentelemetry-instrumentation-psycopg2 == 0.65b0",
81
+ "opentelemetry-instrumentation-pymemcache == 0.65b0",
82
+ "opentelemetry-instrumentation-pymongo == 0.65b0",
83
+ "opentelemetry-instrumentation-pymssql == 0.65b0",
84
+ "opentelemetry-instrumentation-pymysql == 0.65b0",
85
+ "opentelemetry-instrumentation-pyramid == 0.65b0",
86
+ "opentelemetry-instrumentation-redis == 0.65b0",
87
+ "opentelemetry-instrumentation-remoulade == 0.65b0",
88
+ "opentelemetry-instrumentation-requests == 0.65b0",
89
+ "opentelemetry-instrumentation-sqlalchemy == 0.65b0",
90
+ "opentelemetry-instrumentation-sqlite3 == 0.65b0",
91
+ "opentelemetry-instrumentation-starlette == 0.65b0",
92
+ "opentelemetry-instrumentation-structlog == 0.65b0",
93
+ "opentelemetry-instrumentation-system-metrics == 0.65b0",
94
+ "opentelemetry-instrumentation-threading == 0.65b0",
95
+ "opentelemetry-instrumentation-tornado == 0.65b0",
96
+ "opentelemetry-instrumentation-tortoiseorm == 0.65b0",
97
+ "opentelemetry-instrumentation-urllib == 0.65b0",
98
+ "opentelemetry-instrumentation-urllib3 == 0.65b0",
99
+ "opentelemetry-instrumentation-wsgi == 0.65b0",
100
+ # GenAI instrumentations release on their own version train, not the contrib
101
+ # one. The 2.x line of -vertexai is upstream contrib's; the 0.x line under the
102
+ # same PyPI name belongs to Traceloop's openllmetry — never pin below 2.0b0.
103
+ # openai-v2 is held at 2.3b0: 2.4b0 requires opentelemetry-util-genai >= 0.4b0
104
+ # while vertexai 2.2b0 requires < 0.3b0.
105
+ "opentelemetry-instrumentation-openai-v2 == 2.3b0",
106
+ "opentelemetry-instrumentation-vertexai == 2.2b0",
107
+ "opentelemetry-util-genai == 0.2b0",
108
+ "opentelemetry-util-http == 0.65b0",
109
+ # Shipped on top of the upstream auto-instrumentation list, which only
110
+ # covers instrumentations: the X-Ray propagator was always part of the Dash0
111
+ # operator's instrumentation image.
112
+ "opentelemetry-propagator-aws-xray == 1.0.2",
113
+
114
+ # --- Non-OpenTelemetry packages ---
115
+ # The support libraries the OpenTelemetry packages above pull in
116
+ # transitively, declared here with an exact pin so the full injected tree is
117
+ # spelled out in this file and no version is left to transitive resolution.
118
+ # scripts/check_pinned_dependencies.py fails the build when the declared set
119
+ # drifts from the resolved closure.
120
+ "asgiref == 3.12.1",
121
+ "packaging == 26.2",
122
+ "psutil == 7.2.2",
123
+ "typing-extensions == 4.16.0",
124
+ "wrapt == 1.17.3",
125
+ ]
126
+
127
+ [project.entry-points.opentelemetry_distro]
128
+ dash0 = "dash0.opentelemetry.distro:Dash0Distro"
129
+
130
+ [project.entry-points.opentelemetry_configurator]
131
+ dash0 = "dash0.opentelemetry.configurator:Dash0Configurator"
132
+
133
+ [project.entry-points.opentelemetry_resource_detector]
134
+ dash0_distribution = "dash0.opentelemetry.resource:Dash0DistributionResourceDetector"
135
+ dash0_kubernetes = "dash0.opentelemetry.resource:Dash0KubernetesResourceDetector"
136
+ dash0_service_name = "dash0.opentelemetry.resource:Dash0ServiceNameResourceDetector"
137
+
138
+ [dependency-groups]
139
+ dev = [
140
+ "pytest >= 7.0",
141
+ ]
142
+
143
+ [tool.hatch.version]
144
+ path = "src/dash0/opentelemetry/version.py"
145
+
146
+ [tool.hatch.build.targets.wheel]
147
+ packages = ["src/dash0"]
File without changes
@@ -0,0 +1,41 @@
1
+ """Environment variables read and written by the Dash0 distribution.
2
+
3
+ Grouped here so the distro, the configurator and the resource detection share a
4
+ single definition of each name.
5
+ """
6
+
7
+ # --- Dash0-specific knobs (mirrors the Node.js distribution) ---
8
+
9
+ DASH0_DISABLE = "DASH0_DISABLE"
10
+ """When set to ``true`` the distribution does nothing at all."""
11
+
12
+ DASH0_OTEL_COLLECTOR_BASE_URL = "DASH0_OTEL_COLLECTOR_BASE_URL"
13
+ """Base URL of the collector to export to. Required; without it the
14
+ distribution disables itself, because there is nowhere to send telemetry."""
15
+
16
+ DASH0_AUTOMATIC_SERVICE_NAME = "DASH0_AUTOMATIC_SERVICE_NAME"
17
+ """Set to ``false`` to opt out of deriving a fallback ``service.name``."""
18
+
19
+ DASH0_BOOTSTRAP_SPAN = "DASH0_BOOTSTRAP_SPAN"
20
+ """When set, a single span with this name is emitted once at startup."""
21
+
22
+ DASH0_FLUSH_ON_SIGTERM_SIGINT = "DASH0_FLUSH_ON_SIGTERM_SIGINT"
23
+ """Set to ``true`` to flush telemetry on SIGTERM/SIGINT before exiting."""
24
+
25
+
26
+ # --- Standard OpenTelemetry variables the distribution defaults ---
27
+
28
+ OTEL_TRACES_EXPORTER = "OTEL_TRACES_EXPORTER"
29
+ OTEL_METRICS_EXPORTER = "OTEL_METRICS_EXPORTER"
30
+ OTEL_LOGS_EXPORTER = "OTEL_LOGS_EXPORTER"
31
+ OTEL_EXPORTER_OTLP_PROTOCOL = "OTEL_EXPORTER_OTLP_PROTOCOL"
32
+ OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL"
33
+ OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL"
34
+ OTEL_EXPORTER_OTLP_LOGS_PROTOCOL = "OTEL_EXPORTER_OTLP_LOGS_PROTOCOL"
35
+ OTEL_EXPORTER_OTLP_ENDPOINT = "OTEL_EXPORTER_OTLP_ENDPOINT"
36
+ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"
37
+ OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT"
38
+ OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT"
39
+ OTEL_SERVICE_NAME = "OTEL_SERVICE_NAME"
40
+ OTEL_RESOURCE_ATTRIBUTES = "OTEL_RESOURCE_ATTRIBUTES"
41
+ OTEL_SDK_DISABLED = "OTEL_SDK_DISABLED"