Merge branch 'master' into dev

This commit is contained in:
H0nGzA1
2023-04-21 14:30:12 +08:00
8 changed files with 56 additions and 155 deletions

1
backend/.gitignore vendored
View File

@@ -97,3 +97,4 @@ db.sqlite3
media/ media/
__pypackages__/ __pypackages__/
package-lock.json package-lock.json
gunicorn.pid

View File

@@ -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") LOGS_FILE = os.path.join(BASE_DIR, "logs")
if not os.path.exists(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")) 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 = { LOGGING = {
"version": 1, "version": 1,
"disable_existing_loggers": False, "disable_existing_loggers": False,
"formatters": { "formatters": {
"servers": { "standard": {"format": STANDARD_LOG_FORMAT},
"format": "%(message)s", "console": {
"format": CONSOLE_LOG_FORMAT,
"datefmt": "%Y-%m-%d %H:%M:%S", "datefmt": "%Y-%m-%d %H:%M:%S",
} },
"file": {
"format": CONSOLE_LOG_FORMAT,
"datefmt": "%Y-%m-%d %H:%M:%S",
},
}, },
"handlers": { "handlers": {
"servers": { "file": {
"logging_levels": ["info", "error", "warning"], "level": "INFO",
"class": "dvadmin.utils.log.InterceptTimedRotatingFileHandler", # 这个路径看你本地放在哪里(下面的log文件) "class": "logging.handlers.RotatingFileHandler",
"filename": os.path.join(LOGS_FILE, "server.log"), "filename": SERVER_LOGS_FILE,
"when": "D",
"interval": 1,
"maxBytes": 1024 * 1024 * 100, # 100 MB "maxBytes": 1024 * 1024 * 100, # 100 MB
"backupCount": 1, "backupCount": 5, # 最多备份5个
"formatter": "servers", "formatter": "standard",
"encoding": "utf-8", "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": { "loggers": {
# default日志 "": {
'django': { "handlers": ["console", "error", "file"],
'handlers': ['servers'], "level": "INFO",
'propagate': False,
'level': "INFO"
}, },
'': { "django": {
'handlers': ['servers'], "handlers": ["console", "error", "file"],
'propagate': False, "level": "INFO",
'level': "ERROR" "propagate": False,
},
'celery': {
'handlers': ['servers'],
'propagate': False,
'level': "INFO"
}, },
'django.db.backends': { 'django.db.backends': {
'handlers': ['servers'], 'handlers': ["console", "error", "file"],
'propagate': False, 'propagate': False,
'level': "INFO" 'level': "INFO"
}, },
'django.request': {
'handlers': ['servers'],
'propagate': False,
'level': "DEBUG"
},
"uvicorn.error": { "uvicorn.error": {
"level": "INFO", "level": "INFO",
"handlers": ["servers"], "handlers": ["console", "error", "file"],
}, },
"uvicorn.access": { "uvicorn.access": {
"handlers": ["servers"], "handlers": ["console", "error", "file"],
"level": "INFO", "level": "INFO"
"propagate": False
}, },
}, },
} }

View File

@@ -1,112 +0,0 @@
import logging
import os.path
from logging import LogRecord
from django.core.servers.basehttp import WSGIRequestHandler
from loguru import logger
from logging.handlers import RotatingFileHandler
# 1.🎖先声明一个类继承logging.Handler(制作一件品如的衣服)
from loguru._defaults import LOGURU_FORMAT
class InterceptTimedRotatingFileHandler(RotatingFileHandler):
"""
自定义反射时间回滚日志记录器
缺少命名空间
"""
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"):
super(InterceptTimedRotatingFileHandler, self).__init__(filename)
filename = os.path.abspath(filename)
when = when.lower()
# 2.🎖️需要本地用不同的文件名做为不同日志的筛选器
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="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <green>{extra[ip]}:{extra[port]}</green> | <level>{level: <8}</level>| <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
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 = "-"
locals_self = frame.f_locals.get('self', 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}"
self.logger_ \
.opt(depth=depth, exception=record.exc_info, colors=True) \
.bind(ip=ip, port=port) \
.log(level, msg)

View File

@@ -1 +0,0 @@
7

View File

@@ -15,7 +15,6 @@ ua-parser==0.16.1
pyparsing==3.0.9 pyparsing==3.0.9
openpyxl==3.0.10 openpyxl==3.0.10
requests==2.28.2 requests==2.28.2
loguru==0.6.0
typing-extensions==4.4.0 typing-extensions==4.4.0
smmap==5.0.0 smmap==5.0.0
tzlocal==4.1 tzlocal==4.1

View File

@@ -6,7 +6,7 @@ export function GetList(query: UserPageQuery) {
return request({ return request({
url: apiPrefix, url: apiPrefix,
method: 'get', method: 'get',
data: query, params: query,
}); });
} }
export function GetObj(id: InfoReq) { export function GetObj(id: InfoReq) {

View File

@@ -6,7 +6,7 @@ export function GetList(query: UserPageQuery) {
return request({ return request({
url: apiPrefix, url: apiPrefix,
method: 'get', method: 'get',
data: query, params: query,
}); });
} }
export function GetObj(id: InfoReq) { export function GetObj(id: InfoReq) {

View File

@@ -6,7 +6,7 @@ export function GetList(query: UserPageQuery) {
return request({ return request({
url: apiPrefix, url: apiPrefix,
method: 'get', method: 'get',
data: query, params: query,
}); });
} }
export function GetObj(id: InfoReq) { export function GetObj(id: InfoReq) {