open-telemetry / open-telemetry/opentelemetry-python-contrib
Bare lower-bound constraints on pre-1.0 (0.x) target libraries are not meaningful compatibility constraints
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 1.1k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 16
Description
What
A number of instrumentation packages declare their target-library dependency as a bare lower bound against a pre-1.0 (0.x.y) version, e.g.:
| Package | Constraint | Location |
|---|---|---|
asyncpg |
asyncpg >= 0.12.0 |
instrumentation/opentelemetry-instrumentation-asyncpg (pyproject.toml, package.py) |
httpx |
httpx >= 0.18.0 |
instrumentation/opentelemetry-instrumentation-httpx |
pika |
pika >= 0.12.0 |
instrumentation/opentelemetry-instrumentation-pika |
tortoise-orm |
tortoise-orm >= 0.17.0 |
instrumentation/opentelemetry-instrumentation-tortoiseorm |
aiopg |
aiopg >= 0.13.0, < 2.0.0 |
instrumentation/opentelemetry-instrumentation-aiopg |
(The same strings are duplicated into each package's _instruments tuple and into opentelemetry-instrumentation/.../bootstrap_gen.py.)
I'd like to argue that a constraint of the form dep >= 0.x.y (a bare lower bound whose bound is a pre-1.0 version) is not a meaningful compatibility constraint, and to open a discussion about what these should be instead.
Why it doesn't make sense
1. For a 0.x dependency, the lower bound guarantees nothing and the missing upper bound is where all the risk is.
Under SemVer, 0.y.z explicitly means the public API is unstable: breaking changes are allowed in every minor (0.y) bump. So httpx >= 0.18.0 claims the instrumentation is compatible with 0.18, 0.19, 0.20, … 1.0, 2.0, and everything after — forever. For a package that is permitted to break its API on each minor release, that is an assertion we cannot make and do not test. The one side of the range that would actually protect users (an upper bound) is exactly the side that's absent.
2. Instrumentation is more sensitive to minor churn than an ordinary API consumer.
These packages wrap/monkeypatch internal call sites of the target library (handle_request, connection/cursor internals, etc.), not just its public API. Internal signatures are precisely what a 0.x project changes freely between minor versions. So instrumentation deserves a tighter bound than normal dependencies, yet here it has effectively none.
3. The lower bound is spuriously precise and usually not load-bearing.
>= 0.13.0 / >= 0.18.0 etc. do not correspond to a feature the instrumentation actually requires — they're "whatever version existed when the code was written." A patch-precise minimum with no corresponding real requirement gives a false impression that compatibility has been reasoned about, when the resolver behaviour it produces ("any version at or above X") is the opposite of what a 0.x target needs.
Net effect: the constraint neither reflects the versions actually tested nor prevents installation against a future 0.x release that has broken the internals being patched. It reads as a compatibility statement but provides no compatibility protection.
Suggested direction
For pre-1.0 target libraries, prefer a bounded range that reflects what is actually tested, e.g. a compatible-release / capped form such as dep >= 0.18.0, < 0.N (or ~= where appropriate), and keep the bound in sync with the versions exercised in each package's test matrix. Happy to discuss the exact policy before touching any package.
I can follow up with the full list of affected specifiers if useful.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Review the affected instrumentation packages, including each pyproject.toml and package.py, then trace the duplicated constraints in the _instruments tuples and instrumentation/opentelemetry-instrumentation/bootstrap_gen.py. Compare those bounds with the versions exercised in each package's test matrix. Done means agreeing on a bounded pre-1.0 dependency policy and synchronizing the affected metadata and generated values.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- observability
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100