diff --git a/site/src/components/charts/bandwidth-chart.tsx b/site/src/components/charts/bandwidth-chart.tsx
new file mode 100644
index 0000000..236ca1c
--- /dev/null
+++ b/site/src/components/charts/bandwidth-chart.tsx
@@ -0,0 +1,98 @@
+import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts'
+
+import {
+ ChartConfig,
+ ChartContainer,
+ ChartTooltip,
+ ChartTooltipContent,
+} from '@/components/ui/chart'
+import { formatShortDate, hourWithMinutes } from '@/lib/utils'
+import Spinner from '../spinner'
+
+const chartConfig = {
+ recv: {
+ label: 'Received',
+ color: 'hsl(var(--chart-2))',
+ },
+ sent: {
+ label: 'Sent',
+ color: 'hsl(var(--chart-1))',
+ },
+} satisfies ChartConfig
+
+export default function BandwidthChart({
+ chartData,
+ ticks,
+}: {
+ chartData: { time: number; sent: number; recv: number }[]
+ ticks: number[]
+}) {
+ if (!chartData.length || !ticks.length) {
+ return
+ }
+
+ return (
+
+
+
+
+ {/* todo: short time if first date is same day, otherwise short date */}
+
+ formatShortDate(data[0].payload.time)}
+ indicator="line"
+ />
+ }
+ />
+
+
+
+
+ )
+}
diff --git a/site/src/components/routes/server.tsx b/site/src/components/routes/server.tsx
index 6a3d5fb..378429e 100644
--- a/site/src/components/routes/server.tsx
+++ b/site/src/components/routes/server.tsx
@@ -9,7 +9,6 @@ import ChartTimeSelect from '../charts/chart-time-select'
import { chartTimeData, cn, getPbTimestamp } from '@/lib/utils'
import { Separator } from '../ui/separator'
import { scaleTime } from 'd3-scale'
-import DiskIoChart from '../charts/disk-io-chart'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip'
const CpuChart = lazy(() => import('../charts/cpu-chart'))
@@ -17,6 +16,8 @@ const ContainerCpuChart = lazy(() => import('../charts/container-cpu-chart'))
const MemChart = lazy(() => import('../charts/mem-chart'))
const ContainerMemChart = lazy(() => import('../charts/container-mem-chart'))
const DiskChart = lazy(() => import('../charts/disk-chart'))
+const DiskIoChart = lazy(() => import('../charts/disk-io-chart'))
+const BandwidthChart = lazy(() => import('../charts/bandwidth-chart'))
function timestampToBrowserTime(timestamp: string) {
const date = new Date(timestamp)
@@ -42,6 +43,9 @@ export default function ServerDetail({ name }: { name: string }) {
const [diskIoChartData, setDiskIoChartData] = useState(
[] as { time: number; read: number; write: number }[]
)
+ const [bandwidthChartData, setBandwidthChartData] = useState(
+ [] as { time: number; sent: number; recv: number }[]
+ )
const [dockerCpuChartData, setDockerCpuChartData] = useState(
[] as Record[]
)
@@ -56,6 +60,7 @@ export default function ServerDetail({ name }: { name: string }) {
setCpuChartData([])
setMemChartData([])
setDiskChartData([])
+ setBandwidthChartData([])
setDockerCpuChartData([])
setDockerMemChartData([])
}
@@ -71,17 +76,6 @@ export default function ServerDetail({ name }: { name: string }) {
}
}, [name, server, servers])
- // if visiting directly, make sure server gets set when servers are loaded
- // useEffect(() => {
- // if (!('id' in server)) {
- // const matchingServer = servers.find((s) => s.name === name) as SystemRecord
- // if (matchingServer) {
- // console.log('setting server')
- // setServer(matchingServer)
- // }
- // }
- // }, [servers])
-
// get stats
useEffect(() => {
if (!server.id) {
@@ -114,6 +108,7 @@ export default function ServerDetail({ name }: { name: string }) {
const memData = [] as typeof memChartData
const diskData = [] as typeof diskChartData
const diskIoData = [] as typeof diskIoChartData
+ const networkData = [] as typeof bandwidthChartData
for (let { created, stats } of serverStats) {
const time = new Date(created).getTime()
cpuData.push({ time, cpu: stats.cpu })
@@ -125,11 +120,13 @@ export default function ServerDetail({ name }: { name: string }) {
})
diskData.push({ time, disk: stats.d, diskUsed: stats.du })
diskIoData.push({ time, read: stats.dr, write: stats.dw })
+ networkData.push({ time, sent: stats.ns, recv: stats.nr })
}
setCpuChartData(cpuData)
setMemChartData(memData)
setDiskChartData(diskData)
setDiskIoChartData(diskIoData)
+ setBandwidthChartData(networkData)
}, [serverStats])
useEffect(() => {
@@ -278,6 +275,11 @@ export default function ServerDetail({ name }: { name: string }) {
>
+
+
+
+
+
{server.name}
diff --git a/site/src/main.tsx b/site/src/main.tsx
index 2545647..3553e25 100644
--- a/site/src/main.tsx
+++ b/site/src/main.tsx
@@ -44,8 +44,9 @@ import {
} from './components/ui/dropdown-menu.tsx'
import { AlertRecord, SystemRecord } from './types'
import { $router, Link, navigate } from './components/router.tsx'
+import ServerDetail from './components/routes/server.tsx'
-const ServerDetail = lazy(() => import('./components/routes/server.tsx'))
+// const ServerDetail = lazy(() => import('./components/routes/server.tsx'))
const CommandPalette = lazy(() => import('./components/command-palette.tsx'))
const LoginPage = lazy(() => import('./components/login/login.tsx'))
@@ -103,11 +104,7 @@ const App = () => {
} else if (page.path === '/') {
return
} else if (page.route === 'server') {
- return (
-
-
-
- )
+ return
}
}
diff --git a/site/src/types.d.ts b/site/src/types.d.ts
index 1b58a70..fe12558 100644
--- a/site/src/types.d.ts
+++ b/site/src/types.d.ts
@@ -48,6 +48,10 @@ export interface SystemStats {
dr: number
/** disk write (mb) */
dw: number
+ /** network sent (mb) */
+ ns: number
+ /** network received (mb) */
+ nr: number
}
export interface ContainerStatsRecord extends RecordModel {
@@ -66,7 +70,7 @@ interface ContainerStats {
export interface SystemStatsRecord extends RecordModel {
system: string
- info: SystemStats
+ stats: SystemStats
}
export interface AlertRecord extends RecordModel {
diff --git a/types.go b/types.go
index 0574ae5..9e59e7c 100644
--- a/types.go
+++ b/types.go
@@ -39,6 +39,8 @@ type SystemStats struct {
DiskPct float64 `json:"dp"`
DiskRead float64 `json:"dr"`
DiskWrite float64 `json:"dw"`
+ NetworkSent float64 `json:"ns"`
+ NetworkRecv float64 `json:"nr"`
}
type ContainerStats struct {