feat(project): init

This commit is contained in:
2026-01-21 14:03:53 +08:00
commit 739234a896
10 changed files with 415 additions and 0 deletions

20
src/outputs/console.rs Normal file
View File

@@ -0,0 +1,20 @@
// src/outputs/console.rs
use super::LogOutput;
use crate::model::LogRecord;
use async_trait::async_trait;
pub struct ConsoleOutput;
#[async_trait]
impl LogOutput for ConsoleOutput {
async fn write(&self, record: &LogRecord) {
// 简单的控制台打印,生产环境可以加上颜色代码
println!(
"[{}] [{}] ({}) - {}",
record.timestamp.format("%Y-%m-%d %H:%M:%S"),
record.level,
record.module,
record.message
);
}
}

12
src/outputs/mod.rs Normal file
View File

@@ -0,0 +1,12 @@
// src/outputs/mod.rs
pub mod console;
pub mod postgres;
use crate::model::LogRecord;
use async_trait::async_trait;
// 定义 Trait要求实现者必须是线程安全的 (Send + Sync)
#[async_trait]
pub trait LogOutput: Send + Sync {
async fn write(&self, record: &LogRecord);
}

39
src/outputs/postgres.rs Normal file
View File

@@ -0,0 +1,39 @@
// src/outputs/postgres.rs
use super::LogOutput;
use crate::model::LogRecord;
use async_trait::async_trait;
use sqlx::PgPool;
pub struct PostgresOutput {
pool: PgPool,
}
impl PostgresOutput {
pub fn new(pool: PgPool) -> Self {
Self { pool }
}
}
#[async_trait]
impl LogOutput for PostgresOutput {
async fn write(&self, record: &LogRecord) {
let query = r#"
INSERT INTO app_logs (log_level, message, module, created_at)
VALUES ($1, $2, $3, $4)
"#;
// 注意:这里的 write 是在后台任务中执行的,就算慢也不会阻塞主业务
// 我们忽略错误,因为如果日志系统挂了,不能让它导致业务逻辑崩溃 (Panic)
// 生产环境可以考虑加一个 fallback 机制(比如降级写文件)
if let Err(e) = sqlx::query(query)
.bind(record.level.to_string())
.bind(&record.message)
.bind(&record.module)
.bind(record.timestamp)
.execute(&self.pool)
.await
{
eprintln!("Failed to write log to PostgreSQL: {}", e);
}
}
}