* wip * wip: basic telemetry * fix merge * keep errors for telemetry * fix upload when queued events are empty * add per session id and keep track of build timing * keep track of what commands are run * capture panics * keep track of panics * better path stripping * better tracing error telemetry * only sync every week and check settings before sending any telemetry * keep track of the args passed to commands * anonymize commands * more error tolerant * wip * wip * wip * merge cnflict * other merg conflict * migrate everything from telemetry to logging * update docs * wip... about to merge trace controller * lil bit more refactor to clean up tracer * more performant log writer * cleanup ci detecting * wire up to posthog * re-uploads work * yoink out the anon from each file * cleanup sig * lil bit cleaner * dont write empty files * wip log handler * fmt * cleanup logging of backtraces * add proper backtrace support * use stable reporter * adhere to posthog format * fix stacktraces * use anyhow for capturing backtraces * I think we're done? * cleanup logging * properly collect! * move out keycode handling * she works * typo * add extra fields * fix cargo doc --------- Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
188 lines
5.7 KiB
Rust
188 lines
5.7 KiB
Rust
//! Report progress about the build to the user. We use channels to report progress back to the CLI.
|
|
|
|
use super::BuildMode;
|
|
use crate::{BuildArtifacts, BuildStage, Error, TraceSrc};
|
|
use cargo_metadata::diagnostic::Diagnostic;
|
|
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::{path::PathBuf, process::ExitStatus};
|
|
|
|
/// The context of the build process. While the BuildRequest is a "plan" for the build, the BuildContext
|
|
/// provides some dynamic configuration that is only known at runtime. For example, the Progress channel
|
|
/// and the BuildMode can change while serving.
|
|
///
|
|
/// The structure of this is roughly taken from cargo itself which uses a similar pattern.
|
|
#[derive(Debug, Clone)]
|
|
pub struct BuildContext {
|
|
pub tx: ProgressTx,
|
|
pub mode: BuildMode,
|
|
}
|
|
|
|
pub type ProgressTx = UnboundedSender<BuilderUpdate>;
|
|
pub type ProgressRx = UnboundedReceiver<BuilderUpdate>;
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
|
pub struct BuildId(pub(crate) usize);
|
|
impl BuildId {
|
|
pub const CLIENT: Self = Self(0);
|
|
pub const SERVER: Self = Self(1);
|
|
}
|
|
|
|
#[allow(clippy::large_enum_variant)]
|
|
pub enum BuilderUpdate {
|
|
Progress {
|
|
stage: BuildStage,
|
|
},
|
|
|
|
CompilerMessage {
|
|
message: Diagnostic,
|
|
},
|
|
|
|
/// The build completed successfully and the artifacts are ready. The artifacts are dependent on
|
|
/// the build mode (fat vs thin vs base).
|
|
BuildReady {
|
|
bundle: BuildArtifacts,
|
|
},
|
|
|
|
/// The build failed. This might be because of a compilation error, or an error internal to DX.
|
|
BuildFailed {
|
|
err: Error,
|
|
},
|
|
|
|
/// A running process has received a stdout.
|
|
/// May or may not be a complete line - do not treat it as a line. It will include a line if it is a complete line.
|
|
///
|
|
/// We will poll lines and any content in a 50ms interval
|
|
StdoutReceived {
|
|
msg: String,
|
|
},
|
|
|
|
/// A running process has received a stderr.
|
|
/// May or may not be a complete line - do not treat it as a line. It will include a line if it is a complete line.
|
|
///
|
|
/// We will poll lines and any content in a 50ms interval
|
|
StderrReceived {
|
|
msg: String,
|
|
},
|
|
|
|
/// The running app (DUT) has exited and is no longer running.
|
|
ProcessExited {
|
|
status: ExitStatus,
|
|
},
|
|
|
|
/// Waiting for the process failed. This might be because it's hung or being debugged.
|
|
/// This is not the same as the process exiting, so it should just be logged but not treated as an error.
|
|
ProcessWaitFailed {
|
|
err: std::io::Error,
|
|
},
|
|
}
|
|
|
|
impl BuildContext {
|
|
pub(crate) fn status_wasm_bindgen_start(&self) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::RunningBindgen,
|
|
});
|
|
}
|
|
|
|
pub(crate) fn status_splitting_bundle(&self) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::SplittingBundle,
|
|
});
|
|
}
|
|
|
|
pub(crate) fn status_start_bundle(&self) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::Bundling,
|
|
});
|
|
}
|
|
|
|
pub(crate) fn status_running_gradle(&self) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::RunningGradle,
|
|
})
|
|
}
|
|
|
|
pub(crate) fn status_build_diagnostic(&self, message: Diagnostic) {
|
|
_ = self
|
|
.tx
|
|
.unbounded_send(BuilderUpdate::CompilerMessage { message });
|
|
}
|
|
|
|
pub(crate) fn status_build_error(&self, line: String) {
|
|
tracing::warn!(dx_src = ?TraceSrc::Cargo, "{line}");
|
|
}
|
|
|
|
pub(crate) fn status_build_message(&self, line: String) {
|
|
tracing::trace!(dx_src = ?TraceSrc::Cargo, "{line}");
|
|
}
|
|
|
|
pub(crate) fn status_build_progress(&self, count: usize, total: usize, name: String) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::Compiling {
|
|
current: count,
|
|
total,
|
|
krate: name,
|
|
},
|
|
});
|
|
}
|
|
|
|
pub(crate) fn status_starting_build(&self, crate_count: usize) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::Starting {
|
|
patch: matches!(self.mode, BuildMode::Thin { .. }),
|
|
crate_count,
|
|
},
|
|
});
|
|
}
|
|
|
|
pub(crate) fn status_starting_link(&self) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::Linking,
|
|
});
|
|
}
|
|
|
|
pub(crate) fn status_copied_asset(
|
|
progress: &UnboundedSender<BuilderUpdate>,
|
|
current: usize,
|
|
total: usize,
|
|
path: PathBuf,
|
|
) {
|
|
_ = progress.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::CopyingAssets {
|
|
current,
|
|
total,
|
|
path,
|
|
},
|
|
});
|
|
}
|
|
|
|
pub(crate) fn status_optimizing_wasm(&self) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::OptimizingWasm,
|
|
});
|
|
}
|
|
|
|
pub(crate) fn status_hotpatching(&self) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::Hotpatching,
|
|
});
|
|
}
|
|
|
|
pub(crate) fn status_installing_tooling(&self) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::InstallingTooling,
|
|
});
|
|
}
|
|
|
|
pub(crate) fn status_compressing_assets(&self) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::CompressingAssets,
|
|
});
|
|
}
|
|
pub(crate) fn status_extracting_assets(&self) {
|
|
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
|
|
stage: BuildStage::ExtractingAssets,
|
|
});
|
|
}
|
|
}
|