mirror of
https://github.com/henrygd/beszel.git
synced 2026-05-06 19:01:48 +02:00
updates
This commit is contained in:
@@ -66,7 +66,7 @@ export default function AreaChartDefault({
|
||||
}) {
|
||||
const { yAxisWidth, updateYAxisWidth } = useYAxisWidth()
|
||||
const { isIntersecting, ref } = useIntersectionObserver({ freeze: false })
|
||||
const sourceData = customData ?? chartData.systemStats
|
||||
const sourceData = customData ?? chartData.systemStats ?? []
|
||||
const [displayData, setDisplayData] = useState(sourceData)
|
||||
const [displayMaxToggled, setDisplayMaxToggled] = useState(maxToggled)
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ export default function LineChartDefault({
|
||||
}) {
|
||||
const { yAxisWidth, updateYAxisWidth } = useYAxisWidth()
|
||||
const { isIntersecting, ref } = useIntersectionObserver({ freeze: false })
|
||||
const sourceData = customData ?? chartData.systemStats
|
||||
const sourceData = customData ?? chartData.systemStats ?? []
|
||||
const [displayData, setDisplayData] = useState(sourceData)
|
||||
const [displayMaxToggled, setDisplayMaxToggled] = useState(maxToggled)
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ export function getProbeColumns(
|
||||
<Checkbox
|
||||
className="ms-2"
|
||||
checked={table.getIsAllRowsSelected() || (table.getIsSomeRowsSelected() && "indeterminate")}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
onCheckedChange={(value) => table.toggleAllRowsSelected(!!value)}
|
||||
aria-label={t`Select all`}
|
||||
/>
|
||||
@@ -78,6 +79,7 @@ export function getProbeColumns(
|
||||
cell: ({ row }) => (
|
||||
<Checkbox
|
||||
checked={row.getIsSelected()}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
onCheckedChange={(value) => row.toggleSelected(!!value)}
|
||||
aria-label={t`Select row`}
|
||||
/>
|
||||
@@ -264,14 +266,24 @@ export function getProbeColumns(
|
||||
<MoreHorizontalIcon className="w-5" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuContent align="end" onClick={(event) => event.stopPropagation()}>
|
||||
{!isBulkAction && (
|
||||
<DropdownMenuItem onClick={() => onEdit?.(row.original)}>
|
||||
<DropdownMenuItem
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
onEdit?.(row.original)
|
||||
}}
|
||||
>
|
||||
<PenBoxIcon className="me-2.5 size-4" />
|
||||
<Trans>Edit</Trans>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem onClick={() => onSetEnabled?.(actionRows, !shouldPause)}>
|
||||
<DropdownMenuItem
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
onSetEnabled?.(actionRows, !shouldPause)
|
||||
}}
|
||||
>
|
||||
{shouldPause ? (
|
||||
<>
|
||||
<PauseCircleIcon className="me-2.5 size-4" />
|
||||
@@ -286,7 +298,8 @@ export function getProbeColumns(
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
onClick={() => {
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
onDelete?.(actionRows)
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -33,11 +33,19 @@ import { TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/compon
|
||||
import { useToast } from "@/components/ui/use-toast"
|
||||
import { isReadOnlyUser } from "@/lib/api"
|
||||
import { pb } from "@/lib/api"
|
||||
import { $allSystemsById } from "@/lib/stores"
|
||||
import { $allSystemsById, $chartTime, $direction } from "@/lib/stores"
|
||||
import { cn, useBrowserStorage } from "@/lib/utils"
|
||||
import type { NetworkProbeRecord } from "@/types"
|
||||
import { AddProbeDialog, EditProbeDialog } from "./probe-dialog"
|
||||
import { XIcon } from "lucide-react"
|
||||
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@/components/ui/sheet"
|
||||
import ChartTimeSelect from "@/components/charts/chart-time-select"
|
||||
import { ResponseChart, LossChart } from "@/components/routes/system/charts/probes-charts"
|
||||
import { useNetworkProbeStats } from "@/lib/use-network-probes"
|
||||
import { useStore } from "@nanostores/react"
|
||||
import type { ChartData } from "@/types"
|
||||
import { parseSemVer } from "@/lib/utils"
|
||||
import { Separator } from "../ui/separator"
|
||||
|
||||
export default function NetworkProbesTableNew({
|
||||
systemId,
|
||||
@@ -325,6 +333,13 @@ const NetworkProbesTable = memo(function NetworkProbeTable({
|
||||
}) {
|
||||
// The virtualizer will need a reference to the scrollable container element
|
||||
const scrollRef = useRef<HTMLDivElement>(null)
|
||||
const [sheetOpen, setSheetOpen] = useState(false)
|
||||
const [activeProbeId, setActiveProbeId] = useState<string | null>(null)
|
||||
const activeProbe = activeProbeId ? table.options.data.find((probe) => probe.id === activeProbeId) : undefined
|
||||
const openSheet = useCallback((probe: NetworkProbeRecord) => {
|
||||
setActiveProbeId(probe.id)
|
||||
setSheetOpen(true)
|
||||
}, [])
|
||||
|
||||
const virtualizer = useVirtualizer<HTMLDivElement, HTMLTableRowElement>({
|
||||
count: rows.length,
|
||||
@@ -360,6 +375,7 @@ const NetworkProbesTable = memo(function NetworkProbeTable({
|
||||
row={row}
|
||||
virtualRow={virtualRow}
|
||||
isSelected={row.getIsSelected()}
|
||||
openSheet={openSheet}
|
||||
/>
|
||||
)
|
||||
})
|
||||
@@ -373,6 +389,13 @@ const NetworkProbesTable = memo(function NetworkProbeTable({
|
||||
</TableBody>
|
||||
</table>
|
||||
</div>
|
||||
<NetworkProbeSheet
|
||||
open={sheetOpen}
|
||||
onOpenChange={(nextOpen) => {
|
||||
setSheetOpen(nextOpen)
|
||||
}}
|
||||
probe={activeProbe}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
@@ -399,13 +422,19 @@ const NetworkProbeTableRow = memo(function NetworkProbeTableRow({
|
||||
row,
|
||||
virtualRow,
|
||||
isSelected,
|
||||
openSheet,
|
||||
}: {
|
||||
row: Row<NetworkProbeRecord>
|
||||
virtualRow: VirtualItem
|
||||
isSelected: boolean
|
||||
openSheet: (probe: NetworkProbeRecord) => void
|
||||
}) {
|
||||
return (
|
||||
<TableRow data-state={isSelected && "selected"} className="transition-opacity">
|
||||
<TableRow
|
||||
data-state={isSelected && "selected"}
|
||||
className="cursor-pointer transition-opacity"
|
||||
onClick={() => openSheet(row.original)}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell
|
||||
key={cell.id}
|
||||
@@ -421,3 +450,88 @@ const NetworkProbeTableRow = memo(function NetworkProbeTableRow({
|
||||
</TableRow>
|
||||
)
|
||||
})
|
||||
|
||||
function NetworkProbeSheet({
|
||||
open,
|
||||
onOpenChange,
|
||||
probe,
|
||||
}: {
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
probe?: NetworkProbeRecord
|
||||
}) {
|
||||
if (!probe) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <NetworkProbeSheetContent key={probe.system} open={open} onOpenChange={onOpenChange} probe={probe} />
|
||||
}
|
||||
|
||||
function NetworkProbeSheetContent({
|
||||
open,
|
||||
onOpenChange,
|
||||
probe,
|
||||
}: {
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
probe: NetworkProbeRecord
|
||||
}) {
|
||||
const chartTime = useStore($chartTime)
|
||||
const direction = useStore($direction)
|
||||
const system = useStore($allSystemsById)[probe.system]
|
||||
|
||||
const probeStats = useNetworkProbeStats({ systemId: probe.system, chartTime })
|
||||
|
||||
const chartData = useMemo<ChartData>(
|
||||
() => ({
|
||||
agentVersion: parseSemVer(system?.info?.v),
|
||||
orientation: direction === "rtl" ? "right" : "left",
|
||||
chartTime,
|
||||
}),
|
||||
[chartTime]
|
||||
)
|
||||
const hasProbeStats = probeStats.some((record) => record.stats?.[probe.id] != null)
|
||||
const probeLabel = probe.name || probe.target
|
||||
|
||||
return (
|
||||
<Sheet open={open} onOpenChange={onOpenChange}>
|
||||
<SheetContent className="w-full sm:max-w-220 overflow-auto p-4 sm:p-6">
|
||||
<SheetHeader className="mb-0 border-b p-0 pb-4">
|
||||
<SheetTitle>{probeLabel}</SheetTitle>
|
||||
<SheetDescription className="flex flex-wrap items-center gap-x-2 gap-y-1">
|
||||
{system?.name ?? ""}
|
||||
<Separator orientation="vertical" className="h-2.5 bg-muted-foreground opacity-70" />
|
||||
{probe.protocol.toUpperCase()}
|
||||
<Separator orientation="vertical" className="h-2.5 bg-muted-foreground opacity-70" />
|
||||
{probe.target}
|
||||
{probe.port > 0 && (
|
||||
<>
|
||||
<Separator orientation="vertical" className="h-2.5 bg-muted-foreground opacity-70" />
|
||||
<span>{probe.port}</span>
|
||||
</>
|
||||
)}
|
||||
</SheetDescription>
|
||||
</SheetHeader>
|
||||
<div className="grid gap-4">
|
||||
<ChartTimeSelect className="bg-card" agentVersion={chartData.agentVersion} />
|
||||
<ResponseChart
|
||||
probeStats={probeStats}
|
||||
grid={false}
|
||||
probes={[probe]}
|
||||
chartData={chartData}
|
||||
empty={!hasProbeStats}
|
||||
showFilter={false}
|
||||
/>
|
||||
<LossChart
|
||||
probeStats={probeStats}
|
||||
grid={false}
|
||||
probes={[probe]}
|
||||
chartData={chartData}
|
||||
empty={!hasProbeStats}
|
||||
showFilter={false}
|
||||
/>
|
||||
</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ import { memo, useEffect } from "react"
|
||||
import NetworkProbesTableNew from "@/components/network-probes-table/network-probes-table"
|
||||
import { ActiveAlerts } from "@/components/active-alerts"
|
||||
import { FooterRepoLink } from "@/components/footer-repo-link"
|
||||
import { useNetworkProbesData } from "@/lib/use-network-probes"
|
||||
import { useNetworkProbes } from "@/lib/use-network-probes"
|
||||
|
||||
export default memo(() => {
|
||||
const { t } = useLingui()
|
||||
const { probes } = useNetworkProbesData({})
|
||||
const probes = useNetworkProbes({})
|
||||
|
||||
useEffect(() => {
|
||||
document.title = `${t`Network Probes`} / Beszel`
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import { getPbTimestamp, pb } from "@/lib/api"
|
||||
import { chartTimeData } from "@/lib/utils"
|
||||
import type { ChartData, ChartTimes, ContainerStatsRecord, NetworkProbeStatsRecord, SystemStatsRecord } from "@/types"
|
||||
import type {
|
||||
ChartData,
|
||||
ChartDataContainer,
|
||||
ChartTimes,
|
||||
ContainerStatsRecord,
|
||||
NetworkProbeStatsRecord,
|
||||
SystemStatsRecord,
|
||||
} from "@/types"
|
||||
|
||||
type ChartTimeData = {
|
||||
time: number
|
||||
@@ -19,7 +26,7 @@ export const cache = new Map<
|
||||
/** Append new records onto prev with gap detection. Converts string `created` values to ms timestamps in place.
|
||||
* Pass `maxLen` to cap the result length in one copy instead of slicing again after the call. */
|
||||
export function appendData<T extends { created: string | number | null }>(
|
||||
prev: T[],
|
||||
prev: T[] = [],
|
||||
newRecords: T[],
|
||||
expectedInterval: number,
|
||||
maxLen?: number
|
||||
@@ -63,11 +70,11 @@ export async function getStats<T extends SystemStatsRecord | ContainerStatsRecor
|
||||
})
|
||||
}
|
||||
|
||||
export function makeContainerData(containers: ContainerStatsRecord[]): ChartData["containerData"] {
|
||||
const result = [] as ChartData["containerData"]
|
||||
export function makeContainerData(containers: ContainerStatsRecord[]): ChartDataContainer[] {
|
||||
const result = [] as ChartDataContainer[]
|
||||
for (const { created, stats } of containers) {
|
||||
if (!created) {
|
||||
result.push({ created: null } as ChartData["containerData"][0])
|
||||
result.push({ created: null } as ChartDataContainer)
|
||||
continue
|
||||
}
|
||||
result.push(makeContainerPoint(new Date(created).getTime(), stats))
|
||||
@@ -76,11 +83,8 @@ export function makeContainerData(containers: ContainerStatsRecord[]): ChartData
|
||||
}
|
||||
|
||||
/** Transform a single realtime container stats message into a ChartDataContainer point. */
|
||||
export function makeContainerPoint(
|
||||
created: number,
|
||||
stats: ContainerStatsRecord["stats"]
|
||||
): ChartData["containerData"][0] {
|
||||
const point: ChartData["containerData"][0] = { created } as ChartData["containerData"][0]
|
||||
export function makeContainerPoint(created: number, stats: ContainerStatsRecord["stats"]): ChartDataContainer {
|
||||
const point: ChartDataContainer = { created } as ChartDataContainer
|
||||
for (const container of stats) {
|
||||
;(point as Record<string, unknown>)[container.n] = container
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ type ProbeChartProps = {
|
||||
probes: NetworkProbeRecord[]
|
||||
chartData: ChartData
|
||||
empty: boolean
|
||||
showFilter?: boolean
|
||||
}
|
||||
|
||||
type ProbeChartBaseProps = ProbeChartProps & {
|
||||
@@ -39,8 +40,10 @@ function ProbeChart({
|
||||
tickFormatter,
|
||||
contentFormatter,
|
||||
domain,
|
||||
showFilter = probes.length > 1,
|
||||
}: ProbeChartBaseProps) {
|
||||
const filter = useStore($filter)
|
||||
const storedFilter = useStore($filter)
|
||||
const filter = showFilter ? storedFilter : ""
|
||||
|
||||
const { dataPoints, visibleKeys } = useMemo(() => {
|
||||
const sortedProbes = [...probes].sort((a, b) => b.resAvg1h - a.resAvg1h)
|
||||
@@ -78,12 +81,12 @@ function ProbeChart({
|
||||
return probeStats.filter((record) => visibleKeys.some((id) => record.stats?.[id] != null))
|
||||
}, [probeStats, visibleKeys])
|
||||
|
||||
const legend = dataPoints.length < 10
|
||||
const legend = dataPoints.length < 10 && dataPoints.length > 1
|
||||
|
||||
return (
|
||||
<ChartCard
|
||||
legend={legend}
|
||||
cornerEl={<FilterBar store={$filter} />}
|
||||
legend={legend || !showFilter}
|
||||
cornerEl={showFilter ? <FilterBar store={$filter} /> : undefined}
|
||||
empty={empty}
|
||||
title={title}
|
||||
description={description}
|
||||
@@ -129,6 +132,30 @@ export function ResponseChart({ probeStats, grid, probes, chartData, empty }: Pr
|
||||
)
|
||||
}
|
||||
|
||||
export function MaxResponseChart({ probeStats, grid, probes, chartData, empty }: ProbeChartProps) {
|
||||
const { t } = useLingui()
|
||||
|
||||
return (
|
||||
<ProbeChart
|
||||
probeStats={probeStats}
|
||||
grid={grid}
|
||||
probes={probes}
|
||||
chartData={chartData}
|
||||
empty={empty}
|
||||
valueIndex={0}
|
||||
title={t`Response`}
|
||||
description={t`Average response time`}
|
||||
tickFormatter={(value) => formatMicroseconds(value, false)}
|
||||
contentFormatter={({ value }) => {
|
||||
if (typeof value !== "number") {
|
||||
return value
|
||||
}
|
||||
return formatMicroseconds(value)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function LossChart({ probeStats, grid, probes, chartData, empty }: ProbeChartProps) {
|
||||
const { t } = useLingui()
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ResponseChart, LossChart } from "./charts/probes-charts"
|
||||
import type { SystemData } from "./use-system-data"
|
||||
import { $chartTime } from "@/lib/stores"
|
||||
import { useStore } from "@nanostores/react"
|
||||
import { useNetworkProbesData } from "@/lib/use-network-probes"
|
||||
import { useNetworkProbes, useNetworkProbeStats } from "@/lib/use-network-probes"
|
||||
|
||||
const ContainersTable = lazy(() => import("../../containers-table/containers-table"))
|
||||
|
||||
@@ -56,7 +56,8 @@ function ProbesTable({ systemId, systemData }: { systemId: string; systemData: S
|
||||
const { grid, chartData } = systemData ?? {}
|
||||
const chartTime = useStore($chartTime)
|
||||
|
||||
const { probes, probeStats } = useNetworkProbesData({ systemId, loadStats: !!chartData, chartTime })
|
||||
const probes = useNetworkProbes({ systemId })
|
||||
const probeStats = useNetworkProbeStats({ systemId, chartTime })
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -288,7 +288,7 @@ export function useSystemData(id: string) {
|
||||
// derived values
|
||||
const isLongerChart = !["1m", "1h"].includes(chartTime)
|
||||
const showMax = maxValues && isLongerChart
|
||||
const dataEmpty = !chartLoading && chartData.systemStats.length === 0
|
||||
const dataEmpty = !chartLoading && chartData.systemStats?.length === 0
|
||||
const lastGpus = systemStats.at(-1)?.stats?.g
|
||||
const isPodman = details?.podman ?? system.info?.p ?? false
|
||||
|
||||
|
||||
@@ -36,22 +36,15 @@ const NETWORK_PROBE_FIELDS =
|
||||
|
||||
interface UseNetworkProbesProps {
|
||||
systemId?: string
|
||||
loadStats?: boolean
|
||||
chartTime?: ChartTimes
|
||||
existingProbes?: NetworkProbeRecord[]
|
||||
}
|
||||
|
||||
export function useNetworkProbesData(props: UseNetworkProbesProps) {
|
||||
const { systemId, loadStats, chartTime, existingProbes } = props
|
||||
export function useNetworkProbes(props: UseNetworkProbesProps) {
|
||||
const { systemId } = props
|
||||
|
||||
const [p, setProbes] = useState<NetworkProbeRecord[]>([])
|
||||
const [probeStats, setProbeStats] = useState<NetworkProbeStatsRecord[]>([])
|
||||
const statsRequestId = useRef(0)
|
||||
const [probes, setProbes] = useState<NetworkProbeRecord[]>([])
|
||||
const pendingProbeEvents = useRef(new Map<string, RecordSubscription<NetworkProbeRecord>>())
|
||||
const probeBatchTimeout = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
|
||||
const probes = existingProbes ?? p
|
||||
|
||||
// clear old data when systemId changes
|
||||
// useEffect(() => {
|
||||
// return setProbes([])
|
||||
@@ -59,16 +52,11 @@ export function useNetworkProbesData(props: UseNetworkProbesProps) {
|
||||
|
||||
// initial load - fetch probes if not provided by caller
|
||||
useEffect(() => {
|
||||
if (!existingProbes) {
|
||||
fetchProbes(systemId).then((probes) => setProbes(probes))
|
||||
}
|
||||
fetchProbes(systemId).then((probes) => setProbes(probes))
|
||||
}, [systemId])
|
||||
|
||||
// Subscribe to updates if probes not provided by caller
|
||||
useEffect(() => {
|
||||
if (existingProbes) {
|
||||
return
|
||||
}
|
||||
let unsubscribe: (() => void) | undefined
|
||||
|
||||
function flushPendingProbeEvents() {
|
||||
@@ -115,9 +103,22 @@ export function useNetworkProbesData(props: UseNetworkProbesProps) {
|
||||
}
|
||||
}, [systemId])
|
||||
|
||||
return probes
|
||||
}
|
||||
|
||||
interface UseNetworkProbeStatsProps {
|
||||
systemId?: string
|
||||
chartTime: ChartTimes
|
||||
}
|
||||
|
||||
export function useNetworkProbeStats(props: UseNetworkProbeStatsProps) {
|
||||
const { systemId, chartTime } = props
|
||||
const [probeStats, setProbeStats] = useState<NetworkProbeStatsRecord[]>([])
|
||||
const requestID = useRef(0)
|
||||
|
||||
// Subscribe to new probe stats
|
||||
useEffect(() => {
|
||||
if (!loadStats || !systemId) {
|
||||
if (!systemId) {
|
||||
return
|
||||
}
|
||||
let unsubscribe: (() => void) | undefined
|
||||
@@ -175,12 +176,12 @@ export function useNetworkProbesData(props: UseNetworkProbesProps) {
|
||||
|
||||
// fetch missing probe stats on load and when chart time changes
|
||||
useEffect(() => {
|
||||
if (!loadStats || !systemId || !chartTime || chartTime === "1m") {
|
||||
if (!systemId || !chartTime || chartTime === "1m") {
|
||||
return
|
||||
}
|
||||
|
||||
const { expectedInterval } = chartTimeData[chartTime]
|
||||
const requestId = ++statsRequestId.current
|
||||
const requestId = ++requestID.current
|
||||
|
||||
const cachedProbeStats = getCacheValue(systemId, chartTime)
|
||||
|
||||
@@ -198,7 +199,7 @@ export function useNetworkProbesData(props: UseNetworkProbesProps) {
|
||||
getStats<NetworkProbeStatsRecord>("network_probe_stats", systemId, chartTime, cachedProbeStats, true).then(
|
||||
(probeStats) => {
|
||||
// If another request has been made since this one, ignore the results
|
||||
if (requestId !== statsRequestId.current) {
|
||||
if (requestId !== requestID.current) {
|
||||
return
|
||||
}
|
||||
const newStats = appendCacheValue(systemId, chartTime, probeStats)
|
||||
@@ -209,7 +210,7 @@ export function useNetworkProbesData(props: UseNetworkProbesProps) {
|
||||
|
||||
// subscribe to realtime metrics if chart time is 1m
|
||||
useEffect(() => {
|
||||
if (!loadStats || !systemId || chartTime !== "1m") {
|
||||
if (!systemId || chartTime !== "1m") {
|
||||
return
|
||||
}
|
||||
let unsubscribe: (() => void) | undefined
|
||||
@@ -238,12 +239,8 @@ export function useNetworkProbesData(props: UseNetworkProbesProps) {
|
||||
return () => unsubscribe?.()
|
||||
}, [chartTime, systemId])
|
||||
|
||||
return {
|
||||
probes,
|
||||
probeStats,
|
||||
}
|
||||
return probeStats
|
||||
}
|
||||
|
||||
// function probesToStats(probes: NetworkProbeRecord[]): NetworkProbeStatsRecord["stats"] {
|
||||
// const stats: NetworkProbeStatsRecord["stats"] = {}
|
||||
// for (const probe of probes) {
|
||||
|
||||
4
internal/site/src/types.d.ts
vendored
4
internal/site/src/types.d.ts
vendored
@@ -313,8 +313,8 @@ export interface SemVer {
|
||||
|
||||
export interface ChartData {
|
||||
agentVersion: SemVer
|
||||
systemStats: SystemStatsRecord[]
|
||||
containerData: ChartDataContainer[]
|
||||
systemStats?: SystemStatsRecord[]
|
||||
containerData?: ChartDataContainer[]
|
||||
orientation: "right" | "left"
|
||||
chartTime: ChartTimes
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user