From 5803d9999d3763e1cc7ac746273cf2873cede646 Mon Sep 17 00:00:00 2001 From: fenn-cs Date: Mon, 11 Oct 2021 13:49:29 +0100 Subject: [PATCH] remove unseriable args in log_call_deferred passed to start_action Signed-off-by: fenn-cs --- src/allmydata/test/test_eliotutil.py | 4 ++-- src/allmydata/util/eliotutil.py | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/allmydata/test/test_eliotutil.py b/src/allmydata/test/test_eliotutil.py index 1fbb9ec8d..3d7b2bd42 100644 --- a/src/allmydata/test/test_eliotutil.py +++ b/src/allmydata/test/test_eliotutil.py @@ -297,7 +297,7 @@ class LogCallDeferredTests(TestCase): self.assertThat( f(4), succeeded(Equals(16))) msg = logger.messages[0] - assertContainsFields(self, msg, {"args": (4,)}) + assertContainsFields(self, msg, {"args": {'arg_0': 4}}) @capture_logging( lambda self, logger: @@ -328,5 +328,5 @@ class LogCallDeferredTests(TestCase): return base ** exp self.assertThat(f(10, 2, message="an exponential function"), succeeded(Equals(100))) msg = logger.messages[0] - assertContainsFields(self, msg, {"args": (10, 2)}) + assertContainsFields(self, msg, {"args": {'arg_0': 10, 'arg_1': 2}}) assertContainsFields(self, msg, {"kwargs": {"message": "an exponential function"}}) diff --git a/src/allmydata/util/eliotutil.py b/src/allmydata/util/eliotutil.py index e0c2fd8ae..fb18ed332 100644 --- a/src/allmydata/util/eliotutil.py +++ b/src/allmydata/util/eliotutil.py @@ -91,7 +91,7 @@ from .jsonbytes import ( AnyBytesJSONEncoder, bytes_to_unicode ) - +import json def validateInstanceOf(t): @@ -315,6 +315,14 @@ class _DestinationParser(object): _parse_destination_description = _DestinationParser().parse +def is_json_serializable(object): + try: + json.dumps(object) + return True + except (TypeError, OverflowError): + return False + + def log_call_deferred(action_type): """ Like ``eliot.log_call`` but for functions which return ``Deferred``. @@ -325,7 +333,14 @@ def log_call_deferred(action_type): # Use the action's context method to avoid ending the action when # the `with` block ends. kwargs = {k: bytes_to_unicode(True, kw[k]) for k in kw} - with start_action(action_type=action_type, args=a, kwargs=kwargs).context(): + # Remove complex (unserializable) objects from positional args to + # prevent eliot from throwing errors when it attempts serialization + args = { + "arg_" + str(pos): bytes_to_unicode(True, a[pos]) + for pos in range(len(a)) + if is_json_serializable(a[pos]) + } + with start_action(action_type=action_type, args=args, kwargs=kwargs).context(): # Use addActionFinish so that the action finishes when the # Deferred fires. d = maybeDeferred(f, *a, **kw) @@ -339,3 +354,5 @@ if PY2: capture_logging = eliot_capture_logging else: capture_logging = partial(eliot_capture_logging, encoder_=AnyBytesJSONEncoder) + +