Skip to content

Commit

Permalink
ensure extra events are serializable before uploading (#20)
Browse files Browse the repository at this point in the history
Co-authored-by: Petr Heinz <[email protected]>
  • Loading branch information
gorkem2020 and PetrHeinz authored Dec 13, 2023
1 parent d206a32 commit 32f8507
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 2 deletions.
4 changes: 3 additions & 1 deletion logtail/handler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# coding: utf-8
from __future__ import print_function, unicode_literals
import logging
import json

from .compat import queue
from .helpers import DEFAULT_CONTEXT
Expand Down Expand Up @@ -60,8 +61,9 @@ def emit(self, record):

message = self.format(record)
frame = create_frame(record, message, self.context, include_extra_attributes=self.include_extra_attributes)
serializable_frame = json.loads(json.dumps(frame, default=str))
try:
self.pipe.put(frame, block=(not self.drop_extra_events))
self.pipe.put(serializable_frame, block=(not self.drop_extra_events))
except queue.Full:
# Only raised when not blocking, which means that extra events
# should be dropped.
Expand Down
45 changes: 44 additions & 1 deletion tests/test_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import unittest
import logging

from logtail.handler import LogtailHandler
from logtail import LogtailHandler, context


class TestLogtailHandler(unittest.TestCase):
Expand Down Expand Up @@ -138,3 +138,46 @@ def test_error_suppression(self, MockWorker):

handler.raise_exceptions = False
logger.critical('hello')

@mock.patch('logtail.handler.FlushWorker')
def test_can_send_unserializable_extra_data(self, MockWorker):
buffer_capacity = 1
handler = LogtailHandler(
source_token=self.source_token,
buffer_capacity=buffer_capacity
)

logger = logging.getLogger(__name__)
logger.handlers = []
logger.addHandler(handler)
logger.info('hello', extra={'data': {'unserializable': UnserializableObject()}})

log_entry = handler.pipe.get()

self.assertEqual(log_entry['message'], 'hello')
self.assertRegex(log_entry['data']['unserializable'], r'^<tests\.test_handler\.UnserializableObject object at 0x[0-f]+>$')
self.assertTrue(handler.pipe.empty())

@mock.patch('logtail.handler.FlushWorker')
def test_can_send_unserializable_extra_context(self, MockWorker):
buffer_capacity = 1
handler = LogtailHandler(
source_token=self.source_token,
buffer_capacity=buffer_capacity
)

logger = logging.getLogger(__name__)
logger.handlers = []
logger.addHandler(handler)
with context(data={'unserializable': UnserializableObject()}):
logger.info('hello')

log_entry = handler.pipe.get()

self.assertEqual(log_entry['message'], 'hello')
self.assertRegex(log_entry['context']['data']['unserializable'], r'^<tests\.test_handler\.UnserializableObject object at 0x[0-f]+>$')
self.assertTrue(handler.pipe.empty())


class UnserializableObject(object):
""" Because this is a custom class, it cannot be serialized into JSON. """

0 comments on commit 32f8507

Please sign in to comment.