Skip to content

FastAPI 环境配置与日志体系

一个应用不能只在本地跑通,还要能在开发、测试、生产等不同环境中安全稳定运行。环境配置和日志体系,就是应用程序的“安全自适应生存法则”:配置让程序适配环境,日志让问题可追踪。

同一套代码通常会运行在多个环境里,比如本地开发、测试服务器和生产服务器。不同环境的数据库地址、密钥、日志级别、调试模式都不一样。

安全性

密码、密钥、数据库地址等敏感信息不能写死在代码里,也不能暴露到仓库中。

环境自适应

一套代码根据环境变量切换配置,减少重复代码和维护成本。

运行可追溯

通过日志记录时间、环境、事件级别和请求上下文,方便快速排查问题。

核心问题可以概括为一句话:应用需要在“开发 / 生产”等不同环境中安全运行。

环境变量分层的作用,是把“代码逻辑”和“运行配置”分开。代码负责业务,配置负责告诉代码当前运行在哪里、连接哪个数据库、使用什么密钥。

识别环境身份

通过环境变量判断当前是开发环境、测试环境还是生产环境。

加载正确配置

根据不同环境加载不同数据库地址、日志级别、调试开关等配置项。

守护隐私安全

敏感信息只走 .env 文件或服务器环境变量,不写死在业务代码中。

常见环境配置可以这样拆:

配置项 开发环境 生产环境
APP_ENV dev prod
DEBUG true false
DATABASE_URL 本地数据库地址 生产数据库地址
SECRET_KEY 本地测试密钥 生产安全密钥
LOG_LEVEL DEBUG INFO / WARNING

FastAPI 项目里可以用 Pydantic Settings 或类似方式读取环境变量。重点不是工具本身,而是让配置集中管理。

app/core/config.py
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
app_env: str = "dev"
debug: bool = True
database_url: str
secret_key: str
log_level: str = "INFO"
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
settings = Settings()

对应 .env 示例:

.env.example
APP_ENV=dev
DEBUG=true
DATABASE_URL=mysql+pymysql://root:password@localhost:3306/fastapi_demo
SECRET_KEY=change-me
LOG_LEVEL=DEBUG

配置读取后,业务代码只使用 settings.database_url 这类变量,不直接写死真实地址和密钥。

日志不是随便 print(),而是要留下能排查问题的关键线索。

日志四大记忆要素:

要素 说明
时间戳 记录精确时间,方便按时间线排查
环境身份 标明开发、测试或生产环境
事件级别 区分 DEBUGINFOWARNINGERROR
上下文 记录请求 ID、接口路径、用户 ID、异常信息等

Loguru 是一个 Python 日志工具,配置简单,适合快速搭建项目日志体系。

开发环境适合同时输出到控制台和文件,方便边调试边查看历史记录。

app/core/logger.py
from loguru import logger
logger.add(
"logs/dev.log",
level="DEBUG",
rotation="10 MB",
retention="7 days",
encoding="utf-8",
)

开发环境可以保留更多调试信息,但也要避免输出密码、密钥等敏感内容。

Loguru 关键特性:

特性 作用
控制台输出 开发时直接查看运行状态
文件输出 保留历史问题线索
日志级别 控制不同环境输出哪些内容
日志轮转 按大小或时间拆分文件
保留策略 自动清理过旧日志,节省资源

如果前面已经做了统一错误处理,可以把日志体系和 request_id 结合起来,让一次请求的链路更完整。

app/core/middleware.py
import time
import uuid
from fastapi import Request
from loguru import logger
async def request_log_middleware(request: Request, call_next):
request_id = str(uuid.uuid4())
request.state.request_id = request_id
start = time.time()
response = await call_next(request)
cost_ms = round((time.time() - start) * 1000, 2)
logger.info(
"request_id={} method={} path={} status={} cost_ms={}",
request_id,
request.method,
request.url.path,
response.status_code,
cost_ms,
)
response.headers["X-Request-ID"] = request_id
return response

这样前端、错误响应和日志里都能看到同一个 request_id

  1. 拆分配置项:确认哪些配置会随环境变化,比如数据库地址、密钥、日志级别。

  2. 建立 .env.example:只保留字段说明和示例值,不放真实敏感信息。

  3. 集中读取配置:通过 Settings 类或配置模块统一读取环境变量。

  4. 配置日志输出:开发环境输出控制台和文件,生产环境以文件为主并开启轮转。

  5. 接入请求日志:在中间件里记录 request_id、路径、状态码和耗时。

  6. 补齐忽略规则:把 .env、真实日志文件、临时文件加入 .gitignore

.gitignore
.env
logs/
*.log
__pycache__/
.venv/

忽略规则的核心,是避免把敏感配置、运行日志、虚拟环境和缓存文件提交到仓库。

prompt.md
# 实现环境变量分层管理和日志体系
1. 环境变量分层:支持开发 / 生产环境;
2. 敏感信息只走环境变量 / 配置层,不写死在业务代码;
3. 建立日志体系:日志文件用于留痕与排障,避免重复和噪音;
4. 日志需要包含时间戳、环境身份、事件级别、请求 ID 和关键上下文;
5. 使用 Loguru,开发环境输出控制台 + 文件,生产环境仅文件输出并按天分割;
6. 补齐 .gitignore,避免提交 .env、logs、虚拟环境和缓存文件。