137 lines
4.9 KiB
Python
137 lines
4.9 KiB
Python
# The following code and documentation was inspired, and in some cases
|
|
# copied and modified, from the work of Vinay Sajip and contributors
|
|
# on cpython's logging package
|
|
import os
|
|
import time
|
|
import types
|
|
from collections.abc import Mapping
|
|
from typing import Optional, Tuple, Type
|
|
|
|
from aiologger.levels import LogLevel, get_level_name
|
|
|
|
ExceptionInfo = Tuple[Type[BaseException], BaseException, types.TracebackType]
|
|
|
|
|
|
class LogRecord:
|
|
"""
|
|
A LogRecord instance represents an event being logged.
|
|
|
|
ExtendedLogRecord instances are created every time something is logged. They
|
|
contain all the information pertinent to the event being logged. The
|
|
main information passed in is in msg and args, which are combined
|
|
using str(msg) % args to create the message field of the record. The
|
|
record also includes information such as when the record was created,
|
|
the source line where the logging call was made, and any exception
|
|
information to be logged.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
name: str,
|
|
level: LogLevel,
|
|
pathname: str,
|
|
lineno: int,
|
|
msg,
|
|
args: Optional[Tuple[Mapping]] = None,
|
|
exc_info: Optional[ExceptionInfo] = None,
|
|
func: Optional[str] = None,
|
|
sinfo: Optional[str] = None,
|
|
**kwargs,
|
|
) -> None:
|
|
"""
|
|
:param name: The name of the logger used to log the event represented
|
|
by this LogRecord. Note that this name will always have this value,
|
|
even though it may be emitted by a handler attached to a
|
|
different (ancestor) logger.
|
|
:param level: The numeric level of the logging event (one of DEBUG,
|
|
INFO etc.) Note that this is converted to two attributes of the
|
|
LogRecord: levelno for the numeric value and levelname for the
|
|
corresponding level name.
|
|
:param pathname: The full pathname of the source file where the
|
|
logging call was made.
|
|
:param lineno: The line number in the source file where the logging
|
|
call was made.
|
|
:param msg: The event description message, possibly a format string
|
|
with placeholders for variable data.
|
|
:param args: Variable data to merge into the msg argument to obtain
|
|
the event description.
|
|
:param exc_info: An exception tuple with the current exception
|
|
information, or None if no exception information is available.
|
|
:param func: The name of the function or method from which the
|
|
logging call was invoked.
|
|
:param sinfo: A text string representing stack information from the
|
|
base of the stack in the current thread, up to the logging call.
|
|
"""
|
|
created_at = time.time()
|
|
self.name = name
|
|
self.msg = msg
|
|
self.args: Optional[Mapping]
|
|
if args:
|
|
if len(args) != 1 or not isinstance(args[0], Mapping):
|
|
raise ValueError(
|
|
f"Invalid LogRecord args type: {type(args[0])}. "
|
|
f"Expected Mapping"
|
|
)
|
|
self.args: Optional[Mapping] = args[0]
|
|
else:
|
|
self.args = args
|
|
self.levelname = get_level_name(level)
|
|
self.levelno = level
|
|
self.pathname = pathname
|
|
try:
|
|
self.filename = os.path.basename(pathname)
|
|
self.module = os.path.splitext(self.filename)[0]
|
|
except (TypeError, ValueError, AttributeError):
|
|
self.filename = pathname
|
|
self.module = "Unknown module"
|
|
self.exc_info = exc_info
|
|
self.exc_text: Optional[str] = None # used to cache the traceback text
|
|
self.stack_info = sinfo
|
|
self.lineno = lineno
|
|
self.funcName = func
|
|
self.created = created_at
|
|
self.msecs = (created_at - int(created_at)) * 1000
|
|
self.process = os.getpid()
|
|
self.asctime: Optional[str] = None
|
|
self.message: Optional[str] = None
|
|
|
|
def __str__(self):
|
|
return (
|
|
f"<{self.__class__.__name__}: {self.name}, {self.levelname}, "
|
|
f'{self.pathname}, {self.lineno}, "{self.msg}">'
|
|
)
|
|
|
|
__repr__ = __str__
|
|
|
|
def get_message(self):
|
|
"""
|
|
Return the message for this LogRecord after merging any user-supplied
|
|
arguments with the message.
|
|
"""
|
|
msg = str(self.msg)
|
|
if self.args:
|
|
msg = msg % self.args
|
|
return msg
|
|
|
|
|
|
class ExtendedLogRecord(LogRecord):
|
|
def __init__(
|
|
self,
|
|
name: str,
|
|
level: LogLevel,
|
|
pathname: str,
|
|
lineno: int,
|
|
msg,
|
|
args: Optional[Tuple[Mapping]],
|
|
exc_info: Optional[ExceptionInfo],
|
|
func: Optional[str] = None,
|
|
sinfo: Optional[str] = None,
|
|
**kwargs,
|
|
) -> None:
|
|
super().__init__(
|
|
name, level, pathname, lineno, msg, args, exc_info, func, sinfo
|
|
)
|
|
self.extra = kwargs["extra"]
|
|
self.flatten = kwargs["flatten"]
|
|
self.serializer_kwargs = kwargs["serializer_kwargs"]
|