diff --git a/.gitignore b/.gitignore index 7c4bdc1fb..865aafe8e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ deno.lock .DS_Store .idea .dev +teste-temp/ diff --git a/bin/core/src/monitor/record.rs b/bin/core/src/monitor/record.rs index 3d3eb626c..7d218043e 100644 --- a/bin/core/src/monitor/record.rs +++ b/bin/core/src/monitor/record.rs @@ -20,6 +20,7 @@ pub async fn record_server_stats(ts: i64) { ts, sid: status.id.clone(), cpu_perc: stats.cpu_perc, + cpu_temp: stats.cpu_temp, load_average: stats.load_average.clone(), mem_total_gb: stats.mem_total_gb, mem_used_gb: stats.mem_used_gb, diff --git a/bin/periphery/src/stats.rs b/bin/periphery/src/stats.rs index 2a82a3791..b5708ef89 100644 --- a/bin/periphery/src/stats.rs +++ b/bin/periphery/src/stats.rs @@ -39,6 +39,7 @@ pub struct StatsClient { system: sysinfo::System, disks: sysinfo::Disks, networks: sysinfo::Networks, + components: sysinfo::Components, } const BYTES_PER_GB: f64 = 1073741824.0; @@ -50,6 +51,7 @@ impl Default for StatsClient { let system = sysinfo::System::new_all(); let disks = sysinfo::Disks::new_with_refreshed_list(); let networks = sysinfo::Networks::new_with_refreshed_list(); + let components = sysinfo::Components::new_with_refreshed_list(); let stats = SystemStats { polling_rate: periphery_config().stats_polling_rate, ..Default::default() @@ -59,6 +61,7 @@ impl Default for StatsClient { system, disks, networks, + components, stats, } } @@ -75,6 +78,7 @@ impl StatsClient { ); self.disks.refresh(true); self.networks.refresh(true); + self.components.refresh(true); } pub fn get_system_stats(&self) -> SystemStats { @@ -91,8 +95,21 @@ impl StatsClient { let load_avg = System::load_average(); + let cpu_temp = self + .components + .iter() + .filter(|c| { + let label = c.label().to_lowercase(); + label.contains("core") + || label.contains("package") + || label.contains("cpu") + }) + .filter_map(|c| c.temperature()) + .max_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal)); + SystemStats { cpu_perc: self.system.global_cpu_usage(), + cpu_temp, load_average: SystemLoadAverage { one: load_avg.one, five: load_avg.five, diff --git a/client/core/rs/src/entities/stats.rs b/client/core/rs/src/entities/stats.rs index da22cb9c1..71a6cf074 100644 --- a/client/core/rs/src/entities/stats.rs +++ b/client/core/rs/src/entities/stats.rs @@ -43,6 +43,9 @@ pub struct SystemStatsRecord { // basic stats /// Cpu usage percentage pub cpu_perc: f32, + /// CPU temperature in Celsius + #[serde(default, skip_serializing_if = "Option::is_none")] + pub cpu_temp: Option, /// Load average (1m, 5m, 15m) #[serde(default)] pub load_average: SystemLoadAverage, @@ -74,6 +77,9 @@ pub struct SystemStatsRecord { pub struct SystemStats { /// Cpu usage percentage pub cpu_perc: f32, + /// CPU temperature in Celsius + #[serde(default, skip_serializing_if = "Option::is_none")] + pub cpu_temp: Option, /// Load average (1m, 5m, 15m) #[serde(default)] pub load_average: SystemLoadAverage, diff --git a/client/core/ts/src/types.ts b/client/core/ts/src/types.ts index dba43aa9c..79a562c4e 100644 --- a/client/core/ts/src/types.ts +++ b/client/core/ts/src/types.ts @@ -2816,6 +2816,8 @@ export interface SingleDiskUsage { export interface SystemStats { /** Cpu usage percentage */ cpu_perc: number; + /** CPU temperature in Celsius */ + cpu_temp?: number; /** Load average (1m, 5m, 15m) */ load_average?: SystemLoadAverage; /** @@ -7890,6 +7892,8 @@ export interface SystemStatsRecord { sid: string; /** Cpu usage percentage */ cpu_perc: number; + /** CPU temperature in Celsius */ + cpu_temp?: number; /** Load average (1m, 5m, 15m) */ load_average?: SystemLoadAverage; /** Memory used in GB */ diff --git a/ui/public/client/types.d.ts b/ui/public/client/types.d.ts index a25b5291e..1cb5f8b01 100644 --- a/ui/public/client/types.d.ts +++ b/ui/public/client/types.d.ts @@ -2942,6 +2942,8 @@ export interface SingleDiskUsage { export interface SystemStats { /** Cpu usage percentage */ cpu_perc: number; + /** CPU temperature in Celsius */ + cpu_temp?: number; /** Load average (1m, 5m, 15m) */ load_average?: SystemLoadAverage; /** @@ -7546,6 +7548,8 @@ export interface SystemStatsRecord { sid: string; /** Cpu usage percentage */ cpu_perc: number; + /** CPU temperature in Celsius */ + cpu_temp?: number; /** Load average (1m, 5m, 15m) */ load_average?: SystemLoadAverage; /** Memory used in GB */ diff --git a/ui/src/resources/server/index.tsx b/ui/src/resources/server/index.tsx index fc3c676f7..0dd9147dd 100644 --- a/ui/src/resources/server/index.tsx +++ b/ui/src/resources/server/index.tsx @@ -210,6 +210,33 @@ export const ServerComponents: RequiredResourceComponents< ); }, + Temperature: ({ id }) => { + const isServerAvailable = useIsServerAvailable(id); + const stats = useRead( + "GetSystemStats", + { server: id }, + { + enabled: isServerAvailable, + refetchInterval: 5000, + }, + ).data; + + const temp = stats?.cpu_temp; + + return ( + + + + + {temp !== undefined ? `${temp.toFixed(1)}°C` : "N/A"} + + + + CPU Temperature: {temp !== undefined ? `${temp.toFixed(1)}°C` : "N/A"} + + + ); + }, LoadAvg: ({ id }) => { const isServerAvailable = useIsServerAvailable(id); const stats = useRead( diff --git a/ui/src/resources/server/stats-card.tsx b/ui/src/resources/server/stats-card.tsx index 2fabbb9d9..73ba95c71 100644 --- a/ui/src/resources/server/stats-card.tsx +++ b/ui/src/resources/server/stats-card.tsx @@ -136,6 +136,7 @@ export default function ServerStatsCard({ id }: ServerStatsCardProps) { key={item.label} isUnreachable={isUnreachable || isDisabled} intention={intention} + cpuTemp={item.label === "CPU" ? stats?.cpu_temp : undefined} {...item} /> ))} @@ -166,6 +167,7 @@ function StatItem({ type, isUnreachable, intention, + cpuTemp, }: { icon: LucideIcon; label: string; @@ -176,6 +178,7 @@ function StatItem({ percentage: number, type: "cpu" | "memory" | "disk", ) => ColorIntention; + cpuTemp?: number; }) { return ( @@ -191,7 +194,11 @@ function StatItem({ : hexColorByIntention(intention(percentage, type)) } > - {isUnreachable ? "N/A" : `${percentage.toFixed(1)}%`} + {isUnreachable + ? "N/A" + : type === "cpu" && cpuTemp !== undefined + ? `${cpuTemp.toFixed(0)}°C | ${percentage.toFixed(1)}%` + : `${percentage.toFixed(1)}%`} diff --git a/ui/src/resources/server/stats/current/index.tsx b/ui/src/resources/server/stats/current/index.tsx index 1905fa335..6f767a8ed 100644 --- a/ui/src/resources/server/stats/current/index.tsx +++ b/ui/src/resources/server/stats/current/index.tsx @@ -30,6 +30,13 @@ export default function ServerCurrentStats({ } + description={ + stats?.cpu_temp !== undefined && ( + <> + Temperature: {stats.cpu_temp.toFixed(1)}°C + + ) + } percentage={stats?.cpu_perc} warning={server?.config?.cpu_warning} critical={server?.config?.cpu_critical} diff --git a/ui/src/resources/server/table/stats.tsx b/ui/src/resources/server/table/stats.tsx index cb82bc837..0802f6896 100644 --- a/ui/src/resources/server/table/stats.tsx +++ b/ui/src/resources/server/table/stats.tsx @@ -27,7 +27,7 @@ export default function StatsServerTable({ }} columns={[ { - size: 250, + size: 200, accessorKey: "name", header: ({ column }) => ( @@ -38,17 +38,22 @@ export default function StatsServerTable({ }, { header: "CPU", - size: 200, + size: 180, cell: ({ row }) => , }, + { + header: "Temp", + size: 80, + cell: ({ row }) => , + }, { header: "Memory", - size: 200, + size: 180, cell: ({ row }) => , }, { header: "Disk", - size: 200, + size: 180, cell: ({ row }) => , }, { @@ -81,6 +86,32 @@ function CpuCell({ id }: { id: string }) { return ; } +function TempCell({ id }: { id: string }) { + const stats = useServerStats(id); + const temp = stats?.cpu_temp; + const intent: "Good" | "Warning" | "Critical" = + temp === undefined + ? "Good" + : temp < 65 + ? "Good" + : temp < 80 + ? "Warning" + : "Critical"; + return ( + + CPU Temperature: {temp?.toFixed(1)}°C + + } + /> + ); +} + function MemCell({ id }: { id: string }) { const stats = useServerStats(id); const used = stats?.mem_used_gb ?? 0; diff --git a/ui/src/theme/icons.ts b/ui/src/theme/icons.ts index 45dd2cc1d..5e90c894e 100644 --- a/ui/src/theme/icons.ts +++ b/ui/src/theme/icons.ts @@ -69,6 +69,7 @@ import { Tag, Tags, Terminal, + Thermometer, Trash, Trash2, TriangleAlert, @@ -121,6 +122,7 @@ export const ICONS = { // Device IP: Globe, Cpu, + Temperature: Thermometer, LoadAvg: ChartLine, Memory: MemoryStick, Disk: Database, diff --git a/ui/src/ui/stat-cell.tsx b/ui/src/ui/stat-cell.tsx index 98662ac21..2e1ca21c2 100644 --- a/ui/src/ui/stat-cell.tsx +++ b/ui/src/ui/stat-cell.tsx @@ -21,6 +21,7 @@ export interface StatCellProps extends GroupProps { info?: ReactNode; infoPosition?: FloatingPosition; infoDisabled?: boolean; + suffix?: string; } export default function StatCell({ @@ -31,13 +32,14 @@ export default function StatCell({ info, infoPosition = "left-start", infoDisabled, + suffix = "%", ...groupProps }: StatCellProps) { const ProgressComponent = ( @@ -45,11 +47,11 @@ export default function StatCell({ return ( - {value === undefined ? "N/A" : value.toFixed(1) + "%"} + {value === undefined ? "N/A" : value.toFixed(1) + suffix} {!info && ProgressComponent} {info && (