def test_formatter_with_tz_info_utc(self): """ Check that, if tz is not None, log messages must have timezone info """ formatter = ExtendedJsonFormatter(tz=timezone.utc) result = dict(formatter.formatter_fields_for_record(self.record)) self.assertEqual( result, { 'logged_at': '2018-06-16T13:16:00+00:00', 'line_number': 42, 'function': 'xablaufunc', 'level': 'WARNING', 'file_path': '/aiologger/tests/formatters/test_json_formatter.py' })
def with_default_handlers( # type: ignore cls, *, name: str = "aiologger-json", level: int = LogLevel.NOTSET, serializer: Callable[..., str] = json.dumps, flatten: bool = False, serializer_kwargs: Dict = None, extra: Dict = None, exclude_fields: Iterable[str] = None, loop: Optional[AbstractEventLoop] = None, tz: timezone = None, formatter: Optional[Formatter] = None, ): if formatter is None: formatter = ExtendedJsonFormatter( serializer=serializer, exclude_fields=exclude_fields, tz=tz ) return super(JsonLogger, cls).with_default_handlers( name=name, level=level, loop=loop, flatten=flatten, serializer_kwargs=serializer_kwargs, extra=extra, formatter=formatter, )
def test_json_properly_serialized_when_bytes_object(self): # orjson custom_formatter = ExtendedJsonFormatter(serializer=orjson.dumps) # Note: json.dumps by default uses this separator (', ', ': ') # adding a whitespace whereas with orjson it is not # so to have a perfect match is it necessary to specify it custom_orjson_serializer_msg = custom_formatter.format(self.record) # json serialized_result = self.formatter.format(self.record) content = json.loads(serialized_result) default_json_serializer_msg = self.formatter.serializer( content, separators=(",", ":")) self.assertEqual(custom_orjson_serializer_msg, default_json_serializer_msg)
def __init__(self, name: str = 'aiologger-json', level: int = logging.DEBUG, serializer: Callable[..., str] = json.dumps, flatten: bool = False, serializer_kwargs: Dict = None, extra: Dict = None, exclude_fields: Iterable[str] = None, loop: AbstractEventLoop = None, tz: timezone = None, formatter: Optional[logging.Formatter] = None, handler_factory: Optional[Callable[ [], Awaitable[Iterable[logging.Handler]]]] = None): formatter = formatter or ExtendedJsonFormatter( serializer=serializer, exclude_fields=exclude_fields, tz=tz) super().__init__(name=name, level=level, loop=loop, formatter=formatter, handler_factory=handler_factory) self.flatten = flatten if serializer_kwargs is None: serializer_kwargs = {} self.serializer_kwargs = serializer_kwargs if extra is None: extra = {} self.extra = extra
def test_formatter_with_tz_info_other_zone(self): """ Current time is NOT UTC (is -7) and we want logs to be generate in America/Sao_Paulo (-3) """ tz_america = timezone(timedelta(hours=-3)) formatter = ExtendedJsonFormatter(tz=tz_america) result = dict(formatter.formatter_fields_for_record(self.record)) self.assertEqual( result, { 'logged_at': '2018-06-16T19:20:00-03:00', 'line_number': 42, 'function': 'xablaufunc', 'level': 'WARNING', 'file_path': '/aiologger/tests/formatters/test_json_formatter.py' })
def test_formatter_with_tz_info_utc(self): """ Check that, if tz is not None, log messages must have timezone info """ formatter = ExtendedJsonFormatter(tz=timezone.utc) result = dict(formatter.formatter_fields_for_record(self.record)) self.assertEqual( result, { "logged_at": "2018-06-16T13:16:00+00:00", "line_number": 42, "function": "xablaufunc", "level": "WARNING", "file_path": "/aiologger/tests/formatters/test_json_formatter.py", }, )
def setUp(self): self.formatter = ExtendedJsonFormatter() self.record = LogRecord( level=30, name='aiologger', pathname="/aiologger/tests/formatters/test_json_formatter.py", func='xablaufunc', lineno=42, msg={ "dog": "Xablau", "action": "bark" }, exc_info=None, args=None, extra=None, flatten=False, serializer_kwargs={})
def test_formatter_with_tz_info_america_sao_paulo_from_utc(self): """ Current time is UTC and we want logs to be generated on America/Sao_Paulo (-3) """ tz_america = timezone(timedelta(hours=-3)) formatter = ExtendedJsonFormatter(tz=tz_america) result = dict(formatter.formatter_fields_for_record(self.record)) self.assertEqual( result, { "logged_at": "2018-06-16T13:20:00-03:00", "line_number": 42, "function": "xablaufunc", "level": "WARNING", "file_path": "/aiologger/tests/formatters/test_json_formatter.py", }, )
def get_logger(nats_handler, service_type): """ Creates and returns a nats logging handler Args: nats_handler: a nats_handler object service_type: type of service """ handler = NatsLoggingHandler(nats_handler, service_type) formatter = ExtendedJsonFormatter(exclude_fields=["file_path"]) handler.formatter = formatter logger = JsonLogger(name=nats_handler.sender_id) logger.add_handler(handler) return logger
def test_default_log_fields_can_be_excluded_with_exclude_fields_initialization_argument( self): formatter = ExtendedJsonFormatter( exclude_fields=(LOG_LEVEL_FIELDNAME, )) self.assertNotIn(LOG_LEVEL_FIELDNAME, formatter.log_fields)
def test_it_uses_default_log_fields_if_none_are_excluded_on_initialization( self): formatter = ExtendedJsonFormatter() self.assertEqual(ExtendedJsonFormatter.default_fields, formatter.log_fields)
class ExtendedJsonFormatterTests(unittest.TestCase): def setUp(self): self.formatter = ExtendedJsonFormatter() self.record = ExtendedLogRecord( level=30, name="aiologger", pathname="/aiologger/tests/formatters/test_json_formatter.py", func="xablaufunc", lineno=42, msg={ "dog": "Xablau", "action": "bark" }, exc_info=None, args=None, extra=None, flatten=False, serializer_kwargs={}, ) def test_it_uses_default_log_fields_if_none_are_excluded_on_initialization( self): formatter = ExtendedJsonFormatter() self.assertEqual(ExtendedJsonFormatter.default_fields, formatter.log_fields) def test_default_log_fields_can_be_excluded_with_exclude_fields_initialization_argument( self): formatter = ExtendedJsonFormatter( exclude_fields=(LOG_LEVEL_FIELDNAME, )) self.assertNotIn(LOG_LEVEL_FIELDNAME, formatter.log_fields) def test_formatter_fields_for_record_with_default_fields(self): result = dict(self.formatter.formatter_fields_for_record(self.record)) self.assertEqual( result, { "logged_at": ANY, "line_number": 42, "function": "xablaufunc", "level": "WARNING", "file_path": "/aiologger/tests/formatters/test_json_formatter.py", }, ) @freeze_time("2018-06-16T10:16:00-03:00") def test_formatter_with_tz_info_utc(self): """ Check that, if tz is not None, log messages must have timezone info """ formatter = ExtendedJsonFormatter(tz=timezone.utc) result = dict(formatter.formatter_fields_for_record(self.record)) self.assertEqual( result, { "logged_at": "2018-06-16T13:16:00+00:00", "line_number": 42, "function": "xablaufunc", "level": "WARNING", "file_path": "/aiologger/tests/formatters/test_json_formatter.py", }, ) @freeze_time("2018-06-16T16:20:00+00:00") def test_formatter_with_tz_info_america_sao_paulo_from_utc(self): """ Current time is UTC and we want logs to be generated on America/Sao_Paulo (-3) """ tz_america = timezone(timedelta(hours=-3)) formatter = ExtendedJsonFormatter(tz=tz_america) result = dict(formatter.formatter_fields_for_record(self.record)) self.assertEqual( result, { "logged_at": "2018-06-16T13:20:00-03:00", "line_number": 42, "function": "xablaufunc", "level": "WARNING", "file_path": "/aiologger/tests/formatters/test_json_formatter.py", }, ) @freeze_time("2018-06-16T15:20:00-07:00") def test_formatter_with_tz_info_other_zone(self): """ Current time is NOT UTC (is -7) and we want logs to be generate in America/Sao_Paulo (-3) """ tz_america = timezone(timedelta(hours=-3)) formatter = ExtendedJsonFormatter(tz=tz_america) result = dict(formatter.formatter_fields_for_record(self.record)) self.assertEqual( result, { "logged_at": "2018-06-16T19:20:00-03:00", "line_number": 42, "function": "xablaufunc", "level": "WARNING", "file_path": "/aiologger/tests/formatters/test_json_formatter.py", }, ) def test_formatter_fields_for_record_with_excluded_fields(self): log_fields = {LOG_LEVEL_FIELDNAME, LINE_NUMBER_FIELDNAME} with patch.object(self.formatter, "log_fields", log_fields): result = dict( self.formatter.formatter_fields_for_record(self.record)) self.assertEqual(result, {"line_number": 42, "level": "WARNING"}) def test_default_format(self): serialized_result = self.formatter.format(self.record) content = json.loads(serialized_result) self.assertEqual( content, { "logged_at": ANY, "line_number": 42, "function": "xablaufunc", "level": "WARNING", "file_path": "/aiologger/tests/formatters/test_json_formatter.py", "msg": { "dog": "Xablau", "action": "bark" }, }, ) def test_flatten_record_attr_adds_msg_to_root(self): self.record.flatten = True serialized_result = self.formatter.format(self.record) content = json.loads(serialized_result) self.assertEqual( content, { "logged_at": ANY, "line_number": 42, "function": "xablaufunc", "level": "WARNING", "file_path": "/aiologger/tests/formatters/test_json_formatter.py", "dog": "Xablau", "action": "bark", }, ) def test_flatten_record_attr_does_nothing_if_msg_isnt_a_dict_instance( self): self.record.flatten = True self.record.msg = "Xablau, the dog" serialized_result = self.formatter.format(self.record) content = json.loads(serialized_result) self.assertEqual( content, { "logged_at": ANY, "line_number": 42, "function": "xablaufunc", "level": "WARNING", "file_path": "/aiologger/tests/formatters/test_json_formatter.py", "msg": "Xablau, the dog", }, ) def test_serialized_kwargs_record_attr_is_passed_to_instance_serialized_function( self): self.record.serializer_kwargs = {"indent": 2, "sort_keys": True} expected_msg = { "logged_at": ANY, "line_number": 42, "function": "xablaufunc", "level": "WARNING", "file_path": "/aiologger/tests/formatters/test_json_formatter.py", "msg": { "dog": "Xablau", "action": "bark" }, } with patch.object(self.formatter, "serializer") as serializer: self.formatter.format(self.record) serializer.assert_called_once_with( expected_msg, indent=2, sort_keys=True, default=self.formatter._default_handler, ) def test_extra_record_attr_adds_content_to_root_of_msg(self): self.record.extra = {"female_dog": "Xena"} serialized_result = self.formatter.format(self.record) content = json.loads(serialized_result) self.assertEqual( content, { "logged_at": ANY, "line_number": 42, "function": "xablaufunc", "level": "WARNING", "file_path": "/aiologger/tests/formatters/test_json_formatter.py", "msg": { "dog": "Xablau", "action": "bark" }, "female_dog": "Xena", }, )