Repository: mercadona/rele
Pull request #247 (2023-04-28 16:20:54)

Use custom encoder in logging middleware
### :tophat: What?

Use custom encoder in logging middleware

### :thinking: Why?

Log fails when non-serializable elements present in payload


Patch:
diff --git a/rele/contrib/logging_middleware.py b/rele/contrib/logging_middleware.py
index a2c881a..dccc539 100644
--- a/rele/contrib/logging_middleware.py
+++ b/rele/contrib/logging_middleware.py
@@ -17,6 +17,7 @@ class LoggingMiddleware(BaseMiddleware):
     def setup(self, config, **kwargs):
         self._logger = logging.getLogger(__name__)
         self._app_name = config.app_name
+        self._encoder = config.encoder
 
     def _build_data_metrics(
         self, subscription, message, status, start_processing_time=None
@@ -71,7 +72,7 @@ class LoggingMiddleware(BaseMiddleware):
                     "name": "publications",
                     "data": {"agent": self._app_name, "topic": topic},
                 },
-                "subscription_message": json.dumps(message),
+                "subscription_message": json.dumps(message, cls=self._encoder),
             },
         )
 


Test patch:
diff --git a/tests/contrib/test_logging_middleware.py b/tests/contrib/test_logging_middleware.py
index 8774d9b..b51362e 100644
--- a/tests/contrib/test_logging_middleware.py
+++ b/tests/contrib/test_logging_middleware.py
@@ -1,9 +1,11 @@
 import queue
+from decimal import Decimal
 from unittest.mock import MagicMock
 
 import pytest
 from google.cloud import pubsub_v1
 
+from rele.config import Config
 from rele.contrib.logging_middleware import LoggingMiddleware
 from tests.subs import sub_stub
 
@@ -18,6 +20,11 @@ def expected_message_data_log():
     return '{"foo": "bar"}'
 
 
+@pytest.fixture
+def expected_message_data_log_with_decimal():
+    return '{"foo": "1"}'
+
+
 @pytest.fixture
 def message_wrapper(published_at, publish_time):
     rele_message = pubsub_v1.types.PubsubMessage(
@@ -49,6 +56,16 @@ class TestLoggingMiddleware:
         logging_middleware.setup(config)
         return logging_middleware
 
+    @pytest.fixture
+    def logging_middleware_with_custom_encoder(self, logging_middleware):
+        config = Config(
+            {
+                "ENCODER_PATH": "django.core.serializers.json.DjangoJSONEncoder",
+            }
+        )
+        logging_middleware.setup(config)
+        return logging_middleware
+
     def test_message_payload_log_is_converted_to_string_on_post_publish_failure(
         self,
         logging_middleware,
@@ -64,6 +81,23 @@ class TestLoggingMiddleware:
 
         assert message_log == expected_message_data_log
 
+    def test_message_payload_log_uses_custom_encoder(
+        self,
+        logging_middleware_with_custom_encoder,
+        caplog,
+        message_data,
+        expected_message_data_log_with_decimal,
+    ):
+        message_data["foo"] = Decimal(1)
+
+        logging_middleware_with_custom_encoder.post_publish_failure(
+            sub_stub, RuntimeError("💩"), message_data
+        )
+
+        message_log = caplog.records[0].subscription_message
+
+        assert message_log == expected_message_data_log_with_decimal
+
     def test_message_payload_log_is_converted_to_string_on_post_process_message_failure(
         self,
         logging_middleware,