Skip to main content

yggdrasil/models/
log.rs

1//! 运行日志查看器的共享 DTO(server / wasm 双目标)。
2//!
3//! `LogEntry` 同时用于历史查询(`get_logs` 分页)与 SSE 实时事件
4//! (`/api/logs/stream` 的 `log` 事件负载;实时事件尚未落库,`id` 恒为 0)。
5
6use chrono::{DateTime, Utc};
7use serde::{Deserialize, Serialize};
8
9/// 默认日志保留天数(天)。
10pub const DEFAULT_LOGS_RETENTION_DAYS: i32 = 7;
11/// 默认日志最大行数:超出后按 id 从新到旧裁剪。
12pub const DEFAULT_LOGS_MAX_ROWS: i32 = 100_000;
13/// 保留天数下限(天)。
14#[cfg(feature = "server")]
15pub const MIN_LOGS_RETENTION_DAYS: i32 = 1;
16/// 保留天数上限(天)。防止误填超大值导致永不清理。
17#[cfg(feature = "server")]
18pub const MAX_LOGS_RETENTION_DAYS: i32 = 90;
19/// 最大行数下限。防止误填过小值把日志表裁空。
20#[cfg(feature = "server")]
21pub const MIN_LOGS_MAX_ROWS: i32 = 1_000;
22/// 最大行数上限。防止误填超大值导致表无限增长。
23#[cfg(feature = "server")]
24pub const MAX_LOGS_MAX_ROWS: i32 = 1_000_000;
25
26/// 单条日志记录。
27#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
28pub struct LogEntry {
29    /// 数据库主键(按 id 游标分页)。SSE 实时事件尚未落库,恒为 0。
30    pub id: i64,
31    /// 事件捕获时刻(UTC)。
32    pub ts: DateTime<Utc>,
33    /// 级别大写:ERROR / WARN / INFO / DEBUG / TRACE。
34    pub level: String,
35    /// tracing target(模块路径)。
36    pub target: String,
37    /// 消息文本(含追加的结构化字段,截断至 4KB)。
38    pub message: String,
39}
40
41/// `get_logs` 的一页结果(按 id DESC 游标分页)。
42#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
43pub struct LogsPage {
44    /// 本页条目(id 降序,最新在前)。
45    pub entries: Vec<LogEntry>,
46    /// 下一页游标(本页最后一条的 id);None 表示没有更多。
47    pub next_cursor: Option<i64>,
48    /// 进程启动以来因管道满 / 写库失败被丢弃的日志条数。
49    pub dropped: u64,
50}
51
52/// 日志查看器配置(settings 表 `logs_retention_days` / `logs_max_rows` 键)。
53#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
54pub struct LogSettings {
55    /// 日志保留天数,超过后被后台任务删除。
56    pub retention_days: i32,
57    /// 日志表最大行数,超出后从新到旧裁剪。
58    pub max_rows: i32,
59}
60
61impl Default for LogSettings {
62    fn default() -> Self {
63        Self {
64            retention_days: DEFAULT_LOGS_RETENTION_DAYS,
65            max_rows: DEFAULT_LOGS_MAX_ROWS,
66        }
67    }
68}
69
70impl LogSettings {
71    /// 将保留天数钳制到合法范围 [MIN, MAX]。
72    #[cfg(feature = "server")]
73    pub fn clamp_retention(days: i32) -> i32 {
74        days.clamp(MIN_LOGS_RETENTION_DAYS, MAX_LOGS_RETENTION_DAYS)
75    }
76
77    /// 将最大行数钳制到合法范围 [MIN, MAX]。
78    #[cfg(feature = "server")]
79    pub fn clamp_max_rows(rows: i32) -> i32 {
80        rows.clamp(MIN_LOGS_MAX_ROWS, MAX_LOGS_MAX_ROWS)
81    }
82}