Compress minidumps (#37797)

Julia Ryan created

@notpeter this should fix that issue you were seeing where a generated
minidump was too big to upload with the sentry api.

Release Notes:

- N/A

Change summary

Cargo.lock                    |  1 +
crates/crashes/Cargo.toml     |  1 +
crates/crashes/src/crashes.rs | 11 +++++++++--
crates/zed/src/reliability.rs |  4 +++-
4 files changed, 14 insertions(+), 3 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -4043,6 +4043,7 @@ dependencies = [
  "smol",
  "system_specs",
  "workspace-hack",
+ "zstd",
 ]
 
 [[package]]

crates/crashes/Cargo.toml 🔗

@@ -17,6 +17,7 @@ serde.workspace = true
 serde_json.workspace = true
 system_specs.workspace = true
 workspace-hack.workspace = true
+zstd.workspace = true
 
 [target.'cfg(target_os = "macos")'.dependencies]
 mach2.workspace = true

crates/crashes/src/crashes.rs 🔗

@@ -172,9 +172,16 @@ impl minidumper::ServerHandler for CrashServer {
 
     fn on_minidump_created(&self, result: Result<MinidumpBinary, minidumper::Error>) -> LoopAction {
         let minidump_error = match result {
-            Ok(mut md_bin) => {
+            Ok(MinidumpBinary { mut file, path, .. }) => {
                 use io::Write;
-                let _ = md_bin.file.flush();
+                file.flush().ok();
+                // TODO: clean this up once https://github.com/EmbarkStudios/crash-handling/issues/101 is addressed
+                drop(file);
+                let original_file = File::open(&path).unwrap();
+                let compressed_path = path.with_extension("zstd");
+                let compressed_file = File::create(&compressed_path).unwrap();
+                zstd::stream::copy_encode(original_file, compressed_file, 0).ok();
+                fs::rename(&compressed_path, path).unwrap();
                 None
             }
             Err(e) => Some(format!("{e:?}")),

crates/zed/src/reliability.rs 🔗

@@ -60,7 +60,9 @@ pub fn init_panic_hook(
             .or_else(|| info.payload().downcast_ref::<String>().cloned())
             .unwrap_or_else(|| "Box<Any>".to_string());
 
-        if *release_channel::RELEASE_CHANNEL != ReleaseChannel::Dev {
+        if *release_channel::RELEASE_CHANNEL != ReleaseChannel::Dev
+            || env::var("ZED_GENERATE_MINIDUMPS").is_ok()
+        {
             crashes::handle_panic(payload.clone(), info.location());
         }