api: conditionally load entrypoints for OTEL_PYTHON_CONTEXT#5144
api: conditionally load entrypoints for OTEL_PYTHON_CONTEXT#5144codeboten wants to merge 25 commits into
Conversation
This prevents unnecessarily importing the entry points library, reducing the memory footprint of loading the API by about a MB (27%): |Scenario | Memory before | Memory after | delta | | - | - | - | - | |Import API only | 5.43 MB | 4.49 MB | -940 KB | |API + get_tracer (no-op) | 5.05 MB | 4.10 MB | -950 KB | Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com>
MikeGoldsmith
left a comment
There was a problem hiding this comment.
Looks good, thanks @codeboten. Please add a changelog entry 👍🏻
Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com>
|
added changelog, ptal |
Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com>
Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com>
codeboten
left a comment
There was a problem hiding this comment.
dont think the check-links failure is related to this change
MikeGoldsmith
left a comment
There was a problem hiding this comment.
Nice, thanks @codeboten 🚀
|
@open-telemetry/python-maintainers is there anything else needed on this pr to move it forward? |
@codeboten There are a large number of PRs in the backlog, so unfortunately it's just a bit of a waiting game. |
|
thanks @herin049, just making sure there isn't something i should be doing here :) |
|
Thanks for the PR! Just a heads-up: we no longer update Please add the appropriate changelog fragment for this change instead of editing |
|
We have a WIP PR that will remove |
Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com>
Is there any harm is accepting this and then updating to the other PR to update the import library if we want to accept it? This PR predates the importlib PR by 3 weeks and been approved for 2 weeks. This is the PR: |
Sorry I'm assuming that moving the import of |
|
I've run some comparisons on top of the changes in the importlib-metadata PR and here's the results:
|
Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com>
|
From public API Check I wonder if anyone in the wild was using these accidentally exposed imports. We could probably do a quick GH search to check if this inadvertently breaks anyone. |
There was a problem hiding this comment.
Pull request overview
This PR reduces the baseline import cost of opentelemetry-api by deferring entry_points usage (and related metadata machinery) until it’s actually needed, especially around context selection via OTEL_PYTHON_CONTEXT.
Changes:
- Lazily import
entry_pointsin provider loading utilities to avoid importing entry point machinery during a plain API import. - Update propagator initialization to avoid
entry_pointswhenOTEL_PROPAGATORSis unset (use direct default propagator classes instead). - Update runtime context initialization to return
ContextVarsRuntimeContextdirectly whenOTEL_PYTHON_CONTEXTis not set, and only consult entry points when it is set.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| opentelemetry-api/src/opentelemetry/util/_providers.py | Moves entry_points import inside _load_provider to avoid import-time overhead unless env-driven provider loading occurs. |
| opentelemetry-api/src/opentelemetry/propagate/init.py | Introduces _load_propagators() and avoids entry point loading for the default propagators when OTEL_PROPAGATORS is unset. |
| opentelemetry-api/src/opentelemetry/context/init.py | Avoids entry_points unless OTEL_PYTHON_CONTEXT is explicitly configured; falls back directly to ContextVarsRuntimeContext. |
| .changelog/5144.changed | Adds a changelog entry for the conditional entry point import behavior change. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # pylint: disable=import-outside-toplevel,no-name-in-module | ||
| from opentelemetry.util._importlib_metadata import ( # noqa: PLC0415 | ||
| entry_points, | ||
| ) | ||
|
|
||
| propagators: list[textmap.TextMapPropagator] = [] | ||
| for propagator in configured.split(","): | ||
| propagator = propagator.strip() | ||
| if propagator.lower() == "none": | ||
| logger.debug( | ||
| "OTEL_PROPAGATORS environment variable contains none, removing all propagators" | ||
| ) | ||
| return composite.CompositePropagator([]) |
| configured_context = os.environ.get(OTEL_PYTHON_CONTEXT) | ||
| if not configured_context: | ||
| return ContextVarsRuntimeContext() | ||
|
|
||
| # FIXME use a better implementation of a configuration manager | ||
| # to avoid having to get configuration values straight from | ||
| # environment variables | ||
| default_context = "contextvars_context" | ||
|
|
||
| configured_context = environ.get(OTEL_PYTHON_CONTEXT, default_context) # type: str | ||
| # pylint: disable=import-outside-toplevel,no-name-in-module | ||
| from opentelemetry.util._importlib_metadata import ( # noqa: PLC0415 | ||
| entry_points, | ||
| ) | ||
|
|
||
| try: | ||
| return next( # type: ignore | ||
| iter( # type: ignore | ||
| entry_points( # type: ignore | ||
| group="opentelemetry_context", | ||
| name=configured_context, | ||
| return next( | ||
| iter( | ||
| entry_points( | ||
| group="opentelemetry_context", name=configured_context | ||
| ) | ||
| ) | ||
| ).load()() |
I'm not opposed to merge this since we have a bunch of approvals already and there's some memory savings. I haven't profiled this myself so I don't know what part of the changes is responsible of the savings and I'm not sure all the delayed imports in this PRs (e.g. the propagators) makes a difference or not. Out of scope for to this PR but if we are going to think about memory optimizations we should probably track something in benchmarks so we can see if there's regressions. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
Agreed no lazy imports. IMO we should just wait for 3.15 since it's been solved in python.
I believe this PR is trying to optimizing the opposite case, where |
Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com>
Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com>
I ended up putting those back, didn't want to break a public api |
|
Thank you @codeboten! I turned on auto merge which should start once the Copilot comments are resolved |
Description
This prevents unnecessarily importing the entry points library, reducing the memory footprint of loading the API by about a MB (27%):
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
Does This PR Require a Contrib Repo Change?
Checklist: