From 6f163cf7e0c615ed6d3dfe3167ab525e9572d9af Mon Sep 17 00:00:00 2001 From: dimitraparaskevopoulou Date: Tue, 13 Apr 2021 11:18:07 +0200 Subject: [PATCH 1/3] Fix: RabbitMQ check proper span type Closes #301 --- .circleci/config.yml | 25 +++++++++++++++++++++++++ instana/span.py | 22 +++++++++++----------- tests/clients/test_asynqp.py | 26 +++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 72a05903..9bd52c8c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -76,6 +76,30 @@ jobs: . venv/bin/activate pytest -v + python37: + docker: + - image: circleci/python:3.7.9 + - image: circleci/postgres:9.6.5-alpine-ram + - image: circleci/mariadb:10-ram + - image: circleci/redis:5.0.4 + - image: rabbitmq:3.5.4 + - image: circleci/mongo:4.2.3-ram + - image: singularities/pubsub-emulator + environment: + PUBSUB_PROJECT_ID: "project-test" + PUBSUB_LISTEN_ADDRESS: "0.0.0.0:8432" + working_directory: ~/repo + steps: + - checkout + - pip-install-deps + - run: + name: run tests + environment: + INSTANA_TEST: "true" + command: | + . venv/bin/activate + pytest -v + python38: docker: - image: circleci/python:3.8.6 @@ -227,6 +251,7 @@ workflows: build: jobs: - python27 + - python37 - python38 - python39 - py27cassandra diff --git a/instana/span.py b/instana/span.py index 657c4123..681f126a 100644 --- a/instana/span.py +++ b/instana/span.py @@ -26,7 +26,7 @@ class InstanaSpan(BasicSpan): stack = None synthetic = False - def mark_as_errored(self, tags = None): + def mark_as_errored(self, tags=None): """ Mark this span as errored. @@ -90,6 +90,7 @@ def log_exception(self, exc): logger.debug("span.log_exception", exc_info=True) raise + class BaseSpan(object): sy = None @@ -149,7 +150,7 @@ def _validate_tag(self, key, value): try: # Tag keys must be some type of text or string type if isinstance(key, (six.text_type, six.string_types)): - validated_key = key[0:1024] # Max key length of 1024 characters + validated_key = key[0:1024] # Max key length of 1024 characters if isinstance(value, (bool, float, int, list, dict, six.text_type, six.string_types)): validated_value = value @@ -169,7 +170,7 @@ def _convert_tag_value(self, value): final_value = repr(value) except Exception: final_value = "(non-fatal) span.set_tag: values must be one of these types: bool, float, int, list, " \ - "set, str or alternatively support 'repr'. tag discarded" + "set, str or alternatively support 'repr'. tag discarded" logger.debug(final_value, exc_info=True) return None return final_value @@ -237,7 +238,7 @@ class RegisteredSpan(BaseSpan): "mongo", "mysql", "postgres", "rabbitmq", "redis", "rpc-client", "sqlalchemy", "soap", "tornado-client", "urllib3", "pymongo", "gcs", "gcps-producer") - ENTRY_SPANS = ("aiohttp-server", "aws.lambda.entry", "celery-worker", "django", "wsgi", "rabbitmq", + ENTRY_SPANS = ("aiohttp-server", "aws.lambda.entry", "celery-worker", "django", "wsgi", "rpc-server", "tornado-server", "gcps-consumer") LOCAL_SPANS = ("render") @@ -247,24 +248,23 @@ def __init__(self, span, source, service_name, **kwargs): super(RegisteredSpan, self).__init__(span, source, service_name, **kwargs) self.n = span.operation_name self.k = 1 - if span.operation_name in self.ENTRY_SPANS: + + if span.operation_name in self.ENTRY_SPANS or ( + span.operation_name == "rabbitmq" and span.tags.get('sort', None) == "consume"): # entry self._populate_entry_span_data(span) self.data["service"] = service_name elif span.operation_name in self.EXIT_SPANS: - self.k = 2 # exit + self.k = 2 # exit self._populate_exit_span_data(span) elif span.operation_name in self.LOCAL_SPANS: - self.k = 3 # intermediate span + self.k = 3 # intermediate span self._populate_local_span_data(span) - if "rabbitmq" in self.data and self.data["rabbitmq"]["sort"] == "consume": - self.k = 1 # entry - # unify the span operation_name for gcps-producer and gcps-consumer if "gcps" in span.operation_name: self.n = 'gcps' - + # Store any leftover tags in the custom section if len(span.tags) > 0: self.data["custom"]["tags"] = self._validate_tags(span.tags) diff --git a/tests/clients/test_asynqp.py b/tests/clients/test_asynqp.py index f8360c6f..8b6fc0f4 100644 --- a/tests/clients/test_asynqp.py +++ b/tests/clients/test_asynqp.py @@ -24,7 +24,8 @@ rabbitmq_host = "localhost" is_unsupported_version = LooseVersion(sys.version) < LooseVersion('3.5.3') \ - or LooseVersion(sys.version) >= LooseVersion('3.8.0') + or LooseVersion(sys.version) >= LooseVersion('3.8.0') + @pytest.mark.skipif(is_unsupported_version, reason="Asynqp supports >=3.5.3;<3.8.0") class TestAsynqp(unittest.TestCase): @@ -96,6 +97,9 @@ def test(): self.assertIsNone(test_span.ec) self.assertIsNone(rabbitmq_span.ec) + # Span type + self.assertEqual(rabbitmq_span.k, 2) # exit + # Rabbitmq self.assertEqual('test.exchange', rabbitmq_span.data["rabbitmq"]["exchange"]) self.assertEqual('publish', rabbitmq_span.data["rabbitmq"]["sort"]) @@ -132,6 +136,9 @@ def test(): self.assertIsNone(test_span.ec) self.assertIsNone(rabbitmq_span.ec) + # Span type + self.assertEqual(rabbitmq_span.k, 2) # exit + # Rabbitmq self.assertEqual('test.exchange', rabbitmq_span.data["rabbitmq"]["exchange"]) self.assertEqual('publish', rabbitmq_span.data["rabbitmq"]["sort"]) @@ -196,6 +203,10 @@ def publish(): self.assertEqual(publish_span.p, test_span.s) self.assertEqual(get_span.p, test_span.s) + # Span type + self.assertEqual(publish_span.k, 2) # exit + self.assertEqual(get_span.k, 1) # entry + # Error logging self.assertIsNone(test_span.ec) self.assertIsNone(publish_span.ec) @@ -250,6 +261,10 @@ def test(): self.assertEqual(publish_span.p, test_span.s) self.assertEqual(consume_span.p, publish_span.s) + # Span type + self.assertEqual(publish_span.k, 2) # exit + self.assertEqual(consume_span.k, 1) # entry + # publish self.assertEqual('test.exchange', publish_span.data["rabbitmq"]["exchange"]) self.assertEqual('publish', publish_span.data["rabbitmq"]["sort"]) @@ -311,6 +326,11 @@ def test(): self.assertEqual(consume1_span.p, publish1_span.s) self.assertEqual(publish2_span.p, consume1_span.s) + # Span type + self.assertEqual(publish1_span.k, 2) # exit + self.assertEqual(consume1_span.k, 1) # entry + self.assertEqual(publish2_span.k, 2) # exit + # publish self.assertEqual('test.exchange', publish1_span.data["rabbitmq"]["exchange"]) self.assertEqual('publish', publish1_span.data["rabbitmq"]["sort"]) @@ -402,6 +422,10 @@ def test(): self.assertEqual(run_later_span.p, consume_span.s) self.assertEqual(wsgi_span.p, aioclient_span.s) + # Span type + self.assertEqual(publish_span.k, 2) # exit + self.assertEqual(consume_span.k, 1) # entry + # publish self.assertEqual('test.exchange', publish_span.data["rabbitmq"]["exchange"]) self.assertEqual('publish', publish_span.data["rabbitmq"]["sort"]) From 3ecfc8399db48ebc7eb6854088d4883da141f698 Mon Sep 17 00:00:00 2001 From: dimitraparaskevopoulou Date: Tue, 13 Apr 2021 13:14:43 +0200 Subject: [PATCH 2/3] review requested changes --- instana/span.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/instana/span.py b/instana/span.py index 681f126a..3f44dc57 100644 --- a/instana/span.py +++ b/instana/span.py @@ -238,7 +238,7 @@ class RegisteredSpan(BaseSpan): "mongo", "mysql", "postgres", "rabbitmq", "redis", "rpc-client", "sqlalchemy", "soap", "tornado-client", "urllib3", "pymongo", "gcs", "gcps-producer") - ENTRY_SPANS = ("aiohttp-server", "aws.lambda.entry", "celery-worker", "django", "wsgi", + ENTRY_SPANS = ("aiohttp-server", "aws.lambda.entry", "celery-worker", "django", "wsgi", "rabbitmq" "rpc-server", "tornado-server", "gcps-consumer") LOCAL_SPANS = ("render") @@ -249,8 +249,7 @@ def __init__(self, span, source, service_name, **kwargs): self.n = span.operation_name self.k = 1 - if span.operation_name in self.ENTRY_SPANS or ( - span.operation_name == "rabbitmq" and span.tags.get('sort', None) == "consume"): + if span.operation_name in self.ENTRY_SPANS: # entry self._populate_entry_span_data(span) self.data["service"] = service_name @@ -261,6 +260,9 @@ def __init__(self, span, source, service_name, **kwargs): self.k = 3 # intermediate span self._populate_local_span_data(span) + if "rabbitmq" in self.data and self.data["rabbitmq"]["sort"] == "publish": + self.k = 2 # exit + # unify the span operation_name for gcps-producer and gcps-consumer if "gcps" in span.operation_name: self.n = 'gcps' From 55fcfa39a0b98983919d8c9a115986ece031890d Mon Sep 17 00:00:00 2001 From: dimitraparaskevopoulou Date: Tue, 13 Apr 2021 13:47:12 +0200 Subject: [PATCH 3/3] add missing comma --- instana/span.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instana/span.py b/instana/span.py index 3f44dc57..50972012 100644 --- a/instana/span.py +++ b/instana/span.py @@ -238,7 +238,7 @@ class RegisteredSpan(BaseSpan): "mongo", "mysql", "postgres", "rabbitmq", "redis", "rpc-client", "sqlalchemy", "soap", "tornado-client", "urllib3", "pymongo", "gcs", "gcps-producer") - ENTRY_SPANS = ("aiohttp-server", "aws.lambda.entry", "celery-worker", "django", "wsgi", "rabbitmq" + ENTRY_SPANS = ("aiohttp-server", "aws.lambda.entry", "celery-worker", "django", "wsgi", "rabbitmq", "rpc-server", "tornado-server", "gcps-consumer") LOCAL_SPANS = ("render")