python-opentelemetry-contrib for Debian ======================================= Upstream: https://github.com/open-telemetry/opentelemetry-python-contrib License: Apache-2.0 This package is created with a lot of analysis from https://inference.debian.net and a rewrite assisted by Claude Code. All is based on the basic structure in python-opentelemetry. This whole package is very much open for comments and advice! -- Pieter Lenaerts Sun, 18 Oct 2026 14:31:14 +0200 Overview -------- This source package builds binary packages out of the OpenTelemetry Python Contrib monorepo. That upstream repository contains a large number of independent Python packages: a base "opentelemetry-instrumentation" package (the shared framework all instrumentations build on), dozens of individual instrumentation libraries (one per instrumented framework/stack), plus a few exporters, propagators and utility packages. They are all carried in a single source tarball and are released in lockstep with a common version. This source package builds a growing subset of them, one binary package per upstream sub-project. Binary packages --------------- * python3-opentelemetry-instrumentation (opentelemetry-instrumentation/) The base package everything else depends on: the BaseInstrumentor ABC, dependency-conflict detection, semantic-convention helpers, propagators, the sqlcommenter/utility helpers, and the "opentelemetry-instrument" / "opentelemetry-bootstrap" command line tools. * python3-opentelemetry-util-http (util/opentelemetry-util-http/) HTTP helpers shared by the web framework instrumentations. Upstream declares no dependencies for it, but its httplib module imports wrapt and opentelemetry.instrumentation, so these are added by hand in debian/control. * python3-opentelemetry-instrumentation-, for aiohttp-client, aiohttp-server, asgi, aws-lambda, django, fastapi, flask, httpx, requests, system-metrics and wsgi (all under instrumentation/opentelemetry-instrumentation-/) * python3-opentelemetry-propagator-aws-xray (propagator/opentelemetry-propagator-aws-xray/), needed by aws-lambda * python-opentelemetry-contrib-doc The HTML API reference of all of the above, built from docs/. Dependency chain between them (besides the base package, which they all need): util-http <- wsgi <- django, flask util-http <- asgi <- fastapi, django (optional, only for ASGI deployments) util-http <- aiohttp-client, aiohttp-server, httpx, requests propagator-aws-xray <- aws-lambda Rationale --------- Logfire, which is a dependency of python-mcp and, further down the chain, home-assistant, only needs the base opentelemetry-instrumentation package at runtime: the individual instrumentation packages are optional extras that Logfire imports lazily, only when a specific framework integration is used. The other instrumentations were added because their frameworks are in Debian and they allow running more of the Logfire test suite: its integration tests and documentation examples call logfire.instrument_(), which needs the matching instrumentation package. debian/rules ------------ debian/rules follows the structure Carsten Schoenert uses in the python-opentelemetry source package. Every sub-project is listed in one of these variables, by the upstream directory it lives in: PYTHON_OPENTELEMETRY_PACKAGES ./ PYTHON_OPENTELEMETRY_UTIL_PACKAGES util/ PYTHON_OPENTELEMETRY_INSTRUMENTATION_PACKAGES instrumentation/ PYTHON_OPENTELEMETRY_PROPAGATOR_PACKAGES propagator/ The dh_auto_build and dh_auto_install overrides loop over those lists and run dh_auto_build / dh_auto_install --buildsystem=pybuild --sourcedirectory -- --name= once per sub-project. pybuild's --name makes it stage the files directly into debian/python3-. Since --sourcedirectory is only passed to those dh_auto_* calls (not to the dh sequence), dh_missing finds no debian/tmp and has nothing to check, so no override_dh_missing is needed anymore. The sub-projects import each other (django needs wsgi and util-http, the wsgi tests need util-http, ...), so after building, all .pybuild/cpython3_*_opentelemetry-*/build folders are copied into .pybuild/dist-packages/build, which the tests use as PYTHONPATH. Adding another instrumentation boils down to: * adding its directory name to the right variable in debian/rules; * a Package: stanza in debian/control (Architecture: all). Runtime Depends are generated by dh_python3 from the sub-project's pyproject.toml. Dependencies on other binaries of this source are mapped in debian/py3dist-overrides. The instrumented framework is an optional "instruments" extra upstream, so it goes to Recommends; * its test Build-Depends, gated with ; * a Test-Command stanza in debian/tests/control; * its documentation page in the debian_docs list in docs/conf.py, see "Documentation" below. Tests ----- override_dh_auto_test changes into each sub-project's directory and runs "python3 -m pytest tests" with the shared PYTHONPATH. The tests directory is passed explicitly because the repository-root pytest.ini has a testpaths pointing at the falcon instrumentation. A failing test suite does not stop the loops: every suite runs, failing ones are recorded in .pybuild/tests-failed, and the build fails at the end, listing them. That way one build shows the failures of all packages. The base package is tested against its own build folder only, which is what upstream does too. Its auto_instrumentation tests call initialize(), which loads every installed instrumentor entry point; with the shared folder that imports django and makes test_utils.py::UnwrapTestCase::test_noop_if_module_not_imported fail. Most test suites need the opentelemetry.test helpers (TestBase, WsgiTestBase, HttpTestBase, ...) from the opentelemetry-test-utils distribution. That one lives in the opentelemetry-python repository and is built as python3-opentelemetry-test-utils by the python-opentelemetry source package. Tests that cannot pass in Debian are skipped by quilt patches, with a pytest skip mark (or pytest.importorskip() when a module imports a missing package) and a specific reason: * skip-requests-tests-needing-mocket.patch: mocket is not packaged. * skip-aiohttp-client-tests-needing-http-server-mock.patch: http_server_mock is not packaged. * skip-aiohttp-client-tests-for-newer-aiohttp.patch: upstream tests against aiohttp 3.10, Debian has a much newer aiohttp that behaves differently in four tests. * skip-fastapi-tests-failing-in-debian.patch: two tests expect fastapi to be the only installed instrumentation, which is not true with the shared PYTHONPATH; seven record more spans than expected with Debian's newer FastAPI and Starlette. Manual pages ------------ Upstream ships no manual pages for opentelemetry-bootstrap and opentelemetry-instrument. override_dh_auto_install generates them with help2man from the --help and --version output of the installed scripts, unless the nodoc build profile is active (dh_installman skips them then). The scripts need their runtime dependencies for that, so those are marked in Build-Depends-Indep. The scripts import their modules from the build folder of the opentelemetry-instrumentation sub-project: during dh_auto_install, pybuild installs into versioned usr/lib/python3.X/dist-packages folders, which dh_python3 only merges into usr/lib/python3/dist-packages afterwards. The scripts use argparse, whose output needs some adapting, which debian/help2man-wrapper does: * argparse writes "usage:", help2man only makes a SYNOPSIS out of "Usage:". Only the first line of the usage is kept. * opentelemetry-instrument adds an option without description for every OTEL_* environment variable registered by the installed OpenTelemetry packages (about 90 with the SDK installed). Those depend on what is installed at build time, so they are dropped. The manual page refers to --help for them instead. Its SYNOPSIS is set in the include file. COLUMNS=1000 keeps argparse from wrapping lines at hyphens, which help2man would join without the hyphen. NO_COLOR=1 keeps colour codes out of the help output of newer Python versions. debian/opentelemetry-{bootstrap,instrument}.h2m are the help2man include files with the Debian specific notes. Documentation ------------- The python-opentelemetry-contrib-doc package is built the same way as python-opentelemetry-doc in the python-opentelemetry source package, which serves as the reference for it: same Build-Depends pattern, same override_dh_sphinxdoc in debian/rules, same doc-base file and the same two docs patches, adapted to this repository: * docs-Don-t-load-SVG-graphic-for-Slack-Chat-link.patch replaces the remote Slack badge image with a plain link (privacy). * Use-local-intersphinx-resources-where-possible.patch points intersphinx at the objects.inv files of the -doc packages in the archive (python3-doc, python-aiohttp-doc, python-wrapt-doc and python-opentelemetry-doc), as the build has no network access. On top of that, this repository needs one more patch: * docs-Only-build-the-pages-of-sub-projects-shipped-in-Debian.patch The upstream docs cover the whole monorepo. Sphinx builds every page, whether it is in a toctree or not, and autodoc fails to import the modules of the sub-projects we don't build. So docs/conf.py gets a debian_docs list of the pages to build, everything else is added to exclude_patterns, and the toctrees in docs/index.rst that would be empty are dropped. When adding a binary package, add its page to debian_docs (there is no docs page for util-http upstream). Like in python-opentelemetry, the documentation is built in override_dh_sphinxdoc, with .pybuild/dist-packages/build as PYTHONPATH. The runtime dependencies that autodoc needs to import the documented modules are marked in Build-Depends-Indep, so they are installed unless both the nocheck and nodoc profiles are active. Sphinx emits warnings about unresolved references (conf.py sets nitpicky = True). As in python-opentelemetry, these are not fatal. Autopkgtests ------------ debian/tests/control has one Test-Command per binary package, running debian/tests/run-unittests . That script copies the sub-project's tests to $AUTOPKGTEST_TMP and runs them with every supported python3 version against the installed packages, so the repository-root pytest.ini is not picked up there either. The "Testsuite: autopkgtest-pkg-pybuild" approach can only test a single sub-project (selected through PYBUILD_DIR), so it was dropped when more binary packages were added. Currently, the autopkgtests prepare a specific test bed for each binary. That is a lot of overhead setting up and tearing down, but I don't see another way to have autopkgtests cover the binary dependencies.