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

requests instrumentation: document request_hook mutation and propagation ordering

Open Beginner friendly
#4,990 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 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:

  1. mutations performed by request_hook affect the real request sent to the remote system;
  2. 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_hook receives the live mutable PreparedRequest.
  • 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

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

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.