diff --git a/web/containers/Layout/BottomBar/index.tsx b/web/containers/Layout/BottomBar/index.tsx
index d34173ecb..d6a7c05d2 100644
--- a/web/containers/Layout/BottomBar/index.tsx
+++ b/web/containers/Layout/BottomBar/index.tsx
@@ -1,3 +1,5 @@
+import { useEffect } from 'react'
+
import {
Badge,
Button,
@@ -31,6 +33,11 @@ import { useMainViewState } from '@/hooks/useMainViewState'
import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom'
import { downloadedModelsAtom } from '@/helpers/atoms/Model.atom'
+import {
+ cpuUsageAtom,
+ gpusAtom,
+ ramUtilitizedAtom,
+} from '@/helpers/atoms/SystemBar.atom'
const menuLinks = [
{
@@ -47,9 +54,12 @@ const menuLinks = [
const BottomBar = () => {
const { activeModel, stateModel } = useActiveModel()
- const { ram, cpu, gpus } = useGetSystemResources()
+ const { watch, stopWatching } = useGetSystemResources()
const progress = useAtomValue(appDownloadProgress)
const downloadedModels = useAtomValue(downloadedModelsAtom)
+ const gpus = useAtomValue(gpusAtom)
+ const cpu = useAtomValue(cpuUsageAtom)
+ const ramUtilitized = useAtomValue(ramUtilitizedAtom)
const { setMainViewState } = useMainViewState()
const downloadStates = useAtomValue(modelDownloadStateAtom)
@@ -67,6 +77,16 @@ const BottomBar = () => {
return sum
}
+ useEffect(() => {
+ // Watch for resource update
+ watch()
+
+ return () => {
+ stopWatching()
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [])
+
return (
@@ -127,7 +147,7 @@ const BottomBar = () => {
-
+
{gpus.length > 0 && (
diff --git a/web/containers/Providers/DataLoader.tsx b/web/containers/Providers/DataLoader.tsx
index 2b6675d98..d7b630043 100644
--- a/web/containers/Providers/DataLoader.tsx
+++ b/web/containers/Providers/DataLoader.tsx
@@ -3,6 +3,7 @@
import { Fragment, ReactNode } from 'react'
import useAssistants from '@/hooks/useAssistants'
+import useGetSystemResources from '@/hooks/useGetSystemResources'
import useModels from '@/hooks/useModels'
import useThreads from '@/hooks/useThreads'
@@ -14,6 +15,8 @@ const DataLoader: React.FC = ({ children }) => {
useModels()
useThreads()
useAssistants()
+ useGetSystemResources()
+ console.debug('Load Data...')
return {children}
}
diff --git a/web/containers/Providers/EventHandler.tsx b/web/containers/Providers/EventHandler.tsx
index 2369e41bd..f871331b9 100644
--- a/web/containers/Providers/EventHandler.tsx
+++ b/web/containers/Providers/EventHandler.tsx
@@ -282,11 +282,9 @@ export default function EventHandler({ children }: { children: ReactNode }) {
}
useEffect(() => {
- console.log('Registering events')
if (window.core?.events) {
events.on(MessageEvent.OnMessageResponse, onNewMessageResponse)
events.on(MessageEvent.OnMessageUpdate, onMessageResponseUpdate)
-
events.on(ModelEvent.OnModelReady, onModelReady)
events.on(ModelEvent.OnModelFail, onModelInitFailed)
events.on(ModelEvent.OnModelStopped, onModelStopped)
diff --git a/web/containers/Providers/EventListener.tsx b/web/containers/Providers/EventListener.tsx
index 100805e17..938db69c0 100644
--- a/web/containers/Providers/EventListener.tsx
+++ b/web/containers/Providers/EventListener.tsx
@@ -41,14 +41,14 @@ const EventListenerWrapper = ({ children }: PropsWithChildren) => {
)
useEffect(() => {
- console.log('EventListenerWrapper: registering event listeners...')
+ console.debug('EventListenerWrapper: registering event listeners...')
events.on(DownloadEvent.onFileDownloadUpdate, onFileDownloadUpdate)
events.on(DownloadEvent.onFileDownloadError, onFileDownloadError)
events.on(DownloadEvent.onFileDownloadSuccess, onFileDownloadSuccess)
return () => {
- console.log('EventListenerWrapper: unregistering event listeners...')
+ console.debug('EventListenerWrapper: unregistering event listeners...')
events.off(DownloadEvent.onFileDownloadUpdate, onFileDownloadUpdate)
events.off(DownloadEvent.onFileDownloadError, onFileDownloadError)
events.off(DownloadEvent.onFileDownloadSuccess, onFileDownloadSuccess)
diff --git a/web/helpers/atoms/SystemBar.atom.ts b/web/helpers/atoms/SystemBar.atom.ts
index 22a7573ec..3c9a48f79 100644
--- a/web/helpers/atoms/SystemBar.atom.ts
+++ b/web/helpers/atoms/SystemBar.atom.ts
@@ -2,8 +2,10 @@ import { atom } from 'jotai'
export const totalRamAtom = atom(0)
export const usedRamAtom = atom(0)
-export const availableRamAtom = atom(0)
export const cpuUsageAtom = atom(0)
+export const ramUtilitizedAtom = atom(0)
+
+export const gpusAtom = atom[]>([])
export const nvidiaTotalVramAtom = atom(0)
diff --git a/web/hooks/useGetSystemResources.ts b/web/hooks/useGetSystemResources.ts
index 3f71040d7..ef2f30a61 100644
--- a/web/hooks/useGetSystemResources.ts
+++ b/web/hooks/useGetSystemResources.ts
@@ -1,4 +1,4 @@
-import { useEffect, useState } from 'react'
+import { useCallback, useEffect, useState } from 'react'
import { ExtensionTypeEnum, MonitoringExtension } from '@janhq/core'
@@ -6,25 +6,27 @@ import { useSetAtom } from 'jotai'
import { extensionManager } from '@/extension/ExtensionManager'
import {
- availableRamAtom,
cpuUsageAtom,
totalRamAtom,
usedRamAtom,
nvidiaTotalVramAtom,
+ gpusAtom,
+ ramUtilitizedAtom,
} from '@/helpers/atoms/SystemBar.atom'
export default function useGetSystemResources() {
- const [ram, setRam] = useState(0)
- const [cpu, setCPU] = useState(0)
+ const [intervalId, setIntervalId] = useState<
+ NodeJS.Timeout | number | undefined
+ >(undefined)
- const [gpus, setGPUs] = useState[]>([])
const setTotalRam = useSetAtom(totalRamAtom)
+ const setGpus = useSetAtom(gpusAtom)
const setUsedRam = useSetAtom(usedRamAtom)
- const setAvailableRam = useSetAtom(availableRamAtom)
const setCpuUsage = useSetAtom(cpuUsageAtom)
const setTotalNvidiaVram = useSetAtom(nvidiaTotalVramAtom)
+ const setRamUtilitized = useSetAtom(ramUtilitizedAtom)
- const getSystemResources = async () => {
+ const getSystemResources = useCallback(async () => {
if (
!extensionManager.get(
ExtensionTypeEnum.SystemMonitoring
@@ -38,23 +40,20 @@ export default function useGetSystemResources() {
const resourceInfor = await monitoring?.getResourcesInfo()
const currentLoadInfor = await monitoring?.getCurrentLoad()
- const ram =
- (resourceInfor?.mem?.usedMemory ?? 0) /
- (resourceInfor?.mem?.totalMemory ?? 1)
if (resourceInfor?.mem?.usedMemory) setUsedRam(resourceInfor.mem.usedMemory)
if (resourceInfor?.mem?.totalMemory)
setTotalRam(resourceInfor.mem.totalMemory)
- setRam(Math.round(ram * 100))
- if (resourceInfor.mem.totalMemory && resourceInfor.mem.usedMemory)
- setAvailableRam(
- resourceInfor.mem.totalMemory - resourceInfor.mem.usedMemory
- )
- setCPU(Math.round(currentLoadInfor?.cpu?.usage ?? 0))
+ const ramUtilitized =
+ ((resourceInfor?.mem?.usedMemory ?? 0) /
+ (resourceInfor?.mem?.totalMemory ?? 1)) *
+ 100
+ setRamUtilitized(Math.round(ramUtilitized))
+
setCpuUsage(Math.round(currentLoadInfor?.cpu?.usage ?? 0))
const gpus = currentLoadInfor?.gpu ?? []
- setGPUs(gpus)
+ setGpus(gpus)
let totalNvidiaVram = 0
if (gpus.length > 0) {
@@ -65,27 +64,49 @@ export default function useGetSystemResources() {
)
}
setTotalNvidiaVram(totalNvidiaVram)
- }
+ }, [
+ setUsedRam,
+ setTotalRam,
+ setRamUtilitized,
+ setCpuUsage,
+ setGpus,
+ setTotalNvidiaVram,
+ ])
- useEffect(() => {
+ const watch = () => {
getSystemResources()
// Fetch interval - every 2s
- // TODO: Will we really need this?
- // There is a possibility that this will be removed and replaced by the process event hook?
- const intervalId = setInterval(() => {
+ const itv = setInterval(() => {
getSystemResources()
- }, 5000)
+ }, 2000)
+ setIntervalId(itv)
+ }
+ const stopWatching = useCallback(() => {
+ if (intervalId) clearInterval(intervalId)
+ }, [intervalId])
- // clean up interval
- return () => clearInterval(intervalId)
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [])
+ useEffect(() => {
+ getSystemResources()
+ // Component did unmount
+ // Stop watching if any
+ return () => {
+ stopWatching()
+ }
+ }, [getSystemResources, stopWatching])
return {
- totalRamAtom,
- ram,
- cpu,
- gpus,
+ /**
+ * Fetch resource informations once
+ */
+ getSystemResources,
+ /**
+ * Fetch & watch for resource update
+ */
+ watch,
+ /**
+ * Stop watching
+ */
+ stopWatching,
}
}