Skip to content

Commit

Permalink
Allow log float non-JSON compliant values (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
liranbg authored Jun 2, 2021
1 parent 4c54f56 commit f183ffd
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 5 deletions.
10 changes: 5 additions & 5 deletions hack/ci_assets/function/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@


def handler(context: nuclio_sdk.Context, event: nuclio_sdk.Event):
headers = {
ensure_str(header): ensure_str(value) for header, value in event.headers.items()
}
context.logger.debug_with(
"Received request",
event=json.dumps(
{
"id": event.id,
"eventType": event.trigger.kind,
"contentType": event.content_type,
"headers": {
ensure_str(header): ensure_str(value)
for header, value in event.headers.items()
},
"headers": headers,
"timestamp": event.timestamp.isoformat("T") + "Z",
"path": event.path,
"url": event.url,
Expand All @@ -46,7 +46,7 @@ def handler(context: nuclio_sdk.Context, event: nuclio_sdk.Event):
),
)
return context.Response(
headers=event.headers,
headers=headers,
body={
"sdk_version": get_sdk_version(),
},
Expand Down
63 changes: 63 additions & 0 deletions nuclio_sdk/json_encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,73 @@
# limitations under the License.

import json
import json.encoder


# JSON encoder that can encode custom stuff
class Encoder(json.JSONEncoder):
def __init__(self, **kwargs):
super(Encoder, self).__init__(**kwargs)
self.nan_str = "NaN"

def iterencode(self, o, _one_shot=False):
"""
Encode the given object and yield each string
representation as available.
For example::
for chunk in JSONEncoder().iterencode(bigobject):
mysocket.write(chunk)
"""
if self.check_circular:
markers = {}
else:
markers = None
if self.ensure_ascii:
_encoder = json.encoder.encode_basestring_ascii
else:
_encoder = json.encoder.encode_basestring

def floatstr(
o,
allow_nan=self.allow_nan,
nan_str=self.nan_str,
_repr=float.__repr__,
_inf=json.encoder.INFINITY,
_neginf=-json.encoder.INFINITY,
):
if o != o:
text = '"{0}"'.format(nan_str)
elif o == _inf:
text = '"Infinity"'
elif o == _neginf:
text = '"-Infinity"'
else:
return _repr(o)

if not allow_nan:
raise ValueError(
"Out of range float values are not JSON compliant: " + repr(o)
)

return text

_iterencode = json.encoder._make_iterencode(
markers,
self.default,
_encoder,
self.indent,
floatstr,
self.key_separator,
self.item_separator,
self.sort_keys,
self.skipkeys,
_one_shot,
)
return _iterencode(o, 0)

def default(self, obj):

# EAFP all the way. Leave the unused "exc" in for debugging ease
Expand Down
24 changes: 24 additions & 0 deletions nuclio_sdk/test/test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,30 @@ def test_log_with_date(self):
self._io.getvalue(),
)

def test_log_nan(self):
self._logger.info_with(self._testMethodName, nan=float("NaN"))
self.assertIn(self._testMethodName, self._io.getvalue())
self.assertIn(
'"with": {"nan": "NaN"}',
self._io.getvalue(),
)

def test_log_infinity(self):
self._logger.info_with(self._testMethodName, nan=float("Infinity"))
self.assertIn(self._testMethodName, self._io.getvalue())
self.assertIn(
'"with": {"nan": "Infinity"}',
self._io.getvalue(),
)

def test_log_minus_infinity(self):
self._logger.info_with(self._testMethodName, nan=float("-Infinity"))
self.assertIn(self._testMethodName, self._io.getvalue())
self.assertIn(
'"with": {"nan": "-Infinity"}',
self._io.getvalue(),
)

def test_fail_to_log(self):
"""
Do not fail logging when an object is not log-able
Expand Down

0 comments on commit f183ffd

Please sign in to comment.