add basic crash analytics and very light telemetry to dioxus-cli (#4224)

* 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>
This commit is contained in:
Jonathan KelleyandEvan Almloff authored and GitHub committed 2025-08-08 19:00:00 -07:00
1 parent a610aaefc3
commit e43bf05b69
30 files changed
+1748 -441

No files matched your search

+27 -36
View File
@@ -40,50 +40,41 @@ pub(crate) use workspace::*;
async fn main() {
// The CLI uses dx as a rustcwrapper in some instances (like binary patching)
if rustcwrapper::is_wrapping_rustc() {
return rustcwrapper::run_rustc().await;
return rustcwrapper::run_rustc();
}
// If we're being ran as a linker (likely from ourselves), we want to act as a linker instead.
if let Some(link_args) = link::LinkAction::from_env() {
return link_args.run_link().await;
return link_args.run_link();
}
let args = TraceController::initialize();
let result = match args.action {
Commands::Translate(opts) => opts.translate(),
Commands::New(opts) => opts.create().await,
Commands::Init(opts) => opts.init().await,
Commands::Config(opts) => opts.config().await,
Commands::Autoformat(opts) => opts.autoformat().await,
Commands::Check(opts) => opts.check().await,
Commands::Build(opts) => opts.build().await,
Commands::Serve(opts) => opts.serve().await,
Commands::Bundle(opts) => opts.bundle().await,
Commands::Run(opts) => opts.run().await,
Commands::SelfUpdate(opts) => opts.self_update().await,
Commands::Tools(BuildTools::BuildAssets(opts)) => opts.run().await,
Commands::Doctor(opts) => opts.doctor().await,
};
// Provide a structured output for third party tools that can consume the output of the CLI
match result {
Ok(output) => {
tracing::debug!(json = ?output);
// Run under the tracing collector so we can capture errors/panics.
let result = TraceController::main(|args, tracer| async move {
match args {
Commands::Serve(opts) => opts.serve(&tracer).await,
Commands::Translate(opts) => opts.translate(),
Commands::New(opts) => opts.create().await,
Commands::Init(opts) => opts.init().await,
Commands::Config(opts) => opts.config().await,
Commands::Autoformat(opts) => opts.autoformat().await,
Commands::Check(opts) => opts.check().await,
Commands::Build(opts) => opts.build().await,
Commands::Bundle(opts) => opts.bundle().await,
Commands::Run(opts) => opts.run().await,
Commands::SelfUpdate(opts) => opts.self_update().await,
Commands::Tools(BuildTools::BuildAssets(opts)) => opts.run().await,
Commands::Doctor(opts) => opts.doctor().await,
}
Err(err) => {
tracing::error!(
json = ?StructuredOutput::Error {
message: format!("{err:?}"),
},
);
eprintln!(
"{ERROR_STYLE}Failed{ERROR_STYLE:#}: {}",
crate::error::log_stacktrace(&err, 1),
ERROR_STYLE = crate::styles::ERROR_STYLE,
);
});
// Print the structured output in JSON format for third-party tools to consume.
// Make sure we do this as the last step so you can always `tail -1` it
match result.await {
StructuredOutput::Error { message } => {
tracing::error!(json = ?StructuredOutput::Error { message });
std::process::exit(1);
}
};
output => tracing::debug!(json = ?output),
}
}