From 3866df01a37c2a72788e5a0764a56123972a0932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8A=99=E5=AE=81=E5=A8=9C?= <3072252442@qq.com> Date: Sun, 17 Mar 2024 14:06:09 +0000 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20Log4p?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Log4p/Log4p.py | 100 ++++++++++++++++++++++++++++++++++++++ Log4p/Readme.MD | 49 +++++++++++++++++++ Log4p/core.py | 1 + Log4p/plugins_for_core.py | 8 +++ Log4p/setup.py | 24 +++++++++ 5 files changed, 182 insertions(+) create mode 100644 Log4p/Log4p.py create mode 100644 Log4p/Readme.MD create mode 100644 Log4p/core.py create mode 100644 Log4p/plugins_for_core.py create mode 100644 Log4p/setup.py diff --git a/Log4p/Log4p.py b/Log4p/Log4p.py new file mode 100644 index 0000000..4bab58f --- /dev/null +++ b/Log4p/Log4p.py @@ -0,0 +1,100 @@ +from Log4p.plugins_for_core import * + +class LogManager: + def __init__(self) -> None: + self.public_formatter = logging.Formatter( + fmt='[%(asctime)s][%(name)s/%(levelname)s][%(funcName)s]:%(message)s', + datefmt='%H:%M:%S' + ) + + def GetLogger(self, log_name: str = "default", + out_to_console: bool = True, + web_log_mode: bool = False, + WSpost_url: str = "", + HTTPpost_url: str = "", + http_mode: bool = False, + custom_formatter: logging.Formatter = None): + # 确保日志名称有效 + log_name = log_name if log_name else "default" + if out_to_console: + log_folder = f'./logs/{log_name}' + if not os.path.exists(log_folder): + os.makedirs(log_folder, exist_ok=True) + + logger = logging.getLogger(log_name) + if logger.hasHandlers(): + # Logger已经配置过处理器,避免重复配置 + return logger + + # 颜色配置 + log_color_config = { + 'DEBUG': 'bold_blue', 'INFO': 'bold_cyan', + 'WARNING': 'bold_yellow', 'ERROR': 'red', + 'CRITICAL': 'bold_red', 'RESET': 'reset', + 'asctime': 'green' + } + if out_to_console: + console_handler = logging.StreamHandler() + console_handler.setLevel(logging.DEBUG) + console_formatter = colorlog.ColoredFormatter( + fmt='%(log_color)s [%(asctime)s][%(name)s/%(levelname)s][%(funcName)s]:%(message)s %(reset)s', + datefmt='%H:%M:%S', + log_colors=log_color_config + ) + if custom_formatter: + console_formatter = custom_formatter + + if isinstance(console_handler, logging.StreamHandler): + console_formatter = colorlog.ColoredFormatter(fmt=f"%(log_color)s {console_formatter._fmt} %(reset)s",datefmt=console_formatter.datefmt, log_colors=log_color_config) + console_handler.setFormatter(console_formatter) + + logger.setLevel(logging.DEBUG) + logger.addHandler(console_handler) + + + file_handler = logging.FileHandler( + filename=f'logs/{log_name}/{log_name}.log', mode='a', encoding='utf-8') + file_handler.setLevel(logging.INFO) + file_handler.setFormatter(self.public_formatter) + + if custom_formatter: + file_handler.setFormatter(custom_formatter) + + # 检查代码是否在异步环境中运行 + if asyncio.iscoroutinefunction(logging.Handler.emit): + queue = asyncio.Queue() + queue_handler = QueueHandler(queue) + queue_listener = QueueListener(queue, file_handler) + logger.addHandler(queue_handler) + asyncio.ensure_future(queue_listener.start()) + else: + logger.addHandler(file_handler) + + if web_log_mode and WSpost_url: + websocket_handler = WebsocketHandler(WSpost_url) + websocket_handler.setLevel(logging.INFO) + formatter = self.public_formatter + if custom_formatter: + formatter = custom_formatter + websocket_handler.setFormatter(formatter) + logger.addHandler(websocket_handler) + + if http_mode and HTTPpost_url: + # 检查代码是否在异步环境中运行 + if asyncio.iscoroutinefunction(logging.Handler.emit): + async_http_hander = AsyncHTTPhandler(HTTPpost_url) + async_http_hander.setLevel(logging.INFO) + formatter = self.public_formatter + if custom_formatter: + formatter = custom_formatter + async_http_hander.setFormatter(formatter) + logger.addHandler(async_http_hander) + http_handler = HTTPhandler(HTTPpost_url) + http_handler.setLevel(logging.INFO) + formatter = self.public_formatter + if custom_formatter: + formatter = custom_formatter + http_handler.setFormatter(formatter) + logger.addHandler(http_handler) + + return logger \ No newline at end of file diff --git a/Log4p/Readme.MD b/Log4p/Readme.MD new file mode 100644 index 0000000..277df07 --- /dev/null +++ b/Log4p/Readme.MD @@ -0,0 +1,49 @@ + +# Log4p日志库 + +## 描述 + +这是一个可以支持异步记录日志,发送到HTTP,websocket服务器,同时配置简单,它还实现了识别代码异步和同步的环境 +以支持不同环境下的日志记录,当然了,理论上,这个日志如果2个模式都启用(websocket,http),那么会分别的往2个地方发送日志 + +### 示例用法 + +```python +#from core import * +from Log4p import LogManager + +logger = LogManager().GetLogger( + log_name='example', + out_to_console=True, + web_log_mode=True, + WSpost_url='ws://localhost:8765', + HTTPpost_url='http://localhost:8765', + http_mode = True + custom_fomatter='%(asctime)s - %(name)s - %(levelname)s - %(message)s' +) + +logger.info('这是一个成功信息') +logger.debug('这是一个调试信息') +logger.critical('这是一个严重错误信息') +logger.error('这是一个错误信息') +logger.warning('这是一个警告信息') +``` + +### 参数介绍 + +- `log_name`: 指定日志记录器的名称 +- `out_to_console`: 是否输出到控制台,默认true +- `web_log_mode`:是否启用websocket日志输出模式,默认false +- `WSpost_url`: 如果启用websocket模式,则传入post_url,否则不管,默认None +- `HTTPpost_url`: 如果启用http模式,则传入post_url,否则不管,默认None +- `http_mode`: 是否启用http日志输出模式,默认false + +## 更新日志 + +# 2024/2/20 1:01 + +更新了自定义格式功能,修复了少量bug + +## 添加参数 + +- `custom_formatter`: 自定义格式化函数,默认None diff --git a/Log4p/core.py b/Log4p/core.py new file mode 100644 index 0000000..a0d16a1 --- /dev/null +++ b/Log4p/core.py @@ -0,0 +1 @@ +from Log4p.Log4p import LogManager \ No newline at end of file diff --git a/Log4p/plugins_for_core.py b/Log4p/plugins_for_core.py new file mode 100644 index 0000000..edc76a9 --- /dev/null +++ b/Log4p/plugins_for_core.py @@ -0,0 +1,8 @@ +import logging +import colorlog +import os +import asyncio +from logging.handlers import QueueHandler, QueueListener +from Log4p.plugins.websocketHander import WebsocketHandler +from Log4p.plugins.HttpHander import HTTPhandler , AsyncHTTPhandler +from Log4p.plugins.DecoratorsTools import * \ No newline at end of file diff --git a/Log4p/setup.py b/Log4p/setup.py new file mode 100644 index 0000000..bdc360a --- /dev/null +++ b/Log4p/setup.py @@ -0,0 +1,24 @@ +from setuptools import setup, find_packages + +setup( + name='Log4p', + version='1.0.0', + packages=find_packages(), + author='芙宁娜', + author_email='3072252442@qq.com', + description='A logging library for Python', + long_description=open('Readme.md','r',encoding='utf-8').read(), + long_description_content_type='text/markdown', + url='https://github.com/KOKOMI12345/Log4p', + install_requires=[ + 'requests', + 'websockets', + 'colorlog', + 'httpx', + ], + classifiers=[ + 'Programming Language :: Python :: 3', + 'License :: OSI Approved :: MIT License', + 'Operating System :: OS Independent', + ], +)