From aef92bca114f012e02a5dc4331a06a4f76121ab5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com>
Date: Sat, 8 Apr 2023 21:27:05 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E5=8F=96=E6=B6=88lo?=
=?UTF-8?q?guru=E6=97=A5=E5=BF=97=EF=BC=8C=E4=BD=BF=E7=94=A8=E7=AE=80?=
=?UTF-8?q?=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 | 92 +++++++++++++---------
backend/dvadmin/utils/log.py | 131 --------------------------------
backend/requirements.txt | 1 -
3 files changed, 57 insertions(+), 167 deletions(-)
delete mode 100644 backend/dvadmin/utils/log.py
diff --git a/backend/application/settings.py b/backend/application/settings.py
index c916894..6946d38 100644
--- a/backend/application/settings.py
+++ b/backend/application/settings.py
@@ -187,78 +187,100 @@ else:
},
}
-
-# ================================================= #
-# ********************* 日志配置 ******************* #
-# ================================================= #
-
-# 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"
+ "django": {
+ "handlers": ["console", "error", "file"],
+ "level": "INFO",
+ "propagate": False,
},
'celery': {
- 'handlers': ['servers'],
+ 'handlers': ["console", "error", "file"],
'propagate': False,
'level': "INFO"
},
'django.db.backends': {
- 'handlers': ['servers'],
+ 'handlers': ["console", "error", "file"],
'propagate': False,
'level': "INFO"
},
'django.request': {
- 'handlers': ['servers'],
+ 'handlers': ["console", "error", "file"],
'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"
},
},
}
-
# ================================================= #
# *************** REST_FRAMEWORK配置 *************** #
# ================================================= #
diff --git a/backend/dvadmin/utils/log.py b/backend/dvadmin/utils/log.py
deleted file mode 100644
index 73618c2..0000000
--- a/backend/dvadmin/utils/log.py
+++ /dev/null
@@ -1,131 +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):
- """
- 自定义反射时间回滚日志记录器
- 缺少命名空间
- """
-
- 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[client_addr]:^18} | {level: <8}| {message}"
- when = when.lower()
- # 2.🎖️需要本地用不同的文件名做为不同日志的筛选器
- logger.configure(
- handlers=[
- dict(sink=sys.stderr, format=format),
- ],
- )
- self.logger_ = logger.bind(sime=filename, client_addr="-")
- 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
- # 设置自定义属性
- details = frame.f_locals.get('details', None)
- msg = self.format(record)
- bind = {}
- record_client = None
- if isinstance(record.args, dict):
- record_client = record.args.get('client_addr') or record.args.get('client')
- elif isinstance(record.args, tuple) and len(record.args) > 0:
- if ":" in str(record.args[0]):
- record_client = record.args[0]
- if msg.split("-") and len(msg.split("-")) == 2:
- msg = f"{msg.split('-')[1].strip(' ')}"
- elif isinstance(record.args[0], tuple) and len(record.args[0]) == 2:
- record_client = f"{record.args[0][0]}:{record.args[0][1]}"
- if msg.split("-") and len(msg.split("-")) == 2:
- msg = f"{msg.split('-')[1].strip(' ')}"
- client = record_client or (details and details.get('client'))
- if client:
- bind["client_addr"] = client
- if is_tenants_mode():
- bind["schema_name"] = connection.tenant.schema_name
- bind["domain_url"] = getattr(connection.tenant, 'domain_url', None)
- self.logger_.opt(depth=depth, exception=record.exc_info, colors=True, lazy=True).bind(**bind).log(level, f"{msg}")
diff --git a/backend/requirements.txt b/backend/requirements.txt
index c8660ac..17727f8 100644
--- a/backend/requirements.txt
+++ b/backend/requirements.txt
@@ -47,4 +47,3 @@ uvicorn==0.21.1
gunicorn==20.1.0
gevent==22.10.2
websockets==10.4
-loguru==0.6.0