diff --git a/beszel/internal/agent/system.go b/beszel/internal/agent/system.go
index 7ce4fee..a1a129f 100644
--- a/beszel/internal/agent/system.go
+++ b/beszel/internal/agent/system.go
@@ -22,7 +22,22 @@ import (
func (a *Agent) initializeSystemInfo() {
a.systemInfo.AgentVersion = beszel.Version
a.systemInfo.Hostname, _ = os.Hostname()
- a.systemInfo.KernelVersion, _ = host.KernelVersion()
+
+ platform, _, version, _ := host.PlatformInformation()
+
+ if platform == "darwin" {
+ a.systemInfo.KernelVersion = version
+ a.systemInfo.Os = system.Darwin
+ } else if strings.Contains(platform, "indows") {
+ a.systemInfo.KernelVersion = strings.Replace(platform, "Microsoft ", "", 1) + " " + version
+ a.systemInfo.Os = system.Windows
+ } else {
+ a.systemInfo.Os = system.Linux
+ }
+
+ if a.systemInfo.KernelVersion == "" {
+ a.systemInfo.KernelVersion, _ = host.KernelVersion()
+ }
// cpu model
if info, err := cpu.Info(); err == nil && len(info) > 0 {
diff --git a/beszel/internal/entities/system/system.go b/beszel/internal/entities/system/system.go
index 316377d..e298911 100644
--- a/beszel/internal/entities/system/system.go
+++ b/beszel/internal/entities/system/system.go
@@ -64,6 +64,14 @@ type NetIoStats struct {
Name string
}
+type Os uint8
+
+const (
+ Linux Os = iota
+ Darwin
+ Windows
+)
+
type Info struct {
Hostname string `json:"h"`
KernelVersion string `json:"k,omitempty"`
@@ -79,6 +87,7 @@ type Info struct {
Podman bool `json:"p,omitempty"`
GpuPct float64 `json:"g,omitempty"`
DashboardTemp float64 `json:"dt,omitempty"`
+ Os Os `json:"os"`
}
// Final data structure to return to the hub
diff --git a/beszel/site/src/components/charts/container-chart.tsx b/beszel/site/src/components/charts/container-chart.tsx
index 32727da..b4661ee 100644
--- a/beszel/site/src/components/charts/container-chart.tsx
+++ b/beszel/site/src/components/charts/container-chart.tsx
@@ -16,16 +16,17 @@ import { useStore } from "@nanostores/react"
import { $containerFilter } from "@/lib/stores"
import { ChartData } from "@/types"
import { Separator } from "../ui/separator"
+import { ChartType } from "@/lib/enums"
export default memo(function ContainerChart({
dataKey,
chartData,
- chartName,
+ chartType,
unit = "%",
}: {
dataKey: string
chartData: ChartData
- chartName: string
+ chartType: ChartType
unit?: string
}) {
const filter = useStore($containerFilter)
@@ -33,7 +34,7 @@ export default memo(function ContainerChart({
const { containerData } = chartData
- const isNetChart = chartName === "net"
+ const isNetChart = chartType === ChartType.Network
const chartConfig = useMemo(() => {
let config = {} as Record<
@@ -81,7 +82,7 @@ export default memo(function ContainerChart({
tickFormatter: (value: any) => string
}
// tick formatter
- if (chartName === "cpu") {
+ if (chartType === ChartType.CPU) {
obj.tickFormatter = (value) => {
const val = toFixedWithoutTrailingZeros(value, 2) + unit
return updateYAxisWidth(val)
@@ -111,6 +112,11 @@ export default memo(function ContainerChart({
return null
}
}
+ } else if (chartType === ChartType.Memory) {
+ obj.toolTipFormatter = (item: any) => {
+ const { v, u } = getSizeAndUnit(item.value, false)
+ return updateYAxisWidth(toFixedFloat(v, 2) + u)
+ }
} else {
obj.toolTipFormatter = (item: any) => decimalString(item.value) + unit
}
diff --git a/beszel/site/src/components/routes/system.tsx b/beszel/site/src/components/routes/system.tsx
index f6a27c0..d033bb3 100644
--- a/beszel/site/src/components/routes/system.tsx
+++ b/beszel/site/src/components/routes/system.tsx
@@ -2,6 +2,7 @@ import { t } from "@lingui/core/macro"
import { Plural, Trans } from "@lingui/react/macro"
import { $systems, pb, $chartTime, $containerFilter, $userSettings, $direction, $maxValues } from "@/lib/stores"
import { ChartData, ChartTimes, ContainerStatsRecord, GPUData, SystemRecord, SystemStatsRecord } from "@/types"
+import { ChartType, Os } from "@/lib/enums"
import React, { lazy, memo, useCallback, useEffect, useMemo, useRef, useState } from "react"
import { Card, CardHeader, CardTitle, CardDescription } from "../ui/card"
import { useStore } from "@nanostores/react"
@@ -22,7 +23,7 @@ import { Separator } from "../ui/separator"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip"
import { Button } from "../ui/button"
import { Input } from "../ui/input"
-import { ChartAverage, ChartMax, Rows, TuxIcon, WindowsIcon } from "../ui/icons"
+import { ChartAverage, ChartMax, Rows, TuxIcon, WindowsIcon, AppleIcon } from "../ui/icons"
import { useIntersectionObserver } from "@/lib/use-intersection-observer"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"
import { timeTicks } from "d3-time"
@@ -251,12 +252,23 @@ export default function SystemDetail({ name }: { name: string }) {
if (!system.info) {
return []
}
- let version = system.info.k ?? ""
- const buildIndex = version.indexOf(" Build")
- const isWindows = buildIndex !== -1
- if (isWindows) {
- version = version.substring(0, buildIndex)
+
+ const osInfo = {
+ [Os.Linux]: {
+ Icon: TuxIcon,
+ value: system.info.k,
+ label: t({ comment: "Linux kernel", message: "Kernel" }),
+ },
+ [Os.Darwin]: {
+ Icon: AppleIcon,
+ value: `macOS ${system.info.k}`,
+ },
+ [Os.Windows]: {
+ Icon: WindowsIcon,
+ value: system.info.k,
+ },
}
+
let uptime: React.ReactNode
if (system.info.u < 172800) {
const hours = Math.trunc(system.info.u / 3600)
@@ -274,11 +286,7 @@ export default function SystemDetail({ name }: { name: string }) {
hide: system.info.h === system.host || system.info.h === system.name,
},
{ value: uptime, Icon: ClockArrowUp, label: t`Uptime`, hide: !system.info.u },
- {
- value: version,
- Icon: isWindows ? WindowsIcon : TuxIcon,
- label: isWindows ? t`Windows build` : t({ comment: "Linux kernel", message: "Kernel" }),
- },
+ osInfo[system.info.os ?? Os.Linux],
{
value: `${system.info.m} (${system.info.c}c${system.info.t ? `/${system.info.t}t` : ""})`,
Icon: CpuIcon,
@@ -456,7 +464,7 @@ export default function SystemDetail({ name }: { name: string }) {
description={t`Average CPU utilization of containers`}
cornerEl={containerFilterBar}
>
-
+
)}
@@ -477,7 +485,7 @@ export default function SystemDetail({ name }: { name: string }) {
description={dockerOrPodman(t`Memory usage of docker containers`, system)}
cornerEl={containerFilterBar}
>
-
+
)}
@@ -519,7 +527,7 @@ export default function SystemDetail({ name }: { name: string }) {
cornerEl={containerFilterBar}
>
{/* @ts-ignore */}
-
+
)}
diff --git a/beszel/site/src/components/ui/icons.tsx b/beszel/site/src/components/ui/icons.tsx
index 8fe4060..6dd6d6d 100644
--- a/beszel/site/src/components/ui/icons.tsx
+++ b/beszel/site/src/components/ui/icons.tsx
@@ -12,16 +12,27 @@ export function TuxIcon(props: SVGProps) {
)
}
-// meteor icons (MIT) https://github.com/zkreations/icons/blob/main/LICENSE
+// icon park (Apache 2.0) https://github.com/bytedance/IconPark/blob/master/LICENSE
export function WindowsIcon(props: SVGProps) {
return (
-