Pure-Python otlp-proto-http over stdlib urllib (drop protobuf + requests) [3/4 RFC] - #5505
Draft
ocelotl wants to merge 4 commits into
Draft
Pure-Python otlp-proto-http over stdlib urllib (drop protobuf + requests) [3/4 RFC]#5505ocelotl wants to merge 4 commits into
ocelotl wants to merge 4 commits into
Conversation
Swap the google.protobuf-generated message classes for hand-written pure-Python encoders under opentelemetry._proto, keeping the public opentelemetry.proto.* import namespace via thin re-export shims. Removes the protobuf (and native upb) dependency entirely; only the serialize path used by the OTLP exporters is implemented (plus the empty export-service response decode).
Point the shared OTLP encoders at the pure-Python opentelemetry-proto package. No google.protobuf dependency; public opentelemetry.exporter.otlp.proto.common.* API preserved via re-export shims over the private _proto implementation.
Drop the requests dependency in favour of stdlib urllib.request + ssl for the OTLP/HTTP export, and use the pure-Python protobuf encoders. Removes both the protobuf and requests native/third-party dependencies. The requests.Session credential-provider feature (session= arg and *_CREDENTIAL_PROVIDER env vars, plus the gcp-auth extra) is not carried over, as it is typed to requests.Session.
…no requests) Reinstates the original exporter's pluggable-client capability without a `requests` dependency: - A `urllib.request.OpenerDirector` is now the supported injectable, via the `session` constructor argument or an `opentelemetry_otlp_credential_provider` entry point named by the existing OTEL_PYTHON_EXPORTER_OTLP_HTTP[_TRACES|_METRICS|_LOGS]_CREDENTIAL_PROVIDER environment variables (previously loaded but never wired in). - A `requests.Session` is still accepted for backwards compatibility, detected structurally (never importing `requests`) and routed through its `.post()`; passing one now emits a DeprecationWarning. Its transport errors are normalized to URLError so the retry loop is unchanged. - Default (no injection) builds a stdlib opener from the SSL context, matching prior behavior. `_common` gains `_resolve_client` (the client seam) and `_opener_client` / `_session_client` senders; `_load_session_from_envvar` becomes `_load_provider_from_envvar`. The three HTTP credential-provider docstrings in opentelemetry-sdk are updated to document the OpenerDirector contract and the requests.Session deprecation. Drops the moot pyproto-vs-requests equivalence test and covers the new client-resolution paths.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Replace the
opentelemetry-exporter-otlp-proto-httptransport with a pure-Python implementation that:protobuf, andurllib.request+sslinstead ofrequests— drops therequestsdependency.Also drops the
googleapis-common-protosdependency (pullsprotobuf) and thegcp-authoptional extra.Why drop
requestsrequestsis the last third-party runtime dependency on the OTLP/HTTP export path. Everything the exporter needs — gzip/deflate compression, timeouts, TLS with custom CA / client cert (OTEL_EXPORTER_OTLP_CERTIFICATE,..._CLIENT_KEY,..._CLIENT_CERTIFICATE), and the retry/backoff loop — is covered byurllib.request+ a stdlibssl.SSLContext. The exporter already implements its own retry loop, so little is lost.Pluggable HTTP client — preserved, without
requestsThe original exporter let callers inject a configured
requests.Session(custom auth, proxies, TLS, retry adapters) as its HTTP client, both via thesession=constructor argument and via theOTEL_PYTHON_EXPORTER_OTLP_HTTP*_CREDENTIAL_PROVIDERentry-point env vars. This PR keeps that capability using the stdlib:urllib.request.OpenerDirector— the stdlib structural analog of aSession. Handlers cover the same ground:HTTPSHandler(context=…)(TLS),ProxyHandler(proxies), auth handlers, and a customBaseHandler.https_requesthook for dynamic per-request auth (e.g. refreshing bearer tokens).OTEL_PYTHON_EXPORTER_OTLP_HTTP_CREDENTIAL_PROVIDERand the per-signal…_{TRACES,METRICS,LOGS}_CREDENTIAL_PROVIDERand theopentelemetry_otlp_credential_providergroup are unchanged; the provider now returns anOpenerDirector. (These were previously loaded but never wired into the send path — this PR actually wires them in.)requests.Sessionstill works, deprecated. Passing one (viasession=or a provider) is detected structurally, without importingrequests, routed through its.post()exactly as before, and now emits aDeprecationWarning. Its transport errors are normalized toURLErrorso the retry loop is uniform.OTEL_PYTHON_-prefixed vars are non-spec extensions, so this changes no spec-required behavior; all spec-defined TLS/auth (file-path based) still works.SDK docstrings updated (in this PR): the four HTTP credential-provider env-var docstrings in
opentelemetry-sdknow document theOpenerDirectorcontract (with an example) and therequests.Sessiondeprecation. The gRPC credential-provider docstrings (which returngrpc.ChannelCredentials) are untouched.Implementation: a small client seam in
_common(_resolve_client+_opener_client/_session_client); the three exporters wireself._clientfrom_resolve_client(session, <SIGNAL_ENV>, ssl_context)and send through it. Unit tests cover the default,OpenerDirector, deprecated-session (warns + routes), transport-error, and invalid-return paths.Stacked series (merge in order)
opentelemetry-proto→ pure-Pythonopentelemetry-exporter-otlp-proto-common→ pure-Python backendopentelemetry-exporter-otlp-proto-http→ pure-Python + urllib (this PR)opentelemetry-exporter-otlp-proto-grpc→ pure-Python gRPCDepends on #5503 and #5504; diff is cumulative. Isolated per-package diff:
https://github.com/ocelotl/opentelemetry-python/compare/pure-python-otlp-2-common...pure-python-otlp-3-httpEntry-point names (
otlp_proto_httpfor traces/metrics/logs) are unchanged. CI not expected green while the stack is in flight; see #5503 for full rationale.Stack (merge in order): #5503 (proto) → #5504 (common) → #5505 (http) → #5506 (grpc)