Skip to main content

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}