feat: 升级日志系统为 tracing 结构化日志

- 替换 env_logger 为 tracing + tracing-subscriber
- 统一使用 tracing::{debug, error, info, warn} 日志宏
- 消除所有 eprintln!/println 调用
- 添加 JSON 格式日志输出便于 ELK Stack 收集
- 添加文件日志轮转(每天一个新文件 ./logs/rust-backend-{date}.log)
- 日志等级过滤:rust_backend=info, actix_web=info, sqlx=warn
- 更新 IMPROVEMENTS.md 标记 6.1 日志系统两项完成
This commit is contained in:
2026-04-15 10:39:30 +08:00
parent 98ef90b01e
commit 741d6acff1
6 changed files with 154 additions and 220 deletions

View File

@@ -1,5 +1,6 @@
use std::env;
use dotenvy::dotenv;
use tracing;
#[derive(Debug, Clone)]
pub struct Config {
@@ -14,7 +15,7 @@ impl Config {
pub fn load() -> Result<Self, String> {
// 加载.env文件
if let Err(e) = dotenv() {
eprintln!("警告: 无法加载.env文件 - {}", e);
tracing::warn!("无法加载.env文件 - {}", e);
}
Ok(Self {

View File

@@ -1,7 +1,7 @@
use actix_web::middleware::from_fn;
use actix_web::{App, HttpResponse, HttpServer, Responder, delete, get, post, put, web};
use include_dir::{Dir, include_dir};
use log::{debug, error, info, warn};
use tracing::{debug, error, info, warn};
use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod};
use reqwest::Client;
use serde::Deserialize;
@@ -717,11 +717,41 @@ fn create_server_config(
#[actix_web::main]
async fn main() -> std::io::Result<()> {
if let Err(e) = dotenvy::dotenv() {
eprintln!("警告:加载.env文件失败使用系统环境变量: {}", e);
tracing::warn!("加载.env文件失败使用系统环境变量: {}", e);
}
env_logger::init();
info!("logger init successful");
// 初始化文件日志JSON 格式,带轮转)
let log_dir = std::path::Path::new("./logs");
std::fs::create_dir_all(log_dir).ok(); // 确保日志目录存在
let file_appender = tracing_appender::rolling::Builder::new()
.rotation(tracing_appender::rolling::Rotation::DAILY)
.filename_prefix("rust-backend")
.filename_suffix("log")
.build(log_dir)
.expect("无法创建日志文件");
let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
// 保持文件 guard 存活(使用 Box 泄漏)
std::mem::forget(_guard);
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::from_default_env()
.add_directive("rust_backend=info".parse().unwrap())
.add_directive("actix_web=info".parse().unwrap())
.add_directive("sqlx=warn".parse().unwrap()) // SQLx 日志太多,降级
)
.with_target(true)
.with_thread_ids(false) // 生产环境可开启
.with_file(true)
.with_line_number(true)
.with_writer(non_blocking)
.with_ansi(false) // 文件中不使用 ANSI 颜色
.json() // JSON 格式便于 ELK 解析
.init();
info!("日志系统初始化成功JSON格式输出到 ./logs/");
let app_state = match AppState::load() {
Ok(state) => state,