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}