Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions logtail/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ def _parse_custom_events(record, include_extra_attributes):
def _remove_circular_dependencies(obj, memo=None):
if memo is None:
memo = set()
# Skip immutable types, which can't contain circular dependencies
if isinstance(obj, (str, int, float, bool)):
return obj
if id(obj) in memo:
return "<omitted circular reference>"
memo.add(id(obj))
Expand All @@ -69,8 +72,11 @@ def _remove_circular_dependencies(obj, memo=None):
new_dict[key] = _remove_circular_dependencies(value, memo)
return new_dict
elif isinstance(obj, list):
new_list = [_remove_circular_dependencies(item, memo) for item in obj]
return new_list
return [_remove_circular_dependencies(item, memo) for item in obj]
elif isinstance(obj, tuple):
return tuple(_remove_circular_dependencies(item, memo) for item in obj)
elif isinstance(obj, set):
return {_remove_circular_dependencies(item, memo) for item in obj}
else:
return obj

Expand Down
20 changes: 20 additions & 0 deletions tests/test_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,26 @@ def test_can_send_circular_dependency_in_extra_data(self, MockWorker):
self.assertEqual(log_entry['data']['egg']['chicken'], "<omitted circular reference>")
self.assertTrue(handler.pipe.empty())

@patch('logtail.handler.FlushWorker')
def test_can_have_multiple_instance_of_same_string_in_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)
test_string = 'this is a test string'
logger.info('hello', extra={'test1': test_string, 'test2': test_string})

log_entry = handler.pipe.get()

self.assertEqual(log_entry['message'], 'hello')
self.assertEqual(log_entry['test1'], 'this is a test string')
self.assertEqual(log_entry['test2'], 'this is a test string')
self.assertTrue(handler.pipe.empty())

@patch('logtail.handler.FlushWorker')
def test_can_send_circular_dependency_in_context(self, MockWorker):
Expand Down