cargowatch_core/event.rs
1//! Shared event model for runners, detectors, and persistence.
2
3use std::path::PathBuf;
4
5use serde::{Deserialize, Serialize};
6use time::OffsetDateTime;
7
8/// Whether a session is launched by CargoWatch or passively detected.
9#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
10pub enum SessionMode {
11 /// CargoWatch launched and supervised the process.
12 Managed,
13 /// CargoWatch detected an existing process on the machine.
14 Detected,
15}
16
17/// Lifecycle status for a session.
18#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
19pub enum SessionStatus {
20 /// The process is still running.
21 Running,
22 /// The process finished successfully.
23 Succeeded,
24 /// The process finished with a non-zero exit code.
25 Failed,
26 /// The process was cancelled by the user.
27 Cancelled,
28 /// A detected external process disappeared.
29 Lost,
30}
31
32/// Output stream classification.
33#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
34pub enum OutputStream {
35 /// Standard output.
36 Stdout,
37 /// Standard error.
38 Stderr,
39 /// Synthetic system messages created by CargoWatch.
40 System,
41}
42
43/// Severity level used for diagnostics and filtered logs.
44#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
45pub enum Severity {
46 /// Compiler or build error.
47 Error,
48 /// Compiler warning.
49 Warning,
50 /// Additional note.
51 Note,
52 /// Suggested remediation or tip.
53 Help,
54 /// Informational message.
55 Info,
56 /// Positive completion or success status.
57 Success,
58}
59
60/// Session metadata.
61#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
62pub struct SessionInfo {
63 /// Stable session identifier.
64 pub session_id: String,
65 /// Whether this is managed or detected.
66 pub mode: SessionMode,
67 /// Human-friendly title shown in the UI.
68 pub title: String,
69 /// Command line tokens.
70 pub command: Vec<String>,
71 /// Current working directory.
72 pub cwd: PathBuf,
73 /// Best-effort workspace root.
74 pub workspace_root: Option<PathBuf>,
75 /// Start timestamp.
76 pub started_at: OffsetDateTime,
77 /// Current status.
78 pub status: SessionStatus,
79 /// External process id, if one exists.
80 pub external_pid: Option<u32>,
81 /// Best-effort classification for the detected or managed command.
82 pub classification: Option<DetectedProcessClass>,
83}
84
85/// A raw or rendered output line.
86#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
87pub struct LogEntry {
88 /// Monotonic line sequence per session.
89 pub sequence: u64,
90 /// Timestamp when CargoWatch observed the line.
91 pub timestamp: OffsetDateTime,
92 /// Source stream.
93 pub stream: OutputStream,
94 /// Display-ready text.
95 pub text: String,
96 /// Original raw text, when it differs from display text.
97 pub raw: Option<String>,
98 /// Optional inferred severity.
99 pub severity: Option<Severity>,
100}
101
102/// A compiler or build diagnostic.
103#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
104pub struct DiagnosticRecord {
105 /// Unique diagnostic fingerprint within the session.
106 pub id: String,
107 /// Time observed.
108 pub timestamp: OffsetDateTime,
109 /// Diagnostic severity.
110 pub severity: Severity,
111 /// Main message.
112 pub message: String,
113 /// ANSI-rendered message when available.
114 pub rendered: Option<String>,
115 /// Rust diagnostic code, when present.
116 pub code: Option<String>,
117 /// File path for the primary span.
118 pub file: Option<PathBuf>,
119 /// Line for the primary span.
120 pub line: Option<u32>,
121 /// Column for the primary span.
122 pub column: Option<u32>,
123 /// Related target name.
124 pub target: Option<String>,
125 /// Related package id.
126 pub package_id: Option<String>,
127}
128
129/// A compiled or otherwise produced build artifact.
130#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
131pub struct ArtifactRecord {
132 /// Monotonic event sequence within the session.
133 pub sequence: u64,
134 /// Time observed.
135 pub timestamp: OffsetDateTime,
136 /// Package id associated with the artifact.
137 pub package_id: Option<String>,
138 /// Target name.
139 pub target: Option<String>,
140 /// Generated output files.
141 pub filenames: Vec<PathBuf>,
142 /// Generated executable path, if any.
143 pub executable: Option<PathBuf>,
144 /// Whether the build reused a cached artifact.
145 pub fresh: bool,
146}
147
148/// Summary counts for diagnostics.
149#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
150pub struct SummaryCounts {
151 /// Error count.
152 pub errors: u32,
153 /// Warning count.
154 pub warnings: u32,
155 /// Note count.
156 pub notes: u32,
157 /// Help count.
158 pub help: u32,
159 /// Informational line count.
160 pub info: u32,
161}
162
163impl SummaryCounts {
164 /// Increment counts for the provided severity.
165 pub fn observe(&mut self, severity: Severity) {
166 match severity {
167 Severity::Error => self.errors += 1,
168 Severity::Warning => self.warnings += 1,
169 Severity::Note => self.notes += 1,
170 Severity::Help => self.help += 1,
171 Severity::Info | Severity::Success => self.info += 1,
172 }
173 }
174}
175
176/// Classification of a Rust-related process.
177#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
178pub enum DetectedProcessClass {
179 /// `cargo build`
180 CargoBuild,
181 /// `cargo check`
182 CargoCheck,
183 /// `cargo test`
184 CargoTest,
185 /// `cargo clippy`
186 CargoClippy,
187 /// `cargo doc`
188 CargoDoc,
189 /// `rustc`
190 RustcCompile,
191 /// `rustdoc`
192 Rustdoc,
193 /// Anything else in the Rust toolchain family.
194 UnknownRustProcess,
195}
196
197impl DetectedProcessClass {
198 /// Display-friendly label.
199 pub fn label(self) -> &'static str {
200 match self {
201 Self::CargoBuild => "cargo build",
202 Self::CargoCheck => "cargo check",
203 Self::CargoTest => "cargo test",
204 Self::CargoClippy => "cargo clippy",
205 Self::CargoDoc => "cargo doc",
206 Self::RustcCompile => "rustc compile",
207 Self::Rustdoc => "rustdoc",
208 Self::UnknownRustProcess => "rust process",
209 }
210 }
211}
212
213/// Snapshot of a detected external process.
214#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
215pub struct DetectedProcess {
216 /// Stable session identifier derived from process identity.
217 pub session_id: String,
218 /// Operating system pid.
219 pub pid: u32,
220 /// Executable or process name.
221 pub process_name: String,
222 /// Full command line.
223 pub command: Vec<String>,
224 /// Best-effort current working directory.
225 pub cwd: Option<PathBuf>,
226 /// Best-effort workspace root.
227 pub workspace_root: Option<PathBuf>,
228 /// Inferred process class.
229 pub classification: DetectedProcessClass,
230 /// Process start time.
231 pub started_at: OffsetDateTime,
232 /// Most recent observation time.
233 pub last_seen_at: OffsetDateTime,
234 /// Elapsed runtime in milliseconds.
235 pub elapsed_ms: i64,
236}
237
238/// Completion payload for a finished session.
239#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
240pub struct SessionFinished {
241 /// Session identifier.
242 pub session_id: String,
243 /// End timestamp.
244 pub finished_at: OffsetDateTime,
245 /// Final session status.
246 pub status: SessionStatus,
247 /// Process exit code.
248 pub exit_code: Option<i32>,
249 /// Duration in milliseconds.
250 pub duration_ms: i64,
251 /// Final summary.
252 pub summary: SummaryCounts,
253}
254
255/// Unified event stream emitted by the app's runtime services.
256#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
257pub enum SessionEvent {
258 /// Managed or detected session created.
259 SessionStarted(SessionInfo),
260 /// Output line observed.
261 OutputLine {
262 /// Session receiving the log entry.
263 session_id: String,
264 /// Observed output line.
265 entry: LogEntry,
266 },
267 /// Structured diagnostic observed.
268 Diagnostic {
269 /// Session receiving the diagnostic.
270 session_id: String,
271 /// Structured diagnostic payload.
272 diagnostic: DiagnosticRecord,
273 },
274 /// Artifact built.
275 ArtifactBuilt {
276 /// Session receiving the artifact event.
277 session_id: String,
278 /// Produced artifact metadata.
279 artifact: ArtifactRecord,
280 },
281 /// Session finished.
282 SessionFinished(SessionFinished),
283 /// External process first observed.
284 ProcessDetected(DetectedProcess),
285 /// External process changed status.
286 ProcessUpdated(DetectedProcess),
287 /// External process vanished.
288 ProcessGone {
289 /// Session id associated with the process.
290 session_id: String,
291 /// Process id.
292 pid: u32,
293 /// Observation time.
294 observed_at: OffsetDateTime,
295 },
296}