From 7e19bee89f8be74ffd4fc8ff9babac2a21360b63 Mon Sep 17 00:00:00 2001 From: Varsha GS Date: Thu, 28 Aug 2025 13:15:29 +0530 Subject: [PATCH 1/7] feat: Add GEvent instrumentation support with OTel Signed-off-by: Varsha GS --- src/instana/__init__.py | 3 +-- src/instana/instrumentation/gevent.py | 36 ++++++++------------------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/src/instana/__init__.py b/src/instana/__init__.py index 7add8c29..16c7fcc6 100644 --- a/src/instana/__init__.py +++ b/src/instana/__init__.py @@ -182,6 +182,7 @@ def boot_agent() -> None: sqlalchemy, # noqa: F401 starlette, # noqa: F401 urllib3, # noqa: F401 + gevent, # noqa: F401 ) from instana.instrumentation.aiohttp import ( client as aiohttp_client, # noqa: F401 @@ -209,8 +210,6 @@ def boot_agent() -> None: server as tornado_server, # noqa: F401 ) - # from instana.instrumentation import gevent_inst # noqa: F401 - # Hooks from instana.hooks import ( hook_gunicorn, # noqa: F401 diff --git a/src/instana/instrumentation/gevent.py b/src/instana/instrumentation/gevent.py index c083fb84..41ba057e 100644 --- a/src/instana/instrumentation/gevent.py +++ b/src/instana/instrumentation/gevent.py @@ -6,8 +6,11 @@ """ import sys -from ..log import logger -from ..singletons import tracer + +from opentelemetry import context +import contextvars + +from instana.log import logger def instrument_gevent(): @@ -16,26 +19,15 @@ def instrument_gevent(): logger.debug("Instrumenting gevent") import gevent - from opentracing.scope_managers.gevent import GeventScopeManager - from opentracing.scope_managers.gevent import _GeventScope def spawn_callback(new_greenlet): """Handles context propagation for newly spawning greenlets""" - parent_scope = tracer.scope_manager.active - if parent_scope is not None: - # New greenlet, new clean slate. Clone and make active in this new greenlet - # the currently active scope (but don't finish() the span on close - it's a - # clone/not the original and we don't want to close it prematurely) - # TODO: Change to our own ScopeManagers - parent_scope_clone = _GeventScope( - parent_scope.manager, parent_scope.span, finish_on_close=False - ) - tracer._scope_manager._set_greenlet_scope( - parent_scope_clone, new_greenlet - ) - - logger.debug(" -> Updating tracer to use gevent based context management") - tracer._scope_manager = GeventScopeManager() + parent_context = context.get_current() + new_context = contextvars.Context() + + new_context.run(lambda: context.attach(parent_context)) + new_greenlet.gr_context = new_context + gevent.Greenlet.add_spawn_callback(spawn_callback) except Exception: logger.debug("instrument_gevent: ", exc_info=True) @@ -43,11 +35,5 @@ def spawn_callback(new_greenlet): if "gevent" not in sys.modules: logger.debug("Instrumenting gevent: gevent not detected or loaded. Nothing done.") -elif not hasattr(sys.modules["gevent"], "version_info"): - logger.debug("gevent module has no 'version_info'. Skipping instrumentation.") -elif sys.modules["gevent"].version_info < (1, 4): - logger.debug( - "gevent < 1.4 detected. The Instana package supports gevent versions 1.4 and greater." - ) else: instrument_gevent() From d100784e383c66b45f6701256bb6ce2f2ade4f41 Mon Sep 17 00:00:00 2001 From: Varsha GS Date: Thu, 28 Aug 2025 13:16:46 +0530 Subject: [PATCH 2/7] tests: Adapt GEvent tests to OTel spec Signed-off-by: Varsha GS --- tests/frameworks/test_gevent.py | 125 ++++++++++++++++---------------- tests/helpers.py | 2 +- 2 files changed, 62 insertions(+), 65 deletions(-) diff --git a/tests/frameworks/test_gevent.py b/tests/frameworks/test_gevent.py index 69a9a6c8..1dee37b2 100644 --- a/tests/frameworks/test_gevent.py +++ b/tests/frameworks/test_gevent.py @@ -2,36 +2,41 @@ # (c) Copyright Instana Inc. 2020 import os -import unittest +import pytest +import urllib3 import gevent from gevent.pool import Group -import urllib3 -from opentracing.scope_managers.gevent import GeventScopeManager +from typing import Generator import tests.apps.flask_app -from instana.span import SDKSpan from instana.singletons import tracer -from ..helpers import testenv, get_spans_by_filter +from tests.helpers import testenv, get_spans_by_filter, filter_test_span -@unittest.skipIf(not os.environ.get("GEVENT_STARLETTE_TEST"), reason="") -class TestGEvent(unittest.TestCase): - def setUp(self): - self.http = urllib3.HTTPConnectionPool('127.0.0.1', port=testenv["flask_port"], maxsize=20) - self.recorder = tracer.recorder - self.recorder.clear_spans() - tracer._scope_manager = GeventScopeManager() +# Skip the tests if the environment variable `GEVENT_STARLETTE_TEST` is not set +pytestmark = pytest.mark.skipif(not os.environ.get("GEVENT_STARLETTE_TEST"), reason="GEVENT_STARLETTE_TEST not set") + - def tearDown(self): - """ Do nothing for now """ - pass +class TestGEvent: + @classmethod + def setup_class(cls) -> None: + """Setup that runs once before all tests in the class""" + cls.http = urllib3.HTTPConnectionPool('127.0.0.1', port=testenv["flask_port"], maxsize=20) + cls.recorder = tracer.span_processor + + @pytest.fixture(autouse=True) + def setUp(self) -> Generator[None, None, None]: + """Clear all spans before each test run""" + self.recorder.clear_spans() def make_http_call(self, n=None): + """Helper function to make HTTP calls""" return self.http.request('GET', testenv["flask_server"] + '/') def spawn_calls(self): - with tracer.start_active_span('spawn_calls'): + """Helper function to spawn multiple HTTP calls""" + with tracer.start_as_current_span('spawn_calls'): jobs = [] jobs.append(gevent.spawn(self.make_http_call)) jobs.append(gevent.spawn(self.make_http_call)) @@ -39,86 +44,78 @@ def spawn_calls(self): gevent.joinall(jobs, timeout=2) def spawn_imap_unordered(self): + """Helper function to test imap_unordered""" igroup = Group() result = [] - with tracer.start_active_span('test'): + with tracer.start_as_current_span('test'): for i in igroup.imap_unordered(self.make_http_call, range(3)): result.append(i) def launch_gevent_chain(self): - with tracer.start_active_span('test'): + """Helper function to launch a chain of gevent calls""" + with tracer.start_as_current_span('test'): gevent.spawn(self.spawn_calls).join() def test_spawning(self): gevent.spawn(self.launch_gevent_chain) - gevent.sleep(2) - + spans = self.recorder.queued_spans() - - self.assertEqual(8, len(spans)) - - span_filter = lambda span: span.n == "sdk" \ - and span.data['sdk']['name'] == 'test' and span.p == None - test_spans = get_spans_by_filter(spans, span_filter) - self.assertIsNotNone(test_spans) - self.assertEqual(len(test_spans), 1) - + + assert len(spans) == 8 + + test_spans = get_spans_by_filter(spans, filter_test_span) + assert test_spans + assert len(test_spans) == 1 + test_span = test_spans[0] - self.assertTrue(type(test_spans[0]) is SDKSpan) - + span_filter = lambda span: span.n == "sdk" \ - and span.data['sdk']['name'] == 'spawn_calls' and span.p == test_span.s + and span.data['sdk']['name'] == 'spawn_calls' and span.p == test_span.s spawn_spans = get_spans_by_filter(spans, span_filter) - self.assertIsNotNone(spawn_spans) - self.assertEqual(len(spawn_spans), 1) - + assert spawn_spans + assert len(spawn_spans) == 1 + spawn_span = spawn_spans[0] - self.assertTrue(type(spawn_spans[0]) is SDKSpan) - + span_filter = lambda span: span.n == "urllib3" urllib3_spans = get_spans_by_filter(spans, span_filter) - + for urllib3_span in urllib3_spans: # spans should all have the same test span parent - self.assertEqual(urllib3_span.t, spawn_span.t) - self.assertEqual(urllib3_span.p, spawn_span.s) - + assert urllib3_span.t == spawn_span.t + assert urllib3_span.p == spawn_span.s + # find the wsgi span generated from this urllib3 request span_filter = lambda span: span.n == "wsgi" and span.p == urllib3_span.s wsgi_spans = get_spans_by_filter(spans, span_filter) - self.assertIsNotNone(wsgi_spans) - self.assertEqual(len(wsgi_spans), 1) + assert wsgi_spans is not None + assert len(wsgi_spans) == 1 def test_imap_unordered(self): - gevent.spawn(self.spawn_imap_unordered()) - + gevent.spawn(self.spawn_imap_unordered) gevent.sleep(2) - + spans = self.recorder.queued_spans() - self.assertEqual(7, len(spans)) - - span_filter = lambda span: span.n == "sdk" \ - and span.data['sdk']['name'] == 'test' and span.p == None - test_spans = get_spans_by_filter(spans, span_filter) - self.assertIsNotNone(test_spans) - self.assertEqual(len(test_spans), 1) - + assert len(spans) == 7 + + test_spans = get_spans_by_filter(spans, filter_test_span) + assert test_spans is not None + assert len(test_spans) == 1 + test_span = test_spans[0] - self.assertTrue(type(test_spans[0]) is SDKSpan) - + span_filter = lambda span: span.n == "urllib3" urllib3_spans = get_spans_by_filter(spans, span_filter) - self.assertEqual(len(urllib3_spans), 3) - + assert len(urllib3_spans) == 3 + for urllib3_span in urllib3_spans: # spans should all have the same test span parent - self.assertEqual(urllib3_span.t, test_span.t) - self.assertEqual(urllib3_span.p, test_span.s) - + assert urllib3_span.t == test_span.t + assert urllib3_span.p == test_span.s + # find the wsgi span generated from this urllib3 request span_filter = lambda span: span.n == "wsgi" and span.p == urllib3_span.s wsgi_spans = get_spans_by_filter(spans, span_filter) - self.assertIsNotNone(wsgi_spans) - self.assertEqual(len(wsgi_spans), 1) - + assert wsgi_spans is not None + assert len(wsgi_spans) == 1 diff --git a/tests/helpers.py b/tests/helpers.py index 850ba59b..f7c2efc4 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -108,7 +108,7 @@ def fail_with_message_and_span_dump(msg, spans): pytest.fail(msg + span_dump, True) -def is_test_span(span): +def filter_test_span(span): """ return the filter for test span """ From 45000ea8d25dea75ce13a99204d8957fae230112 Mon Sep 17 00:00:00 2001 From: Varsha GS Date: Fri, 29 Aug 2025 12:14:27 +0530 Subject: [PATCH 3/7] ci: Run gevent tests after support Signed-off-by: Varsha GS --- .circleci/config.yml | 6 ++---- tests/conftest.py | 1 - tests/frameworks/test_sanic.py | 22 +++++++++++----------- tests/requirements-gevent-starlette.txt | 2 +- tests/requirements-pre314.txt | 2 +- tests/requirements.txt | 2 +- 6 files changed, 16 insertions(+), 19 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 57495e70..4f4403a8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -219,10 +219,8 @@ jobs: - pip-install-tests-deps: requirements: "tests/requirements-gevent-starlette.txt" - run-tests-with-coverage-report: - # TODO: uncomment once gevent instrumentation is done - # gevent: "true" - # tests: "tests/frameworks/test_gevent.py tests/frameworks/test_starlette.py" - tests: "tests/frameworks/test_starlette.py" + gevent: "true" + tests: "tests/frameworks/test_gevent.py tests/frameworks/test_starlette.py" - store-pytest-results - store-coverage-report diff --git a/tests/conftest.py b/tests/conftest.py index 93f89221..651c3995 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -26,7 +26,6 @@ from instana.util.runtime import is_ppc64, is_s390x collect_ignore_glob = [ - "*test_gevent*", "*collector/test_gcr*", "*agent/test_google*", ] diff --git a/tests/frameworks/test_sanic.py b/tests/frameworks/test_sanic.py index 31b98a49..7aa08e21 100644 --- a/tests/frameworks/test_sanic.py +++ b/tests/frameworks/test_sanic.py @@ -7,7 +7,7 @@ from instana.singletons import tracer, agent from instana.util.ids import hex_id -from tests.helpers import get_first_span_by_filter, get_first_span_by_name, is_test_span +from tests.helpers import get_first_span_by_filter, get_first_span_by_name, filter_test_span from tests.test_utils import _TraceContextMixin from tests.apps.sanic_app.server import app @@ -57,7 +57,7 @@ def test_basic_get(self) -> None: spans = self.recorder.queued_spans() assert len(spans) == 3 - test_span = get_first_span_by_filter(spans, is_test_span) + test_span = get_first_span_by_filter(spans, filter_test_span) assert test_span httpx_span = get_first_span_by_name(spans, "http") @@ -108,7 +108,7 @@ def test_404(self) -> None: spans = self.recorder.queued_spans() assert len(spans) == 3 - test_span = get_first_span_by_filter(spans, is_test_span) + test_span = get_first_span_by_filter(spans, filter_test_span) assert test_span httpx_span = get_first_span_by_name(spans, "http") @@ -159,7 +159,7 @@ def test_sanic_exception(self) -> None: spans = self.recorder.queued_spans() assert len(spans) == 4 - test_span = get_first_span_by_filter(spans, is_test_span) + test_span = get_first_span_by_filter(spans, filter_test_span) assert test_span httpx_span = get_first_span_by_name(spans, "http") @@ -210,7 +210,7 @@ def test_500_instana_exception(self) -> None: spans = self.recorder.queued_spans() assert len(spans) == 4 - test_span = get_first_span_by_filter(spans, is_test_span) + test_span = get_first_span_by_filter(spans, filter_test_span) assert test_span httpx_span = get_first_span_by_name(spans, "http") @@ -261,7 +261,7 @@ def test_500(self) -> None: spans = self.recorder.queued_spans() assert len(spans) == 4 - test_span = get_first_span_by_filter(spans, is_test_span) + test_span = get_first_span_by_filter(spans, filter_test_span) assert test_span httpx_span = get_first_span_by_name(spans, "http") @@ -312,7 +312,7 @@ def test_path_templates(self) -> None: spans = self.recorder.queued_spans() assert len(spans) == 3 - test_span = get_first_span_by_filter(spans, is_test_span) + test_span = get_first_span_by_filter(spans, filter_test_span) assert test_span httpx_span = get_first_span_by_name(spans, "http") @@ -363,7 +363,7 @@ def test_secret_scrubbing(self) -> None: spans = self.recorder.queued_spans() assert len(spans) == 3 - test_span = get_first_span_by_filter(spans, is_test_span) + test_span = get_first_span_by_filter(spans, filter_test_span) assert test_span httpx_span = get_first_span_by_name(spans, "http") @@ -417,7 +417,7 @@ def test_synthetic_request(self) -> None: spans = self.recorder.queued_spans() assert len(spans) == 3 - test_span = get_first_span_by_filter(spans, is_test_span) + test_span = get_first_span_by_filter(spans, filter_test_span) assert test_span httpx_span = get_first_span_by_name(spans, "http") @@ -476,7 +476,7 @@ def test_request_header_capture(self) -> None: spans = self.recorder.queued_spans() assert len(spans) == 3 - test_span = get_first_span_by_filter(spans, is_test_span) + test_span = get_first_span_by_filter(spans, filter_test_span) assert test_span httpx_span = get_first_span_by_name(spans, "http") @@ -523,7 +523,7 @@ def test_response_header_capture(self) -> None: spans = self.recorder.queued_spans() assert len(spans) == 3 - test_span = get_first_span_by_filter(spans, is_test_span) + test_span = get_first_span_by_filter(spans, filter_test_span) assert test_span httpx_span = get_first_span_by_name(spans, "http") diff --git a/tests/requirements-gevent-starlette.txt b/tests/requirements-gevent-starlette.txt index 86da4f49..17465bd6 100644 --- a/tests/requirements-gevent-starlette.txt +++ b/tests/requirements-gevent-starlette.txt @@ -1,6 +1,6 @@ -r requirements-minimal.txt flask>=0.12.2 -gevent>=1.4.0 +gevent>=23.9.0.post1 mock>=2.0.0 pyramid>=2.0.1 starlette>=0.12.13 diff --git a/tests/requirements-pre314.txt b/tests/requirements-pre314.txt index 0a025d53..2ad1e026 100644 --- a/tests/requirements-pre314.txt +++ b/tests/requirements-pre314.txt @@ -12,7 +12,7 @@ Django>=4.2.16 # fastapi>=0.115.0; python_version >= "3.13" flask>=2.3.2 # gevent is taking more than 20min to build on 3.14 -# gevent>=1.4.0 +# gevent>=23.9.0.post1 grpcio>=1.14.1 google-cloud-pubsub>=2.0.0 google-cloud-storage>=1.24.0 diff --git a/tests/requirements.txt b/tests/requirements.txt index 48afb6a9..b8a40793 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -10,7 +10,7 @@ Django>=4.2.16 fastapi>=0.92.0; python_version < "3.13" fastapi>=0.115.0; python_version >= "3.13" flask>=2.3.2 -gevent>=1.4.0 +gevent>=23.9.0.post1 grpcio>=1.14.1 google-cloud-pubsub>=2.0.0 google-cloud-storage>=1.24.0 From d1ae747b7f6c2372eb9e4c0e7c0f0b59c9fece79 Mon Sep 17 00:00:00 2001 From: Varsha GS Date: Fri, 29 Aug 2025 12:35:52 +0530 Subject: [PATCH 4/7] fix: Corrected bug where .replace() was treated as an in-place method Signed-off-by: Varsha GS --- .circleci/config.yml | 2 +- src/instana/__init__.py | 2 +- tests/conftest.py | 3 ++- tests/frameworks/test_starlette.py | 1 - 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4f4403a8..b8e18097 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -220,7 +220,7 @@ jobs: requirements: "tests/requirements-gevent-starlette.txt" - run-tests-with-coverage-report: gevent: "true" - tests: "tests/frameworks/test_gevent.py tests/frameworks/test_starlette.py" + tests: "tests/frameworks/test_starlette.py tests/frameworks/test_gevent.py" - store-pytest-results - store-coverage-report diff --git a/src/instana/__init__.py b/src/instana/__init__.py index 16c7fcc6..f9511537 100644 --- a/src/instana/__init__.py +++ b/src/instana/__init__.py @@ -83,7 +83,7 @@ def key_to_bool(k: str) -> bool: import inspect all_accepted_patch_all_args = inspect.getfullargspec(monkey.patch_all)[0] - provided_options.replace(" ", "").replace("--", "").split(",") + provided_options = provided_options.replace(" ", "").replace("--", "").split(",") provided_options = [ k for k in provided_options if short_key(k) in all_accepted_patch_all_args diff --git a/tests/conftest.py b/tests/conftest.py index 651c3995..7c17023a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -28,6 +28,7 @@ collect_ignore_glob = [ "*collector/test_gcr*", "*agent/test_google*", + "*test_gevent_autotrace*" ] # ppc64le and s390x have limitations with some supported libraries. @@ -53,7 +54,7 @@ if not os.environ.get("GEVENT_STARLETTE_TEST"): collect_ignore_glob.extend( [ - "*test_gevent*", + "*test_gevent.py", "*test_starlette*", ] ) diff --git a/tests/frameworks/test_starlette.py b/tests/frameworks/test_starlette.py index e332e024..d44f39d8 100644 --- a/tests/frameworks/test_starlette.py +++ b/tests/frameworks/test_starlette.py @@ -29,7 +29,6 @@ def _resource(self) -> Generator[None, None, None]: # Clear all spans before a test run. self.recorder = tracer.span_processor self.recorder.clear_spans() - yield def test_vanilla_get(self) -> None: result = self.client.get("/") From f0f7a1815568d2671dbd7809b4743be0c435dcc2 Mon Sep 17 00:00:00 2001 From: Varsha GS Date: Fri, 29 Aug 2025 12:50:11 +0530 Subject: [PATCH 5/7] ci: separate jobs for gevent and starlette Signed-off-by: Varsha GS --- .circleci/config.yml | 25 +++++++++++++++++++++---- tests/conftest.py | 1 - 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b8e18097..329755f5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -208,7 +208,22 @@ jobs: - store-pytest-results - store-coverage-report - py39gevent_starlette: + py39starlette: + docker: + - image: public.ecr.aws/docker/library/python:3.9 + working_directory: ~/repo + steps: + - checkout + - check-if-tests-needed + - pip-install-deps + - pip-install-tests-deps: + requirements: "tests/requirements-gevent-starlette.txt" + - run-tests-with-coverage-report: + tests: "tests/frameworks/test_starlette.py" + - store-pytest-results + - store-coverage-report + + py39gevent: docker: - image: public.ecr.aws/docker/library/python:3.9 working_directory: ~/repo @@ -220,7 +235,7 @@ jobs: requirements: "tests/requirements-gevent-starlette.txt" - run-tests-with-coverage-report: gevent: "true" - tests: "tests/frameworks/test_starlette.py tests/frameworks/test_gevent.py" + tests: "tests/frameworks/test_gevent.py" - store-pytest-results - store-coverage-report @@ -305,7 +320,8 @@ workflows: py-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] - python314 - py39cassandra - - py39gevent_starlette + - py39gevent + - py39starlette - py312aws - py312kafka - autowrapt: @@ -318,7 +334,8 @@ workflows: # Uncomment the following when giving real support to 3.14 # - python314 - py39cassandra - - py39gevent_starlette + - py39gevent + - py39starlette - py312aws - py312kafka - autowrapt diff --git a/tests/conftest.py b/tests/conftest.py index 7c17023a..9e2df527 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -55,7 +55,6 @@ collect_ignore_glob.extend( [ "*test_gevent.py", - "*test_starlette*", ] ) From f2779449d0e7099854995ed8c81d3bfa7cfcc24c Mon Sep 17 00:00:00 2001 From: Varsha GS Date: Fri, 29 Aug 2025 13:17:55 +0530 Subject: [PATCH 6/7] tests: Modify gevent_autotrace Signed-off-by: Varsha GS --- tests/conftest.py | 3 +- tests/frameworks/test_gevent_autotrace.py | 45 ++++++++++++----------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 9e2df527..142c1d5f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -28,7 +28,6 @@ collect_ignore_glob = [ "*collector/test_gcr*", "*agent/test_google*", - "*test_gevent_autotrace*" ] # ppc64le and s390x have limitations with some supported libraries. @@ -54,7 +53,7 @@ if not os.environ.get("GEVENT_STARLETTE_TEST"): collect_ignore_glob.extend( [ - "*test_gevent.py", + "*test_gevent*", ] ) diff --git a/tests/frameworks/test_gevent_autotrace.py b/tests/frameworks/test_gevent_autotrace.py index 41bf5f03..7a7a2b8b 100644 --- a/tests/frameworks/test_gevent_autotrace.py +++ b/tests/frameworks/test_gevent_autotrace.py @@ -3,27 +3,31 @@ import importlib import os -import unittest -import socket +import pytest import gevent from gevent import monkey from instana import apply_gevent_monkey_patch +# Teardown not working as expected, run each testcase separately +class TestGEventAutoTrace: -class TestGEventAutoTrace(unittest.TestCase): - def setUp(self): + @pytest.fixture(autouse=True) + def setup_environment(self): + """Setup test environment before each test""" # Ensure that the test suite is operational even when Django is installed # but not running or configured os.environ['DJANGO_SETTINGS_MODULE'] = '' - + self.default_patched_modules = ('socket', 'time', 'select', 'os', 'threading', 'ssl', 'subprocess', 'signal', 'queue',) - - def tearDown(self): + + yield + + # Teardown if os.environ.get('INSTANA_GEVENT_MONKEY_OPTIONS'): os.environ.pop('INSTANA_GEVENT_MONKEY_OPTIONS') - + # Clean up after gevent monkey patches, by restore from the saved dict for modname in monkey.saved.keys(): try: @@ -35,37 +39,34 @@ def tearDown(self): pass monkey.saved = {} - def test_default_patch_all(self): apply_gevent_monkey_patch() for module_name in self.default_patched_modules: - self.assertTrue(monkey.is_module_patched(module_name), - f"{module_name} is not patched") + assert monkey.is_module_patched(module_name), f"{module_name} is not patched" def test_instana_monkey_options_only_time(self): os.environ['INSTANA_GEVENT_MONKEY_OPTIONS'] = ( 'time,no-socket,no-select,no-os,no-select,no-threading,no-os,' 'no-ssl,no-subprocess,''no-signal,no-queue') apply_gevent_monkey_patch() - - self.assertTrue(monkey.is_module_patched('time'), "time module is not patched") + + assert monkey.is_module_patched('time'), "time module is not patched" not_patched_modules = (m for m in self.default_patched_modules if m not in ('time', 'threading')) - + for module_name in not_patched_modules: - self.assertFalse(monkey.is_module_patched(module_name), - f"{module_name} is patched, when it shouldn't be") - + assert not monkey.is_module_patched(module_name), \ + f"{module_name} is patched, when it shouldn't be" def test_instana_monkey_options_only_socket(self): os.environ['INSTANA_GEVENT_MONKEY_OPTIONS'] = ( '--socket, --no-time, --no-select, --no-os, --no-queue, --no-threading,' '--no-os, --no-ssl, no-subprocess, --no-signal, --no-select,') apply_gevent_monkey_patch() - - self.assertTrue(monkey.is_module_patched('socket'), "socket module is not patched") + + assert monkey.is_module_patched('socket'), "socket module is not patched" not_patched_modules = (m for m in self.default_patched_modules if m not in ('socket', 'threading')) - + for module_name in not_patched_modules: - self.assertFalse(monkey.is_module_patched(module_name), - f"{module_name} is patched, when it shouldn't be") + assert not monkey.is_module_patched(module_name), \ + f"{module_name} is patched, when it shouldn't be" From 40d19c045404269fa72a34e910d7ed86b6d3f37b Mon Sep 17 00:00:00 2001 From: Varsha GS Date: Fri, 29 Aug 2025 13:57:35 +0530 Subject: [PATCH 7/7] chore: rename `GEVENT_STARLETTE_TEST` - remove `py39starlette` job - remove `gevent` from `tests/requirements` file Signed-off-by: Varsha GS --- .circleci/config.yml | 19 +------------------ tests/__init__.py | 2 +- tests/apps/aiohttp_app/__init__.py | 2 +- tests/apps/aiohttp_app2/__init__.py | 2 +- tests/apps/grpc_server/__init__.py | 2 +- tests/apps/tornado_server/__init__.py | 2 +- tests/conftest.py | 2 +- tests/frameworks/test_gevent.py | 4 ++-- tests/requirements.txt | 1 - 9 files changed, 9 insertions(+), 27 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 329755f5..e6711151 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -66,7 +66,7 @@ commands: name: Run Tests With Coverage Report environment: CASSANDRA_TEST: "<>" - GEVENT_STARLETTE_TEST: "<>" + GEVENT_TEST: "<>" KAFKA_TEST: "<>" command: | . venv/bin/activate @@ -208,21 +208,6 @@ jobs: - store-pytest-results - store-coverage-report - py39starlette: - docker: - - image: public.ecr.aws/docker/library/python:3.9 - working_directory: ~/repo - steps: - - checkout - - check-if-tests-needed - - pip-install-deps - - pip-install-tests-deps: - requirements: "tests/requirements-gevent-starlette.txt" - - run-tests-with-coverage-report: - tests: "tests/frameworks/test_starlette.py" - - store-pytest-results - - store-coverage-report - py39gevent: docker: - image: public.ecr.aws/docker/library/python:3.9 @@ -321,7 +306,6 @@ workflows: - python314 - py39cassandra - py39gevent - - py39starlette - py312aws - py312kafka - autowrapt: @@ -335,7 +319,6 @@ workflows: # - python314 - py39cassandra - py39gevent - - py39starlette - py312aws - py312kafka - autowrapt diff --git a/tests/__init__.py b/tests/__init__.py index 39799ddb..a38754a7 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -3,7 +3,7 @@ import os -if os.environ.get('GEVENT_STARLETTE_TEST'): +if os.environ.get('GEVENT_TEST'): from gevent import monkey monkey.patch_all() diff --git a/tests/apps/aiohttp_app/__init__.py b/tests/apps/aiohttp_app/__init__.py index 7429a949..b9cf68a2 100644 --- a/tests/apps/aiohttp_app/__init__.py +++ b/tests/apps/aiohttp_app/__init__.py @@ -8,7 +8,7 @@ APP_THREAD = None -if not any((os.environ.get('GEVENT_STARLETTE_TEST'), +if not any((os.environ.get('GEVENT_TEST'), os.environ.get('CASSANDRA_TEST'), sys.version_info < (3, 5, 3))): APP_THREAD = launch_background_thread(server, "AIOHTTP") diff --git a/tests/apps/aiohttp_app2/__init__.py b/tests/apps/aiohttp_app2/__init__.py index e382343a..96ce3f82 100644 --- a/tests/apps/aiohttp_app2/__init__.py +++ b/tests/apps/aiohttp_app2/__init__.py @@ -7,7 +7,7 @@ APP_THREAD = None -if not any((os.environ.get('GEVENT_STARLETTE_TEST'), +if not any((os.environ.get('GEVENT_TEST'), os.environ.get('CASSANDRA_TEST'), sys.version_info < (3, 5, 3))): APP_THREAD = launch_background_thread(server, "AIOHTTP") diff --git a/tests/apps/grpc_server/__init__.py b/tests/apps/grpc_server/__init__.py index 5a222deb..78439e5e 100644 --- a/tests/apps/grpc_server/__init__.py +++ b/tests/apps/grpc_server/__init__.py @@ -6,7 +6,7 @@ import time import threading -if not any((os.environ.get('GEVENT_STARLETTE_TEST'), +if not any((os.environ.get('GEVENT_TEST'), os.environ.get('CASSANDRA_TEST'), sys.version_info < (3, 5, 3))): # Background RPC application diff --git a/tests/apps/tornado_server/__init__.py b/tests/apps/tornado_server/__init__.py index 20a27361..7b0d6c76 100644 --- a/tests/apps/tornado_server/__init__.py +++ b/tests/apps/tornado_server/__init__.py @@ -8,7 +8,7 @@ app_thread = None -if not any((app_thread, os.environ.get('GEVENT_STARLETTE_TEST'), os.environ.get('CASSANDRA_TEST'))): +if not any((app_thread, os.environ.get('GEVENT_TEST'), os.environ.get('CASSANDRA_TEST'))): testenv["tornado_port"] = 10813 testenv["tornado_server"] = ("http://127.0.0.1:" + str(testenv["tornado_port"])) diff --git a/tests/conftest.py b/tests/conftest.py index 142c1d5f..44088c85 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -50,7 +50,7 @@ if not os.environ.get("COUCHBASE_TEST"): collect_ignore_glob.append("*test_couchbase*") -if not os.environ.get("GEVENT_STARLETTE_TEST"): +if not os.environ.get("GEVENT_TEST"): collect_ignore_glob.extend( [ "*test_gevent*", diff --git a/tests/frameworks/test_gevent.py b/tests/frameworks/test_gevent.py index 1dee37b2..31847024 100644 --- a/tests/frameworks/test_gevent.py +++ b/tests/frameworks/test_gevent.py @@ -14,8 +14,8 @@ from tests.helpers import testenv, get_spans_by_filter, filter_test_span -# Skip the tests if the environment variable `GEVENT_STARLETTE_TEST` is not set -pytestmark = pytest.mark.skipif(not os.environ.get("GEVENT_STARLETTE_TEST"), reason="GEVENT_STARLETTE_TEST not set") +# Skip the tests if the environment variable `GEVENT_TEST` is not set +pytestmark = pytest.mark.skipif(not os.environ.get("GEVENT_TEST"), reason="GEVENT_TEST not set") class TestGEvent: diff --git a/tests/requirements.txt b/tests/requirements.txt index b8a40793..6e8fc6ca 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -10,7 +10,6 @@ Django>=4.2.16 fastapi>=0.92.0; python_version < "3.13" fastapi>=0.115.0; python_version >= "3.13" flask>=2.3.2 -gevent>=23.9.0.post1 grpcio>=1.14.1 google-cloud-pubsub>=2.0.0 google-cloud-storage>=1.24.0