open-telemetry / open-telemetry/opentelemetry-python-contrib

Bare lower-bound constraints on pre-1.0 (0.x) target libraries are not meaningful compatibility constraints

Open
#4,931 0 comments 0 reactions 0 assignees View on GitHub

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.