From 1715fcb4d8c98c1e0cfa2006a6cb34c3721d8d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Fri, 31 Mar 2023 10:30:39 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=96=B0=E5=8A=9F=E8=83=BD:=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E6=97=A5=E5=BF=97=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/utils/log.py | 37 ++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/backend/dvadmin/utils/log.py b/backend/dvadmin/utils/log.py index e8081f4..9586c64 100644 --- a/backend/dvadmin/utils/log.py +++ b/backend/dvadmin/utils/log.py @@ -1,28 +1,37 @@ import logging import os.path -from logging import LogRecord +import sys -from django.core.servers.basehttp import WSGIRequestHandler +from django.db import connection from loguru import logger from logging.handlers import RotatingFileHandler # 1.🎖️先声明一个类继承logging.Handler(制作一件品如的衣服) -from loguru._defaults import LOGURU_FORMAT + +from application.dispatch import is_tenants_mode -class InterceptTimedRotatingFileHandler(RotatingFileHandler): +class InterceptTimedRotatingFileHandler(RotatingFileHandler, logging.Filter): """ 自定义反射时间回滚日志记录器 缺少命名空间 """ def __init__(self, filename, when='d', interval=1, backupCount=5, encoding="utf-8", delay=False, utc=False, - maxBytes=1024 * 1024 * 100, atTime=None, logging_levels="all"): + maxBytes=1024 * 1024 * 100, atTime=None, logging_levels="all", format=None): super(InterceptTimedRotatingFileHandler, self).__init__(filename) filename = os.path.abspath(filename) + # 定义默认格式 + if not format: + format = "{time:YYYY-MM-DD HH:mm:ss.SSS} | {extra[ip]}:{extra[port]} | {level: <8}| {name}:{function}:{line} - {message}" when = when.lower() # 2.🎖️需要本地用不同的文件名做为不同日志的筛选器 + logger.configure( + handlers=[ + dict(sink=sys.stderr, format=format), + ], + ) self.logger_ = logger.bind(sime=filename, ip="-", port="-", username="张三") self.filename = filename key_map = { @@ -74,7 +83,7 @@ class InterceptTimedRotatingFileHandler(RotatingFileHandler): # self.logger_.remove(file_key[filename_fmt_key]) self.logger_.add( filename_fmt, - # format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {extra[ip]}:{extra[port]} | {level: <8}| {name}:{function}:{line} - {message}", + format=format, retention=retention, encoding=encoding, level=self.level, @@ -100,13 +109,17 @@ class InterceptTimedRotatingFileHandler(RotatingFileHandler): # 设置自定义属性 port = "-" ip = "-" - locals_self = frame.f_locals.get('self', None) + details = frame.f_locals.get('details', None) msg = self.format(record) - if locals_self and hasattr(locals_self, 'client_address'): - ip, port = locals_self.client_address - # - 127.0.0.1:56525 - - msg = f"{ip}:{port} - {msg}" + bind = {} + if details and details.get('client'): + ip, port = details.get('client').split(':') + if is_tenants_mode(): + bind["schema_name"] = connection.tenant.schema_name + bind["domain_url"] = getattr(connection.tenant, 'domain_url', None) + bind["ip"] = ip + bind["port"] = port self.logger_ \ .opt(depth=depth, exception=record.exc_info, colors=True) \ - .bind(ip=ip, port=port) \ + .bind(**bind) \ .log(level, msg) From c126c704a449f9e01c8037ce68120cc89c6808ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Fri, 31 Mar 2023 10:31:38 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=96=B0=E5=8A=9F=E8=83=BD:=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4gunicorn.pid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/.gitignore | 1 + backend/gunicorn.pid | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 backend/gunicorn.pid diff --git a/backend/.gitignore b/backend/.gitignore index f22f635..7119be0 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -97,3 +97,4 @@ db.sqlite3 media/ __pypackages__/ package-lock.json +gunicorn.pid diff --git a/backend/gunicorn.pid b/backend/gunicorn.pid deleted file mode 100644 index 7f8f011..0000000 --- a/backend/gunicorn.pid +++ /dev/null @@ -1 +0,0 @@ -7 From 9468abd4a25350149f086300204c143f58a44b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Mon, 17 Apr 2023 23:24:43 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E6=96=B0=E5=8A=9F=E8=83=BD:=20=E5=8F=96?= =?UTF-8?q?=E6=B6=88loguru=E6=97=A5=E5=BF=97=EF=BC=8C=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E7=AE=80=E5=8D=95Django=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/application/settings.py | 90 +++++++++++++---------- backend/dvadmin/utils/log.py | 125 -------------------------------- backend/requirements.txt | 1 - 3 files changed, 52 insertions(+), 164 deletions(-) delete mode 100644 backend/dvadmin/utils/log.py diff --git a/backend/application/settings.py b/backend/application/settings.py index 3277e06..f98615b 100644 --- a/backend/application/settings.py +++ b/backend/application/settings.py @@ -187,69 +187,83 @@ CHANNEL_LAYERS = { # ================================================= # # ********************* 日志配置 ******************* # # ================================================= # - -# log 配置部分BEGIN # +# # log 配置部分BEGIN # +SERVER_LOGS_FILE = os.path.join(BASE_DIR, "logs", "server.log") +ERROR_LOGS_FILE = os.path.join(BASE_DIR, "logs", "error.log") LOGS_FILE = os.path.join(BASE_DIR, "logs") if not os.path.exists(os.path.join(BASE_DIR, "logs")): os.makedirs(os.path.join(BASE_DIR, "logs")) +# 格式:[2020-04-22 23:33:01][micoservice.apps.ready():16] [INFO] 这是一条日志: +# 格式:[日期][模块.函数名称():行号] [级别] 信息 +STANDARD_LOG_FORMAT = ( + "[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s" +) +CONSOLE_LOG_FORMAT = ( + "[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s" +) LOGGING = { "version": 1, "disable_existing_loggers": False, "formatters": { - "servers": { - "format": "%(message)s", + "standard": {"format": STANDARD_LOG_FORMAT}, + "console": { + "format": CONSOLE_LOG_FORMAT, "datefmt": "%Y-%m-%d %H:%M:%S", - } + }, + "file": { + "format": CONSOLE_LOG_FORMAT, + "datefmt": "%Y-%m-%d %H:%M:%S", + }, }, "handlers": { - "servers": { - "logging_levels": ["info", "error", "warning"], - "class": "dvadmin.utils.log.InterceptTimedRotatingFileHandler", # 这个路径看你本地放在哪里(下面的log文件) - "filename": os.path.join(LOGS_FILE, "server.log"), - "when": "D", - "interval": 1, + "file": { + "level": "INFO", + "class": "logging.handlers.RotatingFileHandler", + "filename": SERVER_LOGS_FILE, "maxBytes": 1024 * 1024 * 100, # 100 MB - "backupCount": 1, - "formatter": "servers", + "backupCount": 5, # 最多备份5个 + "formatter": "standard", "encoding": "utf-8", - } + }, + "error": { + "level": "ERROR", + "class": "logging.handlers.RotatingFileHandler", + "filename": ERROR_LOGS_FILE, + "maxBytes": 1024 * 1024 * 100, # 100 MB + "backupCount": 3, # 最多备份3个 + "formatter": "standard", + "encoding": "utf-8", + }, + "console": { + "level": "INFO", + "class": "logging.StreamHandler", + "formatter": "console", + }, + }, "loggers": { - # default日志 - 'django': { - 'handlers': ['servers'], - 'propagate': False, - 'level': "INFO" + "": { + "handlers": ["console", "error", "file"], + "level": "INFO", }, - '': { - 'handlers': ['servers'], - 'propagate': False, - 'level': "ERROR" - }, - 'celery': { - 'handlers': ['servers'], - 'propagate': False, - 'level': "INFO" + "django": { + "handlers": ["console", "error", "file"], + "level": "INFO", + "propagate": False, }, 'django.db.backends': { - 'handlers': ['servers'], + 'handlers': ["console", "error", "file"], 'propagate': False, 'level': "INFO" }, - 'django.request': { - 'handlers': ['servers'], - 'propagate': False, - 'level': "DEBUG" - }, "uvicorn.error": { "level": "INFO", - "handlers": ["servers"], + "handlers": ["console", "error", "file"], }, "uvicorn.access": { - "handlers": ["servers"], - "level": "INFO", - "propagate": False + "handlers": ["console", "error", "file"], + "level": "INFO" }, }, } diff --git a/backend/dvadmin/utils/log.py b/backend/dvadmin/utils/log.py deleted file mode 100644 index 9586c64..0000000 --- a/backend/dvadmin/utils/log.py +++ /dev/null @@ -1,125 +0,0 @@ -import logging -import os.path -import sys - -from django.db import connection -from loguru import logger - -from logging.handlers import RotatingFileHandler - -# 1.🎖️先声明一个类继承logging.Handler(制作一件品如的衣服) - -from application.dispatch import is_tenants_mode - - -class InterceptTimedRotatingFileHandler(RotatingFileHandler, logging.Filter): - """ - 自定义反射时间回滚日志记录器 - 缺少命名空间 - """ - - def __init__(self, filename, when='d', interval=1, backupCount=5, encoding="utf-8", delay=False, utc=False, - maxBytes=1024 * 1024 * 100, atTime=None, logging_levels="all", format=None): - super(InterceptTimedRotatingFileHandler, self).__init__(filename) - filename = os.path.abspath(filename) - # 定义默认格式 - if not format: - format = "{time:YYYY-MM-DD HH:mm:ss.SSS} | {extra[ip]}:{extra[port]} | {level: <8}| {name}:{function}:{line} - {message}" - when = when.lower() - # 2.🎖️需要本地用不同的文件名做为不同日志的筛选器 - logger.configure( - handlers=[ - dict(sink=sys.stderr, format=format), - ], - ) - self.logger_ = logger.bind(sime=filename, ip="-", port="-", username="张三") - self.filename = filename - key_map = { - 'h': 'hour', - 'w': 'week', - 's': 'second', - 'm': 'minute', - 'd': 'day', - } - # 根据输入文件格式及时间回滚设立文件名称 - rotation = f"{maxBytes / 1024 / 1024}MB" - retention = "%d %ss" % (backupCount, key_map[when]) - time_format = "{time:%Y-%m-%d_%H-%M-%S}" - if when == "s": - time_format = "{time:%Y-%m-%d_%H-%M-%S}" - elif when == "m": - time_format = "{time:%Y-%m-%d_%H-%M}" - elif when == "h": - time_format = "{time:%Y-%m-%d_%H}" - elif when == "d": - time_format = "{time:%Y-%m-%d}" - elif when == "w": - time_format = "{time:%Y-%m-%d}" - level_keys = ["info"] - # 3.🎖️构建一个筛选器 - levels = { - "debug": lambda x: "DEBUG" == x['level'].name.upper() and x['extra'].get('sime') == filename, - "error": lambda x: "ERROR" == x['level'].name.upper() and x['extra'].get('sime') == filename, - "info": lambda x: "INFO" == x['level'].name.upper() and x['extra'].get('sime') == filename, - "warning": lambda x: "WARNING" == x['level'].name.upper() and x['extra'].get('sime') == filename - } - # 4. 🎖️根据输出构建筛选器 - if isinstance(logging_levels, str): - if logging_levels.lower() == "all": - level_keys = levels.keys() - elif logging_levels.lower() in levels: - level_keys = [logging_levels] - elif isinstance(logging_levels, (list, tuple)): - level_keys = logging_levels - for k, f in {_: levels[_] for _ in level_keys}.items(): - - # 5.🎖️为防止重复添加sink,而重复写入日志,需要判断是否已经装载了对应sink,防止其使用秘技:反复横跳。 - filename_fmt = filename.replace(".log", "_%s_%s.log" % (time_format, k)) - # noinspection PyUnresolvedReferences,PyProtectedMember - file_key = {_._name: han_id for han_id, _ in self.logger_._core.handlers.items()} - filename_fmt_key = "'{}'".format(filename_fmt) - if filename_fmt_key in file_key: - continue - # self.logger_.remove(file_key[filename_fmt_key]) - self.logger_.add( - filename_fmt, - format=format, - retention=retention, - encoding=encoding, - level=self.level, - rotation=rotation, - compression="zip", # 日志归档自行压缩文件 - delay=delay, - enqueue=True, - backtrace=True, - filter=f - ) - - def emit(self, record): - try: - level = self.logger_.level(record.levelname).name - except ValueError: - level = record.levelno - - frame, depth = logging.currentframe(), 2 - # 6.🎖️把当前帧的栈深度回到发生异常的堆栈深度,不然就是当前帧发生异常而无法回溯 - while frame.f_code.co_filename == logging.__file__: - frame = frame.f_back - depth += 1 - # 设置自定义属性 - port = "-" - ip = "-" - details = frame.f_locals.get('details', None) - msg = self.format(record) - bind = {} - if details and details.get('client'): - ip, port = details.get('client').split(':') - if is_tenants_mode(): - bind["schema_name"] = connection.tenant.schema_name - bind["domain_url"] = getattr(connection.tenant, 'domain_url', None) - bind["ip"] = ip - bind["port"] = port - self.logger_ \ - .opt(depth=depth, exception=record.exc_info, colors=True) \ - .bind(**bind) \ - .log(level, msg) diff --git a/backend/requirements.txt b/backend/requirements.txt index a9f8c3b..64fee45 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -15,7 +15,6 @@ ua-parser==0.16.1 pyparsing==3.0.9 openpyxl==3.0.10 requests==2.28.2 -loguru==0.6.0 typing-extensions==4.4.0 smmap==5.0.0 tzlocal==4.1 From 5ab3ad4ed92a8e0ce2a85c57623767daa858d944 Mon Sep 17 00:00:00 2001 From: H0nGzA1 <2505811377@qq.com> Date: Fri, 21 Apr 2023 14:27:03 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=F0=9F=90=9B=20get=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?params=E5=8F=82=E6=95=B0=E9=97=AE=E9=A2=98=EF=BC=8C=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E5=88=86=E9=A1=B5=E4=B8=8D=E6=88=90=E5=8A=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/views/system/fileList/api.ts | 2 +- web/src/views/system/log/loginLog/api.ts | 2 +- web/src/views/system/whiteList/api.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/views/system/fileList/api.ts b/web/src/views/system/fileList/api.ts index 06c6499..7c5708b 100644 --- a/web/src/views/system/fileList/api.ts +++ b/web/src/views/system/fileList/api.ts @@ -6,7 +6,7 @@ export function GetList(query: UserPageQuery) { return request({ url: apiPrefix, method: 'get', - data: query, + params: query, }); } export function GetObj(id: InfoReq) { diff --git a/web/src/views/system/log/loginLog/api.ts b/web/src/views/system/log/loginLog/api.ts index 71575dd..defefc4 100644 --- a/web/src/views/system/log/loginLog/api.ts +++ b/web/src/views/system/log/loginLog/api.ts @@ -6,7 +6,7 @@ export function GetList(query: UserPageQuery) { return request({ url: apiPrefix, method: 'get', - data: query, + params: query, }); } export function GetObj(id: InfoReq) { diff --git a/web/src/views/system/whiteList/api.ts b/web/src/views/system/whiteList/api.ts index 3be27db..9b7e7f1 100644 --- a/web/src/views/system/whiteList/api.ts +++ b/web/src/views/system/whiteList/api.ts @@ -6,7 +6,7 @@ export function GetList(query: UserPageQuery) { return request({ url: apiPrefix, method: 'get', - data: query, + params: query, }); } export function GetObj(id: InfoReq) {