Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#3666](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3666))
- `opentelemetry-sdk-extension-aws` Add AWS X-Ray Remote Sampler with initial Rules Poller implementation
([#3366](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3366))
- `opentelemetry-instrumentation`: add support for `OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH` to inform opentelemetry-instrument about gevent monkeypatching
([#3699](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3699))

## Version 1.36.0/0.57b0 (2025-07-29)

Expand Down
8 changes: 7 additions & 1 deletion opentelemetry-instrumentation/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,13 @@ check `here <https://opentelemetry-python.readthedocs.io/en/stable/index.html#in
* ``OTEL_PYTHON_DISABLED_INSTRUMENTATIONS``

If set by the user, opentelemetry-instrument will read this environment variable to disable specific instrumentations.
e.g OTEL_PYTHON_DISABLED_INSTRUMENTATIONS = "requests,django"
e.g OTEL_PYTHON_DISABLED_INSTRUMENTATIONS="requests,django"

* ``OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH``

If set by the user to `patch_all` , opentelemetry instrument will call the gevent monkeypatching method ``patch_all``.
This is considered experimental but can be useful to instrument gevent applications.
e.g OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH=patch_all


Examples
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations

from argparse import REMAINDER, ArgumentParser
from logging import getLogger
from os import environ, execl, getcwd
Expand All @@ -24,6 +26,9 @@
_load_distro,
_load_instrumentors,
)
from opentelemetry.instrumentation.environment_variables import (
OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH,
)
from opentelemetry.instrumentation.utils import _python_path_without_directory
from opentelemetry.instrumentation.version import __version__
from opentelemetry.util._importlib_metadata import entry_points
Expand Down Expand Up @@ -130,6 +135,30 @@ def initialize(*, swallow_exceptions: bool = True) -> None:
environ["PYTHONPATH"], dirname(abspath(__file__)), pathsep
)

# handle optional gevent monkey patching. This is done via environment variables so it may be used from the
# opentelemetry operator
gevent_patch: str | None = environ.get(
OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH
)
if gevent_patch is not None:
if gevent_patch != "patch_all":
_logger.error(
"%s value must be `patch_all`",
OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH,
)
else:
try:
# pylint: disable=import-outside-toplevel
from gevent import monkey

getattr(monkey, gevent_patch)()
except ImportError:
_logger.exception(
"Failed to monkey patch with gevent because gevent is not available"
)
if not swallow_exceptions:
raise

try:
distro = _load_distro()
distro.configure()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,10 @@
"""
.. envvar:: OTEL_PYTHON_CONFIGURATOR
"""

OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH = (
"OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH"
)
"""
.. envvar:: OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH
"""
1 change: 1 addition & 0 deletions opentelemetry-instrumentation/test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
asgiref==3.8.1
Deprecated==1.2.14
gevent==25.5.1
iniconfig==2.0.0
packaging==24.0
pluggy==1.5.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,30 @@ def test_reraises_exceptions(self, load_distro_mock, logger_mock):
)

self.assertEqual("inner exception", str(em.exception))

@patch.dict(
"os.environ",
{
"OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH": "patch_foo"
},
)
@patch("opentelemetry.instrumentation.auto_instrumentation._logger")
def test_handles_invalid_gevent_monkeypatch(self, logger_mock):
# pylint:disable=no-self-use
auto_instrumentation.initialize()
logger_mock.error.assert_called_once_with(
"%s value must be `patch_all`",
"OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH",
)

@patch.dict(
"os.environ",
{
"OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH": "patch_all"
},
)
@patch("opentelemetry.instrumentation.auto_instrumentation._logger")
def test_handles_patch_all_gevent_monkeypatch(self, logger_mock):
# pylint:disable=no-self-use
auto_instrumentation.initialize()
logger_mock.error.assert_not_called()