#
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}