1use client::telemetry;
2use gpui::{App, AppContext as _, Task, Window};
3use human_bytes::human_bytes;
4use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};
5use serde::Serialize;
6use std::{env, fmt::Display};
7use sysinfo::{MemoryRefreshKind, RefreshKind, System};
8
9#[derive(Clone, Debug, Serialize)]
10pub struct SystemSpecs {
11 app_version: String,
12 release_channel: &'static str,
13 os_name: String,
14 os_version: String,
15 memory: u64,
16 architecture: &'static str,
17 commit_sha: Option<String>,
18 gpu_specs: Option<String>,
19}
20
21impl SystemSpecs {
22 pub fn new(window: &mut Window, cx: &mut App) -> Task<Self> {
23 let app_version = AppVersion::global(cx).to_string();
24 let release_channel = ReleaseChannel::global(cx);
25 let os_name = telemetry::os_name();
26 let system = System::new_with_specifics(
27 RefreshKind::new().with_memory(MemoryRefreshKind::everything()),
28 );
29 let memory = system.total_memory();
30 let architecture = env::consts::ARCH;
31 let commit_sha = match release_channel {
32 ReleaseChannel::Dev | ReleaseChannel::Nightly => {
33 AppCommitSha::try_global(cx).map(|sha| sha.0.clone())
34 }
35 _ => None,
36 };
37
38 let gpu_specs = if let Some(specs) = window.gpu_specs() {
39 Some(format!(
40 "{} || {} || {}",
41 specs.device_name, specs.driver_name, specs.driver_info
42 ))
43 } else {
44 None
45 };
46
47 cx.background_spawn(async move {
48 let os_version = telemetry::os_version();
49 SystemSpecs {
50 app_version,
51 release_channel: release_channel.display_name(),
52 os_name,
53 os_version,
54 memory,
55 architecture,
56 commit_sha,
57 gpu_specs,
58 }
59 })
60 }
61}
62
63impl Display for SystemSpecs {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 let os_information = format!("OS: {} {}", self.os_name, self.os_version);
66 let app_version_information = format!(
67 "Zed: v{} ({}) {}",
68 self.app_version,
69 match &self.commit_sha {
70 Some(commit_sha) => format!("{} {}", self.release_channel, commit_sha),
71 None => self.release_channel.to_string(),
72 },
73 if cfg!(debug_assertions) {
74 "(Taylor's Version)"
75 } else {
76 ""
77 },
78 );
79 let system_specs = [
80 app_version_information,
81 os_information,
82 format!("Memory: {}", human_bytes(self.memory as f64)),
83 format!("Architecture: {}", self.architecture),
84 ]
85 .into_iter()
86 .chain(
87 self.gpu_specs
88 .as_ref()
89 .map(|specs| format!("GPU: {}", specs)),
90 )
91 .collect::<Vec<String>>()
92 .join("\n");
93
94 write!(f, "{system_specs}")
95 }
96}