@samitouri / QOSami-HFS / commits / 6317965b

admin/monitoring: show ram

Massimo Melina committed Aug 25, 2024 at 10:16 UTC 6317965b6adba84419616f1c4d2fc1efcf76f043
4 files changed +10 -8
admin/src/MonitorPage.ts
+7 -5
@@ -17,6 +17,7 @@ import { agentIcons } from './LogsPage'
17 import { state, useSnapState } from './state'
18 import { useBlockIp } from './useBlockIp'
19 import { alertDialog, confirmDialog } from './dialog'
20 +import { useInterval } from 'usehooks-ts'
21
22 export default function MonitorPage() {
23 return h(Fragment, {},
@@ -26,13 +27,13 @@ export default function MonitorPage() {
27 }
28
29 function MoreInfo() {
29 - const { data: status, element } = useApiEx('get_status')
30 + const { data: status, element, reload } = useApiEx('get_status')
31 + useInterval(reload, 10_000) // status hardly change, but it can
32 const { data: connections } = useApiEvents('get_connection_stats')
31 - if (status && connections)
32 - Object.assign(status, connections)
33 const [allInfo, setAllInfo] = useState(false)
34 const md = useBreakpoint('md')
35 const sm = useBreakpoint('sm')
36 + const xl = useBreakpoint('xl')
37 const formatDuration = createDurationFormatter({ maxTokens: 2, skipZeroes: true })
38 return element || h(Box, { display: 'flex', flexWrap: 'wrap', gap: { xs: .5, md: 1 }, mb: { xs: 1, sm: 2 } },
39 (allInfo || md) && pair('started', {
@@ -52,7 +53,8 @@ function MoreInfo() {
53 (allInfo || sm) && pair('ips', { label: "IPs", title: () => "Currently connected" }),
54 (md || allInfo && md || status?.http?.error) && pair('http', { label: "HTTP", render: port }),
55 (md || allInfo && md || status?.https?.error) && pair('https', { label: "HTTPS", render: port }),
55 - !md && h(IconBtn, {
56 + (xl || allInfo) && pair('ram', { label: "RAM", render: formatBytes }),
57 + !xl && h(IconBtn, {
58 size: 'small',
59 icon: allInfo ? ChevronLeft : ChevronRight,
60 title: "Show more",
@@ -71,7 +73,7 @@ function MoreInfo() {
73 }
74
75 function pair(k: string, { label, minWidth, render, title, onDelete }: PairOptions={}) {
74 - let v = _.get(status, k)
76 + let v = _.get(connections, k) ?? _.get(status, k)
77 if (v === undefined)
78 return null
79 let color: Color = undefined
admin/src/api.ts
+1 -1
@@ -32,7 +32,7 @@ export function useApiEx<T=any>(...args: Parameters<typeof useApi>) {
32 !args[0] ? null
33 : res.error ? h(Alert, { severity: 'error' }, xlate(String(res.error), ERRORS),
34 h(IconBtn, { icon: Refresh, title: "Reload", onClick: res.reload, sx: { m:'-10px 0 -8px 16px' } }) )
35 - : res.loading || res.data === undefined ? spinner()
35 + : res.data === undefined ? spinner()
36 : null,
37 Object.values(res))
38 }
shared/api.ts
+1 -2
@@ -89,13 +89,12 @@ export function useApi<T=any>(cmd: string | Falsy, params?: object, options: Api
89 const dataRef = useRef<any>()
90 useEffect(() => {
91 loadingRef.current?.abort()
92 - setData(undefined)
92 setError(undefined)
93 let aborted = false
94 let req: undefined | ReturnType<typeof apiCall>
95 const wholePromise = wait(0) // postpone a bit, so that if it is aborted immediately, it is never really fired (happens mostly in dev mode)
96 .then(() => !cmd || aborted ? undefined : req = apiCall<T>(cmd, params, options))
98 - .then(res => aborted || setData(dataRef.current = res as any), err => {
97 + .then(res => aborted || setData(dataRef.current = res as any) || setError(undefined), err => {
98 if (aborted) return
99 setError(err)
100 setData(dataRef.current = undefined)
src/adminApis.ts
+1
@@ -128,6 +128,7 @@ export const adminApis = {
128 autoCheckUpdateResult: autoCheckUpdateResult.get(), // in this form, we get the same type of the serialized json
129 alerts: alerts.get(),
130 proxyDetected: getProxyDetected(),
131 + ram: process.memoryUsage.rss(),
132 frpDetected: localhostAdmin.get() && !getProxyDetected()
133 && getConnections().every(isLocalHost)
134 && await frpDebounced(),