cargo/util/log_message.rs
1//! Messages for logging.
2
3use std::io::Write;
4use std::path::PathBuf;
5
6use cargo_util_schemas::core::PackageIdSpec;
7use jiff::Timestamp;
8use serde::Serialize;
9
10use crate::core::compiler::CompileMode;
11use crate::core::compiler::fingerprint::DirtyReason;
12
13/// A log message.
14///
15/// Each variant represents a different type of event.
16#[derive(Serialize)]
17#[serde(tag = "reason", rename_all = "kebab-case")]
18pub enum LogMessage {
19 /// Emitted when a build starts.
20 BuildStarted {
21 /// Current working directory.
22 cwd: PathBuf,
23 /// Host triple.
24 host: String,
25 /// Number of parallel jobs.
26 jobs: u32,
27 /// Build profile name (e.g., "dev", "release").
28 profile: String,
29 /// The rustc version (`1.23.4-beta.2`).
30 rustc_version: String,
31 /// The rustc verbose version information (the output of `rustc -vV`).
32 rustc_version_verbose: String,
33 /// Target directory for build artifacts.
34 target_dir: PathBuf,
35 /// Workspace root directory.
36 workspace_root: PathBuf,
37 },
38 /// Emitted when a compilation unit starts.
39 UnitStarted {
40 /// Package ID specification.
41 package_id: PackageIdSpec,
42 /// Cargo target (lib, bin, example, etc.).
43 target: Target,
44 /// The compilation action this unit is for (check, build, test, etc.).
45 mode: CompileMode,
46 /// Unit index for compact reference in subsequent events.
47 index: u64,
48 /// Seconds elapsed from build start.
49 elapsed: f64,
50 },
51 /// Emitted when a section (e.g., rmeta, link) of the compilation unit finishes.
52 UnitRmetaFinished {
53 /// Unit index from the associated unit-started event.
54 index: u64,
55 /// Seconds elapsed from build start.
56 elapsed: f64,
57 /// Unit indices that were unblocked by this rmeta completion.
58 #[serde(skip_serializing_if = "Vec::is_empty")]
59 unblocked: Vec<u64>,
60 },
61 /// Emitted when a section (e.g., rmeta, link) of the compilation unit starts.
62 ///
63 /// Requires `-Zsection-timings` to be enabled.
64 UnitSectionStarted {
65 /// Unit index from the associated unit-started event.
66 index: u64,
67 /// Seconds elapsed from build start.
68 elapsed: f64,
69 /// Section name from rustc's `-Zjson=timings` (e.g., "codegen", "link").
70 section: String,
71 },
72 /// Emitted when a section (e.g., rmeta, link) of the compilation unit finishes.
73 ///
74 /// Requires `-Zsection-timings` to be enabled.
75 UnitSectionFinished {
76 /// Unit index from the associated unit-started event.
77 index: u64,
78 /// Seconds elapsed from build start.
79 elapsed: f64,
80 /// Section name from rustc's `-Zjson=timings` (e.g., "codegen", "link").
81 section: String,
82 },
83 /// Emitted when a compilation unit finishes.
84 UnitFinished {
85 /// Unit index from the associated unit-started event.
86 index: u64,
87 /// Seconds elapsed from build start.
88 elapsed: f64,
89 /// Unit indices that were unblocked by this completion.
90 #[serde(skip_serializing_if = "Vec::is_empty")]
91 unblocked: Vec<u64>,
92 },
93 /// Emitted when a unit needs to be rebuilt.
94 Rebuild {
95 /// Package ID specification.
96 package_id: PackageIdSpec,
97 /// Cargo target (lib, bin, example, etc.).
98 target: Target,
99 /// The compilation action this unit is for (check, build, test, etc.).
100 mode: CompileMode,
101 /// Reason why the unit is dirty and needs rebuilding.
102 cause: DirtyReason,
103 },
104}
105
106/// Cargo target information.
107#[derive(Serialize)]
108pub struct Target {
109 /// Target name.
110 name: String,
111 /// Target kind (lib, bin, test, bench, example, build-script).
112 kind: &'static str,
113}
114
115impl From<&crate::core::Target> for Target {
116 fn from(target: &crate::core::Target) -> Self {
117 use crate::core::TargetKind;
118 Self {
119 name: target.name().to_string(),
120 kind: match target.kind() {
121 TargetKind::Lib(..) => "lib",
122 TargetKind::Bin => "bin",
123 TargetKind::Test => "test",
124 TargetKind::Bench => "bench",
125 TargetKind::ExampleLib(..) | TargetKind::ExampleBin => "example",
126 TargetKind::CustomBuild => "build-script",
127 },
128 }
129 }
130}
131
132impl LogMessage {
133 /// Serializes this message as a JSON log line directly to the writer.
134 pub fn write_json_log<W: Write>(&self, writer: &mut W, run_id: &str) -> std::io::Result<()> {
135 #[derive(Serialize)]
136 struct LogEntry<'a> {
137 run_id: &'a str,
138 timestamp: Timestamp,
139 #[serde(flatten)]
140 msg: &'a LogMessage,
141 }
142
143 let entry = LogEntry {
144 run_id,
145 timestamp: Timestamp::now(),
146 msg: self,
147 };
148
149 serde_json::to_writer(&mut *writer, &entry)?;
150 writer.write_all(b"\n")?;
151 Ok(())
152 }
153}