open-telemetry / open-telemetry/opentelemetry-python-contrib
requests instrumentation: document request_hook mutation and propagation ordering
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 1.1k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 16
Description
What problem are you trying to solve?
The opentelemetry-instrumentation-requests docs describe request_hook as a way to extend tracing behavior, but the hook receives the live requests.PreparedRequest and therefore can also change the actual outbound request.
On current main, the ordering is effectively:
create CLIENT span
-> request_hook(span, prepared_request)
-> OpenTelemetry inject(headers)
-> requests.Session.send(...)
So two details are easy to miss:
- mutations performed by
request_hookaffect the real request sent to the remote system; - propagation injection happens after the hook, so OpenTelemetry-owned propagation fields may replace values the hook set for those fields.
I ran into a production-shaped failure mode around this boundary: an observability hook copied request-context headers into an outgoing connector request without preserving values already owned by the connector. The instrumentation path then changed application behavior rather than merely observing it.
This was application hook code rather than a bug in the built-in requests instrumentation, but the current docs make the execution semantics easy to misread.
Proposed documentation clarification
I think the Request/Response hooks section should state explicitly that request_hook receives the mutable outbound PreparedRequest and runs before propagation injection.
A short warning/example could establish a conservative rule:
Instrumentation hooks are executable request-path behavior. If a request hook mutates headers, it should preserve application/connector-owned values unless it explicitly owns that header. Avoid copying arbitrary inbound headers wholesale into an outbound request.
It would also be useful to document the propagation ordering for trace context:
application/connector prepares request
request_hook may inspect/mutate PreparedRequest
OpenTelemetry propagator injects trace context
request is sent
That makes it clear that a hook should not depend on being the final writer of traceparent, tracestate, or other fields owned by the configured propagator.
Why this belongs in the instrumentation docs
Hooks are frequently introduced as observability customization points, so users may reasonably assume that they are observational unless told otherwise. In practice they sit on the live request path.
The distinction matters because header precedence can be correctness- or authorization-sensitive for application connectors. A tracing customization that overwrites an application-owned header can create a functional defect that is surprisingly hard to attribute to observability.
This is especially relevant for shared instrumentation packages reused by many services: one unsafe hook implementation can create the same defect class across otherwise unrelated consumers.
Suggested acceptance criteria
- Document that
request_hookreceives the live mutablePreparedRequest. - Document that it runs before OpenTelemetry propagation injection in the requests instrumentation.
- Warn against wholesale copying of inbound/context headers into outbound requests.
- Recommend preserving application/connector-owned header values unless the hook intentionally owns that field.
- Add a small example/test if maintainers think executable documentation of the ordering is useful.
Scope
This is not proposing a new header-ownership API, middleware system, or propagator behavior change.
The current implementation ordering may be perfectly reasonable. The request is only to make the mutation and precedence semantics explicit so users do not accidentally turn an observability hook into an undocumented request-rewriting layer.
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
Start with the opentelemetry-instrumentation-requests documentation's Request/Response hooks section and verify the described ordering against current main. Document that request_hook receives the live mutable PreparedRequest, runs before propagation injection, and should preserve application- or connector-owned headers. Consider the proposed small example or test only if maintainers find executable ordering documentation useful.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 78/100