From 0cd26cafebbd06caa4ac838cdb06ef47f80d6c13 Mon Sep 17 00:00:00 2001 From: Robert Duffner Date: Tue, 1 Mar 2022 08:29:15 -0800 Subject: [PATCH] Update pymemcache instrumentation to support pymemcache version >= 1.3.5 --- CHANGELOG.md | 5 ++ instrumentation/README.md | 2 +- .../instrumentation/pymemcache/package.py | 2 +- .../tests/test_pymemcache.py | 50 +++++++++++++------ .../instrumentation/bootstrap_gen.py | 2 +- tox.ini | 12 +++-- 6 files changed, 52 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c62672bf7..a173340ac4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `opentelemetry-instrumentation-kafka-python` Fix topic extraction ([#949](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/949)) +### Changed + +- `opentelemetry-instrumentation-pymemcache` should run against newer versions of pymemcache. + ([#935](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/935)) + ## [1.9.1-0.28b1](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.9.1-0.28b1) - 2022-01-29 ### Fixed diff --git a/instrumentation/README.md b/instrumentation/README.md index 1421653a70..caacdafdf6 100644 --- a/instrumentation/README.md +++ b/instrumentation/README.md @@ -23,7 +23,7 @@ | [opentelemetry-instrumentation-mysql](./opentelemetry-instrumentation-mysql) | mysql-connector-python ~= 8.0 | | [opentelemetry-instrumentation-pika](./opentelemetry-instrumentation-pika) | pika >= 0.12.0 | | [opentelemetry-instrumentation-psycopg2](./opentelemetry-instrumentation-psycopg2) | psycopg2 >= 2.7.3.1 | -| [opentelemetry-instrumentation-pymemcache](./opentelemetry-instrumentation-pymemcache) | pymemcache ~= 1.3 | +| [opentelemetry-instrumentation-pymemcache](./opentelemetry-instrumentation-pymemcache) | pymemcache >= 1.3.5, < 4 | | [opentelemetry-instrumentation-pymongo](./opentelemetry-instrumentation-pymongo) | pymongo >= 3.1, < 5.0 | | [opentelemetry-instrumentation-pymysql](./opentelemetry-instrumentation-pymysql) | PyMySQL < 2 | | [opentelemetry-instrumentation-pyramid](./opentelemetry-instrumentation-pyramid) | pyramid >= 1.7 | diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/package.py b/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/package.py index a2cfd56932..7229a3ba47 100644 --- a/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/package.py +++ b/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/package.py @@ -13,4 +13,4 @@ # limitations under the License. -_instruments = ("pymemcache ~= 1.3",) +_instruments = ("pymemcache >= 1.3.5, < 4",) diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py b/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py index 4756b5189d..b72571331b 100644 --- a/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py +++ b/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py @@ -14,6 +14,8 @@ from unittest import mock import pymemcache +from packaging import version as get_package_version +from pymemcache import __version__ as pymemcache_package_version from pymemcache.exceptions import ( MemcacheClientError, MemcacheIllegalInputError, @@ -33,6 +35,14 @@ TEST_HOST = "localhost" TEST_PORT = 117711 +pymemcache_version = get_package_version.parse(pymemcache_package_version) +pymemcache_version_lt_2 = pymemcache_version < get_package_version.parse( + "2.0.0" +) +pymemcache_version_gt_341 = pymemcache_version > get_package_version.parse( + "3.4.1" +) + class PymemcacheClientTestCase( TestBase @@ -126,11 +136,13 @@ def test_set_multi_success(self): client = self.make_client([b"STORED\r\n"]) # Alias for set_many, a convienance function that calls set for every key result = client.set_multi({b"key": b"value"}, noreply=False) - self.assertTrue(result) - spans = self.memory_exporter.get_finished_spans() - - self.check_spans(spans, 2, ["set key", "set_multi key"]) + if pymemcache_version_lt_2: + self.assertTrue(result) + self.check_spans(spans, 2, ["set key", "set_multi key"]) + else: + assert len(result) == 0 + self.check_spans(spans, 1, ["set_multi key"]) def test_delete_not_found(self): client = self.make_client([b"NOT_FOUND\r\n"]) @@ -191,19 +203,26 @@ def test_delete_many_found(self): spans = self.memory_exporter.get_finished_spans() - self.check_spans( - spans, 3, ["add key", "delete key", "delete_many key"] - ) + if pymemcache_version_lt_2: + self.check_spans( + spans, 3, ["add key", "delete key", "delete_many key"] + ) + else: + self.check_spans(spans, 2, ["add key", "delete_many key"]) def test_set_many_success(self): client = self.make_client([b"STORED\r\n"]) # a convienance function that calls set for every key result = client.set_many({b"key": b"value"}, noreply=False) - self.assertTrue(result) spans = self.memory_exporter.get_finished_spans() - self.check_spans(spans, 2, ["set key", "set_many key"]) + if pymemcache_version_lt_2: + self.assertTrue(result) + self.check_spans(spans, 2, ["set key", "set_many key"]) + else: + assert len(result) == 0 + self.check_spans(spans, 1, ["set_many key"]) def test_set_get(self): client = self.make_client( @@ -243,7 +262,7 @@ def test_prepend_stored(self): def test_cas_stored(self): client = self.make_client([b"STORED\r\n"]) - result = client.cas(b"key", b"value", b"cas", noreply=False) + result = client.cas(b"key", b"value", b"1", noreply=False) self.assertTrue(result) spans = self.memory_exporter.get_finished_spans() @@ -252,7 +271,7 @@ def test_cas_stored(self): def test_cas_exists(self): client = self.make_client([b"EXISTS\r\n"]) - result = client.cas(b"key", b"value", b"cas", noreply=False) + result = client.cas(b"key", b"value", b"1", noreply=False) assert result is False spans = self.memory_exporter.get_finished_spans() @@ -261,7 +280,7 @@ def test_cas_exists(self): def test_cas_not_found(self): client = self.make_client([b"NOT_FOUND\r\n"]) - result = client.cas(b"key", b"value", b"cas", noreply=False) + result = client.cas(b"key", b"value", b"1", noreply=False) assert result is None spans = self.memory_exporter.get_finished_spans() @@ -445,7 +464,11 @@ def test_version_success(self): def test_stats(self): client = self.make_client([b"STAT fake_stats 1\r\n", b"END\r\n"]) result = client.stats() - assert client.sock.send_bufs == [b"stats \r\n"] + + if pymemcache_version_gt_341: + assert client.sock.send_bufs == [b"stats\r\n"] + else: + assert client.sock.send_bufs == [b"stats \r\n"] assert result == {b"fake_stats": 1} spans = self.memory_exporter.get_finished_spans() @@ -544,5 +567,4 @@ def test_delete_many_found(self): self.assertTrue(result) spans = self.memory_exporter.get_finished_spans() - self.check_spans(spans, 2, ["add key", "delete key"]) diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap_gen.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap_gen.py index a159d3bae9..dd0955a2cb 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap_gen.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap_gen.py @@ -93,7 +93,7 @@ "instrumentation": "opentelemetry-instrumentation-psycopg2==0.29b0", }, "pymemcache": { - "library": "pymemcache ~= 1.3", + "library": "pymemcache >= 1.3.5, < 4", "instrumentation": "opentelemetry-instrumentation-pymemcache==0.29b0", }, "pymongo": { diff --git a/tox.ini b/tox.ini index d2e1dd0f04..409414a617 100644 --- a/tox.ini +++ b/tox.ini @@ -111,8 +111,8 @@ envlist = ; ext-psycopg2 intentionally excluded from pypy3 ; opentelemetry-instrumentation-pymemcache - py3{6,7,8,9,10}-test-instrumentation-pymemcache - pypy3-test-instrumentation-pymemcache + py3{6,7,8,9,10}-test-instrumentation-pymemcache{135,200,340,350} + pypy3-test-instrumentation-pymemcache{135,200,300,342} ; opentelemetry-instrumentation-pymongo py3{6,7,8,9,10}-test-instrumentation-pymongo @@ -222,6 +222,10 @@ deps = sqlalchemy14: sqlalchemy~=1.4 pika0: pika>=0.12.0,<1.0.0 pika1: pika>=1.0.0 + pymemcache135: pymemcache ==1.3.5 + pymemcache200: pymemcache >2.0.0,<3.0.0 + pymemcache300: pymemcache >3.0.0,<3.4.2 + pymemcache342: pymemcache ==3.4.2 httpx18: httpx>=0.18.0,<0.19.0 httpx18: respx~=0.17.0 httpx21: httpx>=0.19.0 @@ -262,7 +266,7 @@ changedir = test-instrumentation-mysql: instrumentation/opentelemetry-instrumentation-mysql/tests test-instrumentation-pika{0,1}: instrumentation/opentelemetry-instrumentation-pika/tests test-instrumentation-psycopg2: instrumentation/opentelemetry-instrumentation-psycopg2/tests - test-instrumentation-pymemcache: instrumentation/opentelemetry-instrumentation-pymemcache/tests + test-instrumentation-pymemcache{135,200,300,342}: instrumentation/opentelemetry-instrumentation-pymemcache/tests test-instrumentation-pymongo: instrumentation/opentelemetry-instrumentation-pymongo/tests test-instrumentation-pymysql: instrumentation/opentelemetry-instrumentation-pymysql/tests test-instrumentation-pyramid: instrumentation/opentelemetry-instrumentation-pyramid/tests @@ -332,7 +336,7 @@ commands_pre = mysql: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi {toxinidir}/instrumentation/opentelemetry-instrumentation-mysql[test] - pymemcache: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymemcache[test] + pymemcache{135,200,300,342}: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymemcache[test] pymongo: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymongo[test]