feat(trace): add trace_id
This commit is contained in:
5
init.sql
5
init.sql
@@ -23,4 +23,7 @@ CREATE INDEX idx_logs_service_time ON app_logs(service_name, created_at);
|
||||
-- create_next_month.sql
|
||||
-- 这里的日期逻辑需要通过外部脚本(Python/Shell)动态生成 SQL 语句
|
||||
CREATE TABLE IF NOT EXISTS app_logs_2026_01 PARTITION OF app_logs
|
||||
FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');
|
||||
FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');
|
||||
|
||||
ALTER TABLE app_logs ADD COLUMN trace_id VARCHAR(64);
|
||||
CREATE INDEX idx_logs_trace_id ON app_logs(trace_id); -- 加上索引,查问题全靠它
|
||||
16
src/context.rs
Normal file
16
src/context.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
// src/context.rs
|
||||
use tokio::task_local;
|
||||
|
||||
// 定义一个 Tokio 任务局部变量
|
||||
task_local! {
|
||||
pub static TRACE_ID: String;
|
||||
}
|
||||
|
||||
// 辅助函数:设置 TraceID 作用域
|
||||
// 在这个 scope 闭包内运行的所有代码,都能访问到这个 ID
|
||||
pub async fn with_trace_id<F, R>(id: String, f: F) -> R
|
||||
where
|
||||
F: std::future::Future<Output = R>,
|
||||
{
|
||||
TRACE_ID.scope(id, f).await
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
// src/core.rs
|
||||
use crate::context::TRACE_ID;
|
||||
use crate::model::{LogLevel, LogRecord};
|
||||
use crate::outputs::LogOutput;
|
||||
use chrono::Utc;
|
||||
@@ -56,6 +57,8 @@ impl Logger {
|
||||
return;
|
||||
}
|
||||
|
||||
let trace_id = TRACE_ID.try_with(|id| id.clone()).ok();
|
||||
|
||||
// 2. 构造记录
|
||||
let record = LogRecord {
|
||||
service_name: self.service_name.clone(),
|
||||
@@ -63,6 +66,7 @@ impl Logger {
|
||||
level,
|
||||
message,
|
||||
module,
|
||||
trace_id,
|
||||
};
|
||||
|
||||
// 3. 发送 (非阻塞,如果队列满则丢弃,防止拖死业务)
|
||||
|
||||
@@ -4,6 +4,7 @@ pub mod core;
|
||||
pub mod model;
|
||||
pub mod outputs;
|
||||
pub use cleaner::LogCleaner;
|
||||
pub mod context;
|
||||
|
||||
use crate::core::Logger;
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
@@ -34,4 +34,5 @@ pub struct LogRecord {
|
||||
pub level: LogLevel,
|
||||
pub message: String,
|
||||
pub module: String,
|
||||
pub trace_id: Option<String>,
|
||||
}
|
||||
|
||||
@@ -110,10 +110,16 @@ impl LogOutput for FileOutput {
|
||||
return;
|
||||
}
|
||||
|
||||
let trace_part = match &record.trace_id {
|
||||
Some(id) => format!("[{}] ", id),
|
||||
None => "".to_string(),
|
||||
};
|
||||
|
||||
let log_line = format!(
|
||||
"{} [{}] - {}\n",
|
||||
"{} [{}] {}- {}\n",
|
||||
record.timestamp.format("%Y-%m-%d %H:%M:%S%.3f"),
|
||||
record.level,
|
||||
trace_part,
|
||||
record.message
|
||||
);
|
||||
|
||||
|
||||
@@ -85,8 +85,8 @@ impl LogOutput for PostgresOutput {
|
||||
self.ensure_partition_exists(&record.timestamp).await;
|
||||
|
||||
let query = r#"
|
||||
INSERT INTO app_logs (service_name, log_level, message, module, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
INSERT INTO app_logs (service_name, log_level, message, module, created_at, trace_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
"#;
|
||||
|
||||
// 注意:这里的 write 是在后台任务中执行的,就算慢也不会阻塞主业务
|
||||
@@ -98,6 +98,7 @@ impl LogOutput for PostgresOutput {
|
||||
.bind(&record.message)
|
||||
.bind(&record.module)
|
||||
.bind(record.timestamp)
|
||||
.bind(&record.trace_id)
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user