Skip to main content

pipedash_core/domain/
run_logs.rs

1use chrono::{
2    DateTime,
3    Utc,
4};
5pub use pipedash_plugin_api::{
6    LineMarker,
7    LogAvailability,
8    LogCursor,
9    LogDialect,
10    LogNodeKind,
11    LogRead,
12    LogReadMode,
13    LogSink,
14    ParsedLine,
15    PlainDialect,
16};
17use serde::{
18    Deserialize,
19    Serialize,
20};
21
22use super::pipeline::PipelineStatus;
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct LogNode {
26    pub id: String,
27    pub parent_id: Option<String>,
28    pub kind: LogNodeKind,
29    pub name: String,
30    pub status: PipelineStatus,
31    pub started_at: Option<DateTime<Utc>>,
32    pub finished_at: Option<DateTime<Utc>>,
33    pub log: Option<LogAvailability>,
34    pub web_url: Option<String>,
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
38pub struct RunLogTree {
39    pub nodes: Vec<RunLogNode>,
40    pub default_node_id: Option<String>,
41    pub complete: bool,
42}
43
44#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
45pub struct RunLogNode {
46    pub id: String,
47    pub parent_id: Option<String>,
48    pub kind: LogNodeKind,
49    pub name: String,
50    pub status: PipelineStatus,
51    pub started_at: Option<DateTime<Utc>>,
52    pub finished_at: Option<DateTime<Utc>>,
53    pub duration_seconds: Option<i64>,
54    pub log: Option<LogAvailability>,
55    pub web_url: Option<String>,
56    pub depth: u8,
57    pub navigable: bool,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
61#[serde(tag = "state", rename_all = "snake_case")]
62pub enum RunLogDocument {
63    Ready(LogDocumentMeta),
64    Loading { received_bytes: u64 },
65    Pending,
66    Unavailable { message: String },
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct LogDocumentMeta {
71    pub node_id: String,
72    pub revision: i64,
73    pub complete: bool,
74    pub truncated: bool,
75    pub line_count: u32,
76    pub text_bytes: u64,
77    pub first_timestamp_ms: Option<i64>,
78    pub styles: Vec<LogStyle>,
79    pub sections: Vec<LogSection>,
80    pub error_lines: Vec<u32>,
81    pub warning_lines: Vec<u32>,
82    pub error_total: u32,
83    pub warning_total: u32,
84    pub focus_line: Option<u32>,
85    pub updated_at_ms: i64,
86    pub stable_lines: u32,
87    pub previous_revision: Option<i64>,
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
91#[serde(rename_all = "lowercase")]
92pub enum LogSectionKind {
93    Step,
94    Group,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct LogSection {
99    pub id: u32,
100    pub parent: Option<u32>,
101    pub kind: LogSectionKind,
102    pub node_id: Option<String>,
103    pub title: String,
104    pub status: Option<PipelineStatus>,
105    pub duration_ms: Option<i64>,
106    pub header_line: Option<u32>,
107    pub start_line: u32,
108    pub end_line: u32,
109    pub error_count: u32,
110    pub open: bool,
111}
112
113#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
114pub struct LogStyle {
115    pub fg: Option<AnsiColor>,
116    pub bg: Option<AnsiColor>,
117    pub bold: bool,
118    pub dim: bool,
119    pub italic: bool,
120    pub underline: bool,
121    pub strike: bool,
122}
123
124#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
125#[serde(rename_all = "lowercase")]
126pub enum AnsiColor {
127    Black,
128    Red,
129    Green,
130    Yellow,
131    Blue,
132    Magenta,
133    Cyan,
134    White,
135}
136
137#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
138#[serde(rename_all = "lowercase")]
139#[repr(u8)]
140pub enum LineKind {
141    #[default]
142    Plain = 0,
143    Group = 1,
144    Error = 2,
145    Warning = 3,
146    Notice = 4,
147    Debug = 5,
148    Command = 6,
149}
150
151impl LineKind {
152    pub fn is_plain(&self) -> bool {
153        *self == LineKind::Plain
154    }
155
156    pub fn from_u8(value: u8) -> Option<Self> {
157        Some(match value {
158            0 => LineKind::Plain,
159            1 => LineKind::Group,
160            2 => LineKind::Error,
161            3 => LineKind::Warning,
162            4 => LineKind::Notice,
163            5 => LineKind::Debug,
164            6 => LineKind::Command,
165            _ => return None,
166        })
167    }
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
171pub struct LogLinesPage {
172    pub start: u32,
173    pub lines: Vec<LogLine>,
174}
175
176fn is_zero(value: &u32) -> bool {
177    *value == 0
178}
179
180#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
181pub struct LogLine {
182    pub text: String,
183    #[serde(default, skip_serializing_if = "LineKind::is_plain")]
184    pub kind: LineKind,
185    #[serde(default, skip_serializing_if = "Option::is_none")]
186    pub ts: Option<i64>,
187    #[serde(default, skip_serializing_if = "Vec::is_empty")]
188    pub spans: Vec<(u32, u32, u16)>,
189    #[serde(default, skip_serializing_if = "is_zero")]
190    pub omitted: u32,
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize)]
194pub struct LogSearchQuery {
195    pub text: String,
196    pub regex: bool,
197    pub case_sensitive: bool,
198}
199
200#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
201pub struct LogSearchResult {
202    pub matches: Vec<(u32, u32, u32)>,
203    pub total: u64,
204    pub capped: bool,
205}
206
207#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
208pub struct LogCacheStats {
209    pub bytes: u64,
210    pub runs: u64,
211}