def format(self, record: LogRecord) -> str: """ Format the specified record as text. The record's attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.get_message(). If the formatting string uses the time (as determined by a call to usesTime(), format_time() is called to format the event time. If there is exception information, it is formatted using format_exception() and appended to the message. """ record.message = record.get_message() if self._style.uses_time: record.asctime = self.format_time(record, self.datefmt) s = self.format_message(record) if record.exc_info: # Cache the traceback text to avoid converting it multiple times # (it's constant anyway) if not record.exc_text: record.exc_text = self.format_exception(record.exc_info) if record.exc_text: if s[-1:] != self.terminator: s = s + self.terminator s = s + record.exc_text if record.stack_info: if s[-1:] != self.terminator: s = s + self.terminator s = s + self.format_stack(record.stack_info) return s
def test_get_message_without_args(self): record = LogRecord( name="name", level=LogLevel.INFO, pathname=__file__, lineno=666, msg="Hello world!", ) self.assertEqual(record.get_message(), "Hello world!")
def test_get_message_with_args(self): record = LogRecord( name="name", level=LogLevel.INFO, pathname=__file__, lineno=666, msg="Dog: %(dog_name)s", args=({ "dog_name": "Xablau" }, ), ) self.assertEqual(record.get_message(), "Dog: Xablau")
async def test_emit_does_rollover_if_should_rollover(self): handler = BaseAsyncRotatingFileHandler(filename=self.temp_file.name) handler.should_rollover = Mock(return_value=True) async def rollover_is_done(): """ sleep is needed so that the loop can schedule the other `do_rollover` coroutines, simulating a real `do_rollover` behaviour """ await asyncio.sleep(0.1) handler.should_rollover.return_value = False handler.do_rollover = CoroutineMock(side_effect=rollover_is_done) await asyncio.gather(*(handler.emit( LogRecord( name=str(i), level=20, pathname="/aiologger/tests/test_logger.py", lineno=17, msg="Xablau!", exc_info=None, args=None, )) for i in range(42))) handler.do_rollover.assert_awaited_once()
def _get_msg_dict(self, record: LogRecord) -> Dict[str, str]: """ :param self: :param record: :return: """ record.message = record.get_message() record.asctime = self.format_time(record, self.datefmt) params = re.findall("%\((.*?)\)", self._fmt) _d = {} for i in params: _v = record.__dict__.get(i) if isinstance(_v, LogLevel): _v = _v.value _d[i] = str(_v) if _v else '' return _d
def test_it_validates_log_record_args(self): with self.assertRaises(ValueError): LogRecord( name="name", level=LogLevel.INFO, pathname=__file__, lineno=666, msg="Dog: %(dog_name)s", args=(1, 2, 3), )
def test_it_saves_record_creation_time(self): with freeze_time("2006-06-06 06:06:06.666666") as t: record = LogRecord( name="name", level=LogLevel.INFO, pathname=__file__, lineno=666, msg="Hello world!", ) self.assertEqual(record.created, 1_149_573_966.666_666)
async def setUp(self): self.record = LogRecord( name="aiologger", level=20, pathname="/aiologger/tests/test_logger.py", lineno=17, msg="Xablau!", exc_info=None, args=None, ) self.temp_file = NamedTemporaryFile()
async def setUp(self): self.log_record = LogRecord( name="aiologger", level=20, pathname="/aiologger/tests/test_logger.py", lineno=17, msg="Xablau!", exc_info=None, args=None, ) self.temp_file = NamedTemporaryFile(delete=False) self.files_to_remove = [self.temp_file.name]
def setUp(self): self.record = LogRecord( level=30, name="aiologger", pathname="/aiologger/tests/formatters/test_json_formatter.py", lineno=42, msg="Xablau", exc_info=None, func="a_function_name", args=None, ) self.formatter = JsonFormatter()
async def setUp(self): self.record = LogRecord( name="aiologger", level=20, pathname="/aiologger/tests/test_logger.py", lineno=17, msg="Xablau!", exc_info=None, args=None, ) r_fileno, w_fileno = os.pipe() self.read_pipe = os.fdopen(r_fileno, "r") self.write_pipe = os.fdopen(w_fileno, "w")
def make_log_record(**kwargs) -> LogRecord: """ Make a LogRecord whose attributes are defined by the specified kwargs """ record = LogRecord( # type: ignore name=None, level=LogLevel.NOTSET, pathname="", lineno=0, msg="", args=(), exc_info=None, ) record.__dict__.update(kwargs) return record
async def test_it_raises_an_error_if_no_handlers_are_found_for_record( self): logger = Logger.with_default_handlers() logger.handlers = [] record = LogRecord( level=10, name="aiologger", pathname="/aiologger/tests/test_logger.py", lineno=17, msg="Xablau!", exc_info=None, args=None, ) with self.assertRaises(Exception): await logger.call_handlers(record)
def test_str_representation(self): record = LogRecord( name="name", level=LogLevel.INFO, pathname=__file__, lineno=666, msg="Dog: %(dog_name)s", args=({ "dog_name": "Xablau" }, ), ) record_str = str(record) self.assertIn(record.__class__.__name__, record_str) self.assertIn(record.levelname, record_str) self.assertIn(record.msg, record_str) self.assertIn(record.pathname, record_str)
async def test_emit_awaits_for_handle_error_is_an_exceptions_is_raised( self): handler = BaseAsyncRotatingFileHandler(filename=self.temp_file.name) handler.should_rollover = Mock(return_value=False) exc = OSError() with patch("aiologger.handlers.files.AsyncFileHandler.emit", side_effect=exc), patch.object( handler, "handle_error", CoroutineMock()) as handleError: log_record = LogRecord( name="Xablau", level=20, pathname="/aiologger/tests/test_logger.py", lineno=17, msg="Xablau!", exc_info=None, args=None, ) await handler.emit(log_record) handleError.assert_awaited_once_with(log_record, exc)
async def test_it_calls_handler_error_if_emit_fails(self): temp_file = NamedTemporaryFile(delete=False) handler = AsyncFileHandler(temp_file.name) log_record = LogRecord( name="Xablau", level=20, pathname="/aiologger/tests/test_logger.py", lineno=17, msg="Xablau!", exc_info=None, args=None, ) await handler._init_writer() exc = Exception("Xablau") with patch.object(handler.stream, "write", side_effect=exc), patch.object( handler, "handle_error", CoroutineMock()) as handle_error: await handler.emit(log_record) handle_error.assert_awaited_once_with(log_record, exc)
async def test_callhandlers_calls_handlers_for_loglevel(self): level10_handler = Mock(level=10, handle=CoroutineMock()) level30_handler = Mock(level=30, handle=CoroutineMock()) logger = Logger.with_default_handlers() logger.handlers = [level10_handler, level30_handler] record = LogRecord( level=20, name="aiologger", pathname="/aiologger/tests/test_logger.py", lineno=17, msg="Xablau!", exc_info=None, args=None, ) await logger.call_handlers(record) level10_handler.handle.assert_awaited_once_with(record) level30_handler.handle.assert_not_awaited()
async def _log( self, level, msg, args, exc_info=None, extra=None, stack_info=False, caller: _Caller = None, ): sinfo = None if _srcfile and caller is None: # type: ignore # IronPython doesn't track Python frames, so find_caller raises an # exception on some versions of IronPython. We trap it here so that # IronPython can use logging. try: fn, lno, func, sinfo = self.find_caller(stack_info) except ValueError: # pragma: no cover fn, lno, func = "(unknown file)", 0, "(unknown function)" elif caller: fn, lno, func, sinfo = caller else: # pragma: no cover fn, lno, func = "(unknown file)", 0, "(unknown function)" if exc_info and isinstance(exc_info, BaseException): exc_info = (type(exc_info), exc_info, exc_info.__traceback__) record = LogRecord( # type: ignore name=self.name, level=level, pathname=fn, lineno=lno, msg=msg, args=args, exc_info=exc_info, func=func, sinfo=sinfo, extra=extra, ) await self.handle(record)