# 日志系统配置文件
# 支持控制台与文件双输出,并配置日志轮转策略
# 在项目根目录下创建 logging.ini 文件
[loggers]
keys=root,uvicorn,fastapi
[handlers]
keys=consoleHandler,timedFileHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=INFO
handlers=consoleHandler,timedFileHandler
[logger_uvicorn]
level=INFO
handlers=consoleHandler,timedFileHandler
qualname=uvicorn
propagate=0
[logger_fastapi]
level=INFO
handlers=consoleHandler,timedFileHandler
qualname=fastapi
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=INFO
formatter=simpleFormatter
args=(sys.stdout,)
[handler_timedFileHandler]
class=handlers.TimedRotatingFileHandler
level=INFO
formatter=simpleFormatter
args=('logs/app.log', 'midnight', 1, 30, 'utf-8')
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=%Y-%m-%d %H:%M:%S
通过调整 sys.stdout.reconfigure(encoding='utf-8') 与 sys.stdout.reconfigure(encoding='gbk') 的使用,可实现编码切换。若环境默认支持中文输出,则此设置可省略。
以下为应用初始化相关代码:
import logging.config
import os
import sys
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from .database import engine
from .models import Base
from .auth.router import router as auth_router
from .posts.router import router as posts_router
from .exception_handler import register_exception_handlers
# 将应用实例从主文件引入
# 配置标准输出编码以避免中文乱码
# 若运行于 uvicorn 调试模式,建议设为 utf-8;常规启动时根据系统环境选择 gbk 或 utf-8
# if hasattr(sys.stdout, "reconfigure"):
# 使用python启动时,通过设置调试模式与正常模式下的编码为utf-8来避免乱码问题
# sys.stdout.reconfigure(encoding='utf-8')
# 获取项目根路径
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
logs_dir = os.path.join(project_root, 'logs')
# 确保日志存储目录存在,若不存在则创建
if not os.path.exists(logs_dir):
os.makedirs(logs_dir)
print(f"创建日志目录: {logs_dir}")
# 加载自定义日志配置文件 logging.ini
logging_ini_path = os.path.join(project_root, 'logging.ini')
print(f"111尝试加载日志配置文件: {logging_ini_path}")
# 判断配置文件是否存在
if os.path.exists(logging_ini_path):
try:
print("22")
# 显式指定utf-8编码,防止在Windows系统中出现读取配置文件的编码错误
logging.config.fileConfig(logging_ini_path, disable_existing_loggers=False, encoding='utf-8')
print("33成功加载日志配置文件")
except Exception as e:
print(f"44加载日志配置文件失败: {e}")
# 若加载失败,则使用基础的日志配置作为备用方案
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(sys.stdout),
logging.FileHandler(os.path.join(logs_dir, 'app.log'), encoding='utf-8')
]
)
else:
print("未找到日志配置文件,使用备用配置")
# 当配置文件缺失时,启用默认日志设置
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(sys.stdout),
logging.FileHandler(os.path.join(logs_dir, 'app.log'), encoding='utf-8')
]
)
# 初始化日志记录器
logger = logging.getLogger(__name__)
logger.info("应用程序启动")
# 定义异步函数用于创建数据库表结构
async def create_tables():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
# 构建 FastAPI 应用实例
app = FastAPI(
title="FastAPI Application",
description="A full-featured FastAPI application with authentication and CRUD operations",
version="0.1.0"
)
# 注册全局异常处理机制
register_exception_handlers(app)
logger.info("全局异常处理器注册完成")
# 添加跨域资源共享(CORS)中间件以支持前端请求
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 挂载路由模块:认证与文章相关接口
app.include_router(auth_router)
app.include_router(posts_router)
# 应用启动时执行的事件
@app.on_event("startup")
async def startup_event():
logger.info("开始执行启动事件")
await create_tables()
logger.info("启动事件执行完成")
# 应用关闭时触发的操作
@app.on_event("shutdown")
# 定义应用关闭时的执行逻辑
async def shutdown_event():
"""服务终止时触发的操作"""
logger.info("===== 服务关闭 =====")
# 注册根路径接口
@app.get("/")
async def root():
logger.info("访问根端点")
return {"message": "Welcome to the FastAPI Application"}
# 注入HTTP中间件以记录请求日志
@app.middleware("http")
async def log_requests(request: Request, call_next):
logger.info(f"收到请求: {request.method} {request.url}")
try:
response = await call_next(request)
logger.info(f"响应状态: {response.status_code}")
return response
except Exception as e:
logger.error(f"处理请求时发生错误: {e}")
raise