Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ deno.lock
.DS_Store
.idea
.dev
teste-temp/
1 change: 1 addition & 0 deletions bin/core/src/monitor/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
17 changes: 17 additions & 0 deletions bin/periphery/src/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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()
Expand All @@ -59,6 +61,7 @@ impl Default for StatsClient {
system,
disks,
networks,
components,
stats,
}
}
Expand All @@ -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 {
Expand All @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions client/core/rs/src/entities/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<f32>,
/// Load average (1m, 5m, 15m)
#[serde(default)]
pub load_average: SystemLoadAverage,
Expand Down Expand Up @@ -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<f32>,
/// Load average (1m, 5m, 15m)
#[serde(default)]
pub load_average: SystemLoadAverage,
Expand Down
4 changes: 4 additions & 0 deletions client/core/ts/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
/**
Expand Down Expand Up @@ -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 */
Expand Down
4 changes: 4 additions & 0 deletions ui/public/client/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
/**
Expand Down Expand Up @@ -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 */
Expand Down
27 changes: 27 additions & 0 deletions ui/src/resources/server/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,33 @@ export const ServerComponents: RequiredResourceComponents<
</HoverCard>
);
},
Temperature: ({ id }) => {
const isServerAvailable = useIsServerAvailable(id);
const stats = useRead(
"GetSystemStats",
{ server: id },
{
enabled: isServerAvailable,
refetchInterval: 5000,
},
).data;

const temp = stats?.cpu_temp;

return (
<HoverCard position="bottom-start">
<HoverCard.Target>
<Group gap="xs">
<ICONS.Temperature size="1rem" />
{temp !== undefined ? `${temp.toFixed(1)}°C` : "N/A"}
</Group>
</HoverCard.Target>
<HoverCard.Dropdown>
CPU Temperature: <b>{temp !== undefined ? `${temp.toFixed(1)}°C` : "N/A"}</b>
</HoverCard.Dropdown>
</HoverCard>
);
},
LoadAvg: ({ id }) => {
const isServerAvailable = useIsServerAvailable(id);
const stats = useRead(
Expand Down
9 changes: 8 additions & 1 deletion ui/src/resources/server/stats-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
/>
))}
Expand Down Expand Up @@ -166,6 +167,7 @@ function StatItem({
type,
isUnreachable,
intention,
cpuTemp,
}: {
icon: LucideIcon;
label: string;
Expand All @@ -176,6 +178,7 @@ function StatItem({
percentage: number,
type: "cpu" | "memory" | "disk",
) => ColorIntention;
cpuTemp?: number;
}) {
return (
<Group gap="xs" wrap="nowrap" c="dimmed">
Expand All @@ -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)}%`}
</Text>
</Group>
<Progress color="bw" value={percentage} size={4} />
Expand Down
7 changes: 7 additions & 0 deletions ui/src/resources/server/stats/current/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ export default function ServerCurrentStats({
<StatBar
title="CPU Usage"
icon={<ICONS.Cpu size="1.3rem" />}
description={
stats?.cpu_temp !== undefined && (
<>
Temperature: <b>{stats.cpu_temp.toFixed(1)}°C</b>
</>
)
}
percentage={stats?.cpu_perc}
warning={server?.config?.cpu_warning}
critical={server?.config?.cpu_critical}
Expand Down
39 changes: 35 additions & 4 deletions ui/src/resources/server/table/stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function StatsServerTable({
}}
columns={[
{
size: 250,
size: 200,
accessorKey: "name",
header: ({ column }) => (
<SortableHeader column={column} title="Name" />
Expand All @@ -38,17 +38,22 @@ export default function StatsServerTable({
},
{
header: "CPU",
size: 200,
size: 180,
cell: ({ row }) => <CpuCell id={row.original.id} />,
},
{
header: "Temp",
size: 80,
cell: ({ row }) => <TempCell id={row.original.id} />,
},
{
header: "Memory",
size: 200,
size: 180,
cell: ({ row }) => <MemCell id={row.original.id} />,
},
{
header: "Disk",
size: 200,
size: 180,
cell: ({ row }) => <DiskCell id={row.original.id} />,
},
{
Expand Down Expand Up @@ -81,6 +86,32 @@ function CpuCell({ id }: { id: string }) {
return <StatCell value={stats ? cpu : undefined} intent={intent} />;
}

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 (
<StatCell
value={temp}
intent={intent}
suffix="°C"
infoDisabled={temp === undefined}
info={
<Text size="sm">
CPU Temperature: <b>{temp?.toFixed(1)}°C</b>
</Text>
}
/>
);
}

function MemCell({ id }: { id: string }) {
const stats = useServerStats(id);
const used = stats?.mem_used_gb ?? 0;
Expand Down
2 changes: 2 additions & 0 deletions ui/src/theme/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import {
Tag,
Tags,
Terminal,
Thermometer,
Trash,
Trash2,
TriangleAlert,
Expand Down Expand Up @@ -121,6 +122,7 @@ export const ICONS = {
// Device
IP: Globe,
Cpu,
Temperature: Thermometer,
LoadAvg: ChartLine,
Memory: MemoryStick,
Disk: Database,
Expand Down
8 changes: 5 additions & 3 deletions ui/src/ui/stat-cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface StatCellProps extends GroupProps {
info?: ReactNode;
infoPosition?: FloatingPosition;
infoDisabled?: boolean;
suffix?: string;
}

export default function StatCell({
Expand All @@ -31,25 +32,26 @@ export default function StatCell({
info,
infoPosition = "left-start",
infoDisabled,
suffix = "%",
...groupProps
}: StatCellProps) {
const ProgressComponent = (
<Progress
value={value ?? 0}
color={hexColorByIntention(intent)}
w={200}
w={120}
size="xl"
{...barProps}
/>
);
return (
<Group gap="xs" justify="space-between" wrap="nowrap" {...groupProps}>
<Text
w={64}
w={48}
c={value === undefined ? "dimmed" : undefined}
{...textProps}
>
{value === undefined ? "N/A" : value.toFixed(1) + "%"}
{value === undefined ? "N/A" : value.toFixed(1) + suffix}
</Text>
{!info && ProgressComponent}
{info && (
Expand Down