优化日志与启动调试脚本
This commit is contained in:
@@ -40,9 +40,15 @@ YYB_WORKER_IMAGE="${YYB_WORKER_IMAGE:-douyu-yyb-worker:local}"
|
||||
DEV_YYB_WORKER_URL="${DEV_YYB_WORKER_URL:-http://127.0.0.1:${YYB_WORKER_PORT}}"
|
||||
YYB_WORKER_CONTAINER="${YYB_WORKER_CONTAINER:-douyu-yyb-worker-dev}"
|
||||
YYB_WORKER_DATA_DIR="${YYB_WORKER_DATA_DIR:-$ROOT_DIR/data/yyb-worker-dev}"
|
||||
LOG_DIR="$ROOT_DIR/logs"
|
||||
LOG_DATE="$(date +%Y-%m-%d)"
|
||||
BACKEND_LOG="$LOG_DIR/backend-$LOG_DATE.log"
|
||||
FRONTEND_LOG="$LOG_DIR/frontend-$LOG_DATE.log"
|
||||
WORKER_LOG="$LOG_DIR/yyb-worker-$LOG_DATE.log"
|
||||
|
||||
BACKEND_PID=""
|
||||
FRONTEND_PID=""
|
||||
WORKER_LOG_PID=""
|
||||
WORKER_STARTED_BY_DEV=false
|
||||
|
||||
stop_tree() {
|
||||
@@ -62,6 +68,7 @@ cleanup() {
|
||||
trap - EXIT INT TERM
|
||||
stop_tree "$FRONTEND_PID"
|
||||
stop_tree "$BACKEND_PID"
|
||||
stop_tree "$WORKER_LOG_PID"
|
||||
if [ "$WORKER_STARTED_BY_DEV" = true ]; then
|
||||
docker stop "$YYB_WORKER_CONTAINER" >/dev/null 2>&1 || true
|
||||
fi
|
||||
@@ -130,7 +137,7 @@ fi
|
||||
BACKEND_PROXY_HOST="${BACKEND_PROXY_HOST:-$(detect_backend_proxy_host)}"
|
||||
BACKEND_PROXY_TARGET="${VITE_BACKEND_TARGET:-http://${BACKEND_PROXY_HOST}:${BACKEND_PORT}}"
|
||||
|
||||
mkdir -p data logs
|
||||
mkdir -p data "$LOG_DIR"
|
||||
mkdir -p "$YYB_WORKER_DATA_DIR"
|
||||
|
||||
trap cleanup EXIT INT TERM
|
||||
@@ -172,7 +179,14 @@ start_yyb_worker() {
|
||||
done
|
||||
}
|
||||
|
||||
stream_yyb_worker_logs() {
|
||||
# docker logs 默认只输出到终端;持续转存后保留 Worker 的异常和协议脚本输出。
|
||||
(docker logs --tail 100 --follow "$YYB_WORKER_CONTAINER" 2>&1 | tee -a "$WORKER_LOG") &
|
||||
WORKER_LOG_PID=$!
|
||||
}
|
||||
|
||||
start_yyb_worker
|
||||
stream_yyb_worker_logs
|
||||
|
||||
echo "正在启动本地 MySQL..."
|
||||
MYSQL_IMAGE="$MYSQL_IMAGE" \
|
||||
@@ -203,35 +217,32 @@ echo " 前端: http://localhost:${FRONTEND_PORT}"
|
||||
echo " API 代理: ${BACKEND_PROXY_TARGET}"
|
||||
echo " MySQL: ${DB_HOST}:${DB_PORT}/${DB_NAME}"
|
||||
echo " YYB Worker: ${DEV_YYB_WORKER_URL}"
|
||||
echo " 后端日志: ${BACKEND_LOG}"
|
||||
echo " 前端日志: ${FRONTEND_LOG}"
|
||||
echo " Worker 日志: ${WORKER_LOG}"
|
||||
echo " 退出: Ctrl+C"
|
||||
echo "=============================="
|
||||
echo ""
|
||||
|
||||
DB_HOST="$DB_HOST" \
|
||||
DB_PORT="$DB_PORT" \
|
||||
DB_NAME="$DB_NAME" \
|
||||
DB_USER="$DB_USER" \
|
||||
DB_PASSWORD="$DB_PASSWORD" \
|
||||
DB_POOL_SIZE="$DB_POOL_SIZE" \
|
||||
DB_MAX_OVERFLOW="$DB_MAX_OVERFLOW" \
|
||||
DB_POOL_TIMEOUT="$DB_POOL_TIMEOUT" \
|
||||
DB_POOL_RECYCLE="$DB_POOL_RECYCLE" \
|
||||
YYB_WORKER_URL="$DEV_YYB_WORKER_URL" \
|
||||
YYB_WORKER_KEY="$YYB_WORKER_KEY" \
|
||||
LOG_LEVEL="$LOG_LEVEL" \
|
||||
uv run uvicorn web.backend.main:app \
|
||||
--host "$BACKEND_HOST" \
|
||||
--port "$BACKEND_PORT" \
|
||||
--reload \
|
||||
--reload-dir core \
|
||||
--reload-dir utils \
|
||||
--reload-dir web/backend &
|
||||
(
|
||||
export DB_HOST DB_PORT DB_NAME DB_USER DB_PASSWORD
|
||||
export DB_POOL_SIZE DB_MAX_OVERFLOW DB_POOL_TIMEOUT DB_POOL_RECYCLE
|
||||
export YYB_WORKER_KEY LOG_LEVEL
|
||||
export YYB_WORKER_URL="$DEV_YYB_WORKER_URL"
|
||||
uv run uvicorn web.backend.main:app \
|
||||
--host "$BACKEND_HOST" \
|
||||
--port "$BACKEND_PORT" \
|
||||
--reload \
|
||||
--reload-dir core \
|
||||
--reload-dir utils \
|
||||
--reload-dir web/backend 2>&1 | tee -a "$BACKEND_LOG"
|
||||
) &
|
||||
BACKEND_PID=$!
|
||||
|
||||
(
|
||||
cd web/frontend
|
||||
VITE_BACKEND_TARGET="$BACKEND_PROXY_TARGET" \
|
||||
npm run dev -- --host "$FRONTEND_HOST" --port "$FRONTEND_PORT"
|
||||
npm run dev -- --host "$FRONTEND_HOST" --port "$FRONTEND_PORT" 2>&1 | tee -a "$FRONTEND_LOG"
|
||||
) &
|
||||
FRONTEND_PID=$!
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
from datetime import date
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
from pathlib import Path
|
||||
|
||||
from loguru import logger
|
||||
@@ -24,6 +26,30 @@ def _should_rotate(message, file):
|
||||
return False
|
||||
|
||||
|
||||
def _configure_standard_logging(level: str, log_dir: Path) -> None:
|
||||
"""将 Uvicorn/FastAPI 的标准日志同步到控制台和文件。"""
|
||||
log_level = getattr(logging, level.upper(), logging.INFO)
|
||||
formatter = logging.Formatter(
|
||||
"%(asctime)s | %(levelname)-8s | %(name)s | %(message)s"
|
||||
)
|
||||
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
console_handler.setLevel(log_level)
|
||||
console_handler.setFormatter(formatter)
|
||||
|
||||
file_handler = TimedRotatingFileHandler(
|
||||
log_dir / "server.log", when="midnight", backupCount=7, encoding="utf-8"
|
||||
)
|
||||
file_handler.setLevel(log_level)
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
for name in ("uvicorn", "uvicorn.error", "uvicorn.access", "fastapi", "starlette"):
|
||||
standard_logger = logging.getLogger(name)
|
||||
standard_logger.handlers = [console_handler, file_handler]
|
||||
standard_logger.setLevel(log_level)
|
||||
standard_logger.propagate = False
|
||||
|
||||
|
||||
def setup_logger(level: str = "INFO", log_dir: str = None, log_file: str = None) -> None:
|
||||
"""
|
||||
配置日志
|
||||
@@ -52,6 +78,7 @@ def setup_logger(level: str = "INFO", log_dir: str = None, log_file: str = None)
|
||||
# 新接口:按目录 + 日期命名
|
||||
dir_path = Path(log_dir)
|
||||
dir_path.mkdir(parents=True, exist_ok=True)
|
||||
_configure_standard_logging(level, dir_path)
|
||||
file_path = str(dir_path / "app-{time:YYYY-MM-DD}.log")
|
||||
elif log_file:
|
||||
# 兼容旧接口
|
||||
|
||||
Reference in New Issue
Block a user