2023-10-23 23:40:36 +08:00
|
|
|
# -------------------------------
|
|
|
|
# Difficult Rocket
|
|
|
|
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
|
|
|
|
# All rights reserved
|
|
|
|
# -------------------------------
|
|
|
|
|
|
|
|
import time
|
|
|
|
import inspect
|
|
|
|
from types import FrameType
|
|
|
|
from typing import List, Optional
|
|
|
|
|
2023-11-06 00:31:03 +08:00
|
|
|
from lib_not_dr.logger import LogLevel
|
2023-10-23 23:40:36 +08:00
|
|
|
from lib_not_dr.types.options import Options
|
2023-11-06 00:19:39 +08:00
|
|
|
from lib_not_dr.logger.structure import LogMessage
|
|
|
|
from lib_not_dr.logger.outstream import BaseOutputStream, StdioOutputStream
|
2023-10-23 23:40:36 +08:00
|
|
|
|
|
|
|
|
|
|
|
class Logger(Options):
|
|
|
|
name = 'Logger-v2'
|
|
|
|
|
2023-11-06 00:19:39 +08:00
|
|
|
outputs: List[BaseOutputStream] = [StdioOutputStream()]
|
|
|
|
|
|
|
|
log_name: str = 'root'
|
2023-10-23 23:40:36 +08:00
|
|
|
|
|
|
|
enable: bool = True
|
2023-11-05 23:56:56 +08:00
|
|
|
level: int = 20 # info
|
2023-10-23 23:40:36 +08:00
|
|
|
|
|
|
|
def log_for(self, level: int) -> bool:
|
|
|
|
"""
|
|
|
|
Check if logging is enabled for a specific level.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
level (int): The logging level to check.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
bool: True if logging is enabled for the given level, False otherwise.
|
|
|
|
"""
|
|
|
|
return self.enable and level >= self.level
|
|
|
|
|
|
|
|
def add_output(self, output: BaseOutputStream) -> None:
|
|
|
|
"""
|
|
|
|
Add an output to the list of outputs.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
output (BaseOutputStream): The output to be added.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
"""
|
|
|
|
self.outputs.append(output)
|
|
|
|
self.level = min(self.level, output.level)
|
|
|
|
|
|
|
|
def remove_output(self, output: BaseOutputStream) -> None:
|
|
|
|
"""
|
|
|
|
Removes the specified output from the list of outputs.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
output (BaseOutputStream): The output to be removed.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
"""
|
|
|
|
self.outputs.remove(output)
|
|
|
|
self.level = max(self.level, *[output.level for output in self.outputs])
|
|
|
|
|
2023-11-06 00:34:06 +08:00
|
|
|
@property
|
|
|
|
def global_level(self) -> int:
|
|
|
|
"""
|
|
|
|
Get the global logging level.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
int: The global logging level.
|
|
|
|
"""
|
|
|
|
return self.level
|
|
|
|
|
|
|
|
@global_level.setter
|
|
|
|
def global_level(self, level: int) -> None:
|
|
|
|
"""
|
|
|
|
Set the global logging level.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
level (int): The global logging level.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
"""
|
|
|
|
self.level = level
|
|
|
|
for output in self.outputs:
|
|
|
|
output.level = level
|
|
|
|
|
2023-10-23 23:40:36 +08:00
|
|
|
def make_log(self,
|
|
|
|
messages: List[str],
|
2023-11-06 00:19:39 +08:00
|
|
|
tag: Optional[str] = None,
|
2023-10-23 23:40:36 +08:00
|
|
|
end: str = '\n',
|
|
|
|
split: str = ' ',
|
|
|
|
flush: bool = True,
|
2023-11-06 00:19:39 +08:00
|
|
|
level: int = 20, # info
|
|
|
|
# log_time: Optional[float] = None,
|
|
|
|
# logger_name: str = 'root',
|
|
|
|
# logger_tag: Optional[str] = None,
|
2023-10-23 23:40:36 +08:00
|
|
|
stack_trace: Optional[FrameType] = None) -> None:
|
|
|
|
# 检查是否需要记录
|
|
|
|
if not self.log_for(level):
|
|
|
|
return
|
2023-11-06 00:19:39 +08:00
|
|
|
log_time = time.time_ns()
|
2023-10-23 23:40:36 +08:00
|
|
|
# 处理堆栈信息
|
|
|
|
if stack_trace is None:
|
|
|
|
# 尝试获取堆栈信息
|
|
|
|
if (stack := inspect.currentframe()) is not None:
|
|
|
|
# 如果可能 尝试获取上两层的堆栈信息
|
|
|
|
if (up_stack := stack.f_back) is not None:
|
|
|
|
if (upper_stack := up_stack.f_back) is not None:
|
|
|
|
stack_trace = upper_stack
|
|
|
|
else:
|
|
|
|
stack_trace = up_stack
|
|
|
|
else:
|
|
|
|
stack_trace = stack
|
|
|
|
|
|
|
|
message = LogMessage(messages=messages,
|
|
|
|
end=end,
|
|
|
|
split=split,
|
|
|
|
flush=flush,
|
|
|
|
level=level,
|
|
|
|
log_time=log_time,
|
2023-11-06 00:19:39 +08:00
|
|
|
logger_name=self.log_name,
|
|
|
|
logger_tag=tag,
|
2023-10-23 23:40:36 +08:00
|
|
|
stack_trace=stack_trace)
|
2023-11-06 00:19:39 +08:00
|
|
|
if level >= 30: # WARN
|
|
|
|
for output in self.outputs:
|
|
|
|
output.write_stderr(message)
|
|
|
|
else:
|
|
|
|
for output in self.outputs:
|
|
|
|
output.write_stdout(message)
|
|
|
|
# done?
|
|
|
|
# 20231106 00:06
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get_logger_by_name(name: str) -> 'Logger':
|
|
|
|
"""
|
|
|
|
Get a logger by name.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
name (str): The name of the logger.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Logger: The logger with the specified name.
|
|
|
|
"""
|
2023-11-06 00:31:03 +08:00
|
|
|
return Logger(log_name=name)
|
|
|
|
|
|
|
|
def info(self,
|
|
|
|
*message,
|
|
|
|
tag: Optional[str] = None,
|
|
|
|
end: str = '\n',
|
|
|
|
split: str = ' ',
|
|
|
|
flush: bool = True,
|
|
|
|
stack_trace: Optional[FrameType] = None) -> None:
|
|
|
|
if not self.log_for(LogLevel.info):
|
|
|
|
return
|
|
|
|
self.make_log(messages=list(message),
|
|
|
|
tag=tag,
|
|
|
|
end=end,
|
|
|
|
split=split,
|
|
|
|
flush=flush,
|
|
|
|
level=LogLevel.info,
|
|
|
|
stack_trace=stack_trace)
|
|
|
|
|
|
|
|
def trace(self,
|
|
|
|
*message,
|
|
|
|
tag: Optional[str] = None,
|
|
|
|
end: str = '\n',
|
|
|
|
split: str = ' ',
|
|
|
|
flush: bool = True,
|
|
|
|
stack_trace: Optional[FrameType] = None) -> None:
|
|
|
|
if not self.log_for(LogLevel.trace):
|
|
|
|
return
|
|
|
|
self.make_log(messages=list(message),
|
|
|
|
tag=tag,
|
|
|
|
end=end,
|
|
|
|
split=split,
|
|
|
|
flush=flush,
|
|
|
|
level=LogLevel.trace,
|
|
|
|
stack_trace=stack_trace)
|
|
|
|
|
|
|
|
def fine(self,
|
|
|
|
*message,
|
|
|
|
tag: Optional[str] = None,
|
|
|
|
end: str = '\n',
|
|
|
|
split: str = ' ',
|
|
|
|
flush: bool = True,
|
|
|
|
stack_trace: Optional[FrameType] = None) -> None:
|
|
|
|
if not self.log_for(LogLevel.fine):
|
|
|
|
return
|
|
|
|
self.make_log(messages=list(message),
|
|
|
|
tag=tag,
|
|
|
|
end=end,
|
|
|
|
split=split,
|
|
|
|
flush=flush,
|
|
|
|
level=LogLevel.fine,
|
|
|
|
stack_trace=stack_trace)
|
|
|
|
|
|
|
|
def debug(self,
|
|
|
|
*message,
|
|
|
|
tag: Optional[str] = None,
|
|
|
|
end: str = '\n',
|
|
|
|
split: str = ' ',
|
|
|
|
flush: bool = True,
|
|
|
|
stack_trace: Optional[FrameType] = None) -> None:
|
|
|
|
if not self.log_for(LogLevel.debug):
|
|
|
|
return
|
|
|
|
self.make_log(messages=list(message),
|
|
|
|
tag=tag,
|
|
|
|
end=end,
|
|
|
|
split=split,
|
|
|
|
flush=flush,
|
|
|
|
level=LogLevel.debug,
|
|
|
|
stack_trace=stack_trace)
|
|
|
|
|
|
|
|
def warn(self,
|
|
|
|
*message,
|
|
|
|
tag: Optional[str] = None,
|
|
|
|
end: str = '\n',
|
|
|
|
split: str = ' ',
|
|
|
|
flush: bool = True,
|
|
|
|
stack_trace: Optional[FrameType] = None) -> None:
|
|
|
|
if not self.log_for(LogLevel.warn):
|
|
|
|
return
|
|
|
|
self.make_log(messages=list(message),
|
|
|
|
tag=tag,
|
|
|
|
end=end,
|
|
|
|
split=split,
|
|
|
|
flush=flush,
|
|
|
|
level=LogLevel.warn,
|
|
|
|
stack_trace=stack_trace)
|
|
|
|
|
|
|
|
def error(self,
|
|
|
|
*message,
|
|
|
|
tag: Optional[str] = None,
|
|
|
|
end: str = '\n',
|
|
|
|
split: str = ' ',
|
|
|
|
flush: bool = True,
|
|
|
|
stack_trace: Optional[FrameType] = None) -> None:
|
|
|
|
if not self.log_for(LogLevel.error):
|
|
|
|
return
|
|
|
|
self.make_log(messages=list(message),
|
|
|
|
tag=tag,
|
|
|
|
end=end,
|
|
|
|
split=split,
|
|
|
|
flush=flush,
|
|
|
|
level=LogLevel.error,
|
|
|
|
stack_trace=stack_trace)
|
|
|
|
|
|
|
|
def fatal(self,
|
|
|
|
*message,
|
|
|
|
tag: Optional[str] = None,
|
|
|
|
end: str = '\n',
|
|
|
|
split: str = ' ',
|
|
|
|
flush: bool = True,
|
|
|
|
stack_trace: Optional[FrameType] = None) -> None:
|
|
|
|
if not self.log_for(LogLevel.fatal):
|
|
|
|
return
|
|
|
|
self.make_log(messages=list(message),
|
|
|
|
tag=tag,
|
|
|
|
end=end,
|
|
|
|
split=split,
|
|
|
|
flush=flush,
|
|
|
|
level=LogLevel.fatal,
|
|
|
|
stack_trace=stack_trace)
|