diff --git a/api/api/versions.json b/api/api/versions.json index 618f42c0..c48d6fc4 100644 --- a/api/api/versions.json +++ b/api/api/versions.json @@ -3,7 +3,7 @@ { "version": "v1", "status": "active", - "release_date": "2025-11-02T13:45:06.273828+05:30", + "release_date": "2025-11-03T02:34:11.994065+05:30", "end_of_life": "0001-01-01T00:00:00Z", "changes": [ "Initial API version" diff --git a/api/internal/features/dashboard/system_stats.go b/api/internal/features/dashboard/system_stats.go index c926d821..d02e2ef0 100644 --- a/api/internal/features/dashboard/system_stats.go +++ b/api/internal/features/dashboard/system_stats.go @@ -165,8 +165,9 @@ func parseLoadAverage(loadStr string) LoadStats { func (m *DashboardMonitor) getCPUStats() CPUStats { cpuStats := CPUStats{ - Overall: 0.0, - PerCore: []CPUCore{}, + Overall: 0.0, + PerCore: []CPUCore{}, + Temperature: 0.0, } perCorePercent, err := cpu.Percent(time.Second, true) @@ -190,6 +191,25 @@ func (m *DashboardMonitor) getCPUStats() CPUStats { } } + // Get CPU temperature using host.SensorsTemperatures + if temps, err := host.SensorsTemperatures(); err == nil && len(temps) > 0 { + // Calculate average temperature from all sensors + var totalTemp float64 + var validReadings int + + for _, temp := range temps { + // Filter for CPU-related sensors and valid temperature readings + if temp.Temperature > 0 && temp.Temperature < 150 { // Reasonable temperature range in Celsius + totalTemp += temp.Temperature + validReadings++ + } + } + + if validReadings > 0 { + cpuStats.Temperature = totalTemp / float64(validReadings) + } + } + return cpuStats } diff --git a/api/internal/features/dashboard/types.go b/api/internal/features/dashboard/types.go index 2b32a0b5..2ef2c662 100644 --- a/api/internal/features/dashboard/types.go +++ b/api/internal/features/dashboard/types.go @@ -63,8 +63,9 @@ type CPUCore struct { } type CPUStats struct { - Overall float64 `json:"overall"` - PerCore []CPUCore `json:"per_core"` + Overall float64 `json:"overall"` + PerCore []CPUCore `json:"per_core"` + Temperature float64 `json:"temperature"` } type MemoryStats struct { diff --git a/view/app/dashboard/components/system/cpu-temperature.tsx b/view/app/dashboard/components/system/cpu-temperature.tsx new file mode 100644 index 00000000..9a9e15ff --- /dev/null +++ b/view/app/dashboard/components/system/cpu-temperature.tsx @@ -0,0 +1,121 @@ +'use client'; + +import React from 'react'; +import { Thermometer } from 'lucide-react'; +import { SystemStatsType } from '@/redux/types/monitor'; +import { TypographySmall, TypographyMuted } from '@/components/ui/typography'; +import { SystemMetricCard } from './system-metric-card'; +import { useSystemMetric } from '../../hooks/use-system-metric'; +import { DEFAULT_METRICS } from '../utils/constants'; +import { CPUTemperatureCardSkeletonContent } from './skeletons/cpu-temperature'; + +interface CPUTemperatureCardProps { + systemStats: SystemStatsType | null; +} + +interface CPUTemperatureDisplayProps { + temperature: number; + label: string; +} + +interface TemperatureGaugeProps { + temperature: number; +} + +const getTemperatureColor = (temp: number): string => { + if (temp < 50) return 'text-blue-500'; + if (temp < 70) return 'text-green-500'; + if (temp < 85) return 'text-orange-500'; + return 'text-red-500'; +}; + +const getTemperatureStatus = (temp: number): string => { + if (temp < 50) return 'Cool'; + if (temp < 70) return 'Normal'; + if (temp < 85) return 'Warm'; + return 'Hot'; +}; + +const CPUTemperatureDisplay: React.FC = ({ temperature, label }) => { + const tempColor = getTemperatureColor(temperature); + const status = getTemperatureStatus(temperature); + + return ( +
+ {label} +
+ {temperature > 0 ? `${temperature.toFixed(1)}°C` : 'N/A'} +
+ {temperature > 0 && ( + {status} + )} +
+ ); +}; + +const TemperatureGauge: React.FC = ({ temperature }) => { + // Calculate percentage based on 0-100°C range + const percentage = Math.min((temperature / 100) * 100, 100); + const gaugeColor = getTemperatureColor(temperature); + + return ( +
+
+ 0°C + 50°C + 100°C +
+
+
+
+
+ Min: 0°C + Max: {temperature > 0 ? `${temperature.toFixed(1)}°C` : 'N/A'} +
+
+ ); +}; + +const CPUTemperatureCard: React.FC = ({ systemStats }) => { + const { + data: cpu, + isLoading, + t + } = useSystemMetric({ + systemStats, + extractData: (stats) => stats.cpu, + defaultData: DEFAULT_METRICS.cpu + }); + + const temperature = cpu.temperature || 0; + + return ( + } + > +
+ + + {temperature === 0 && ( +
+ + Temperature sensors not available on this system + +
+ )} +
+
+ ); +}; + +export default CPUTemperatureCard; + diff --git a/view/app/dashboard/components/system/skeletons/cpu-temperature.tsx b/view/app/dashboard/components/system/skeletons/cpu-temperature.tsx new file mode 100644 index 00000000..d4f9e44c --- /dev/null +++ b/view/app/dashboard/components/system/skeletons/cpu-temperature.tsx @@ -0,0 +1,53 @@ +'use client'; + +import React from 'react'; +import { Thermometer } from 'lucide-react'; +import { Skeleton } from '@/components/ui/skeleton'; +import { TypographyMuted } from '@/components/ui/typography'; +import { SystemMetricCard } from '../system-metric-card'; +import { useSystemMetric } from '../../../hooks/use-system-metric'; +import { DEFAULT_METRICS } from '../../utils/constants'; + +export function CPUTemperatureCardSkeletonContent() { + return ( +
+
+ Current Temperature + + +
+
+
+ 0°C + 50°C + 100°C +
+ +
+ + +
+
+
+ ); +} + +export function CPUTemperatureCardSkeleton() { + const { t } = useSystemMetric({ + systemStats: null, + extractData: (stats) => stats.cpu, + defaultData: DEFAULT_METRICS.cpu + }); + + return ( + } + > +
+ + ); +} + diff --git a/view/app/dashboard/components/utils/constants.ts b/view/app/dashboard/components/utils/constants.ts index 51350e07..2916889e 100644 --- a/view/app/dashboard/components/utils/constants.ts +++ b/view/app/dashboard/components/utils/constants.ts @@ -17,7 +17,8 @@ export const DEFAULT_METRICS = { }, cpu: { overall: 0 as number, - per_core: [] as Array<{ core_id: number; usage: number }> + per_core: [] as Array<{ core_id: number; usage: number }>, + temperature: 0 as number }, memory: { total: 0 as number, diff --git a/view/app/dashboard/page.tsx b/view/app/dashboard/page.tsx index 08bb3390..8df5a0f7 100644 --- a/view/app/dashboard/page.tsx +++ b/view/app/dashboard/page.tsx @@ -6,6 +6,7 @@ import ContainersWidget from './components/containers/containers-widget'; import SystemInfoCard from './components/system/system-info'; import LoadAverageCard from './components/system/load-average'; import CPUUsageCard from './components/system/cpu-usage'; +import CPUTemperatureCard from './components/system/cpu-temperature'; import MemoryUsageCard from './components/system/memory-usage'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Package, ArrowRight, RefreshCw, Info } from 'lucide-react'; @@ -44,7 +45,7 @@ function DashboardPage() { handleLayoutChange } = useDashboard(); - const defaultHiddenWidgets = ['clock', 'network']; + const defaultHiddenWidgets = ['clock', 'network', 'cpu-temperature']; const [hiddenWidgets, setHiddenWidgets] = React.useState(defaultHiddenWidgets); @@ -89,6 +90,7 @@ function DashboardPage() { { id: 'network', label: 'Network Traffic' }, { id: 'load-average', label: 'Load Average' }, { id: 'cpu-usage', label: 'CPU Usage' }, + { id: 'cpu-temperature', label: 'CPU Temperature' }, { id: 'memory-usage', label: 'Memory Usage' }, { id: 'disk-usage', label: 'Disk Usage' }, { id: 'containers', label: 'Containers' } @@ -255,6 +257,11 @@ const MonitoringSection = ({ component: , isDefault: true }, + { + id: 'cpu-temperature', + component: , + isDefault: false + }, { id: 'memory-usage', component: , diff --git a/view/lib/i18n/locales/en.json b/view/lib/i18n/locales/en.json index f5b8f345..5e22e567 100644 --- a/view/lib/i18n/locales/en.json +++ b/view/lib/i18n/locales/en.json @@ -810,7 +810,9 @@ "overall": "Overall", "usage": "Usage (%)", "cores": "Cores", - "perCore": "Per Core" + "perCore": "Per Core", + "temperature": "CPU Temperature", + "current_temp": "Current Temperature" }, "memory": { "title": "Memory Usage", diff --git a/view/lib/i18n/locales/es.json b/view/lib/i18n/locales/es.json index 49629ca9..3ad45d36 100644 --- a/view/lib/i18n/locales/es.json +++ b/view/lib/i18n/locales/es.json @@ -793,7 +793,9 @@ "overall": "General", "usage": "Uso (%)", "cores": "Núcleos", - "perCore": "Por núcleo" + "perCore": "Por núcleo", + "temperature": "Temperatura de CPU", + "current_temp": "Temperatura Actual" }, "memory": { "title": "Uso de memoria", diff --git a/view/lib/i18n/locales/fr.json b/view/lib/i18n/locales/fr.json index add7ba09..0f8fe8ef 100644 --- a/view/lib/i18n/locales/fr.json +++ b/view/lib/i18n/locales/fr.json @@ -794,7 +794,9 @@ "overall": "Global", "usage": "Utilisation (%)", "cores": "Cœurs", - "perCore": "Par cœur" + "perCore": "Par cœur", + "temperature": "Température du CPU", + "current_temp": "Température Actuelle" }, "memory": { "title": "Utilisation de la mémoire", diff --git a/view/lib/i18n/locales/kn.json b/view/lib/i18n/locales/kn.json index a3acc9ea..acece788 100644 --- a/view/lib/i18n/locales/kn.json +++ b/view/lib/i18n/locales/kn.json @@ -790,7 +790,9 @@ "overall": "ಒಟ್ಟಾರೆ", "usage": "ಬಳಕೆ (%)", "cores": "ಕೋರ್‌ಗಳು", - "perCore": "ಪ್ರತಿ ಕೋರ್" + "perCore": "ಪ್ರತಿ ಕೋರ್", + "temperature": "CPU ತಾಪಮಾನ", + "current_temp": "ಪ್ರಸ್ತುತ ತಾಪಮಾನ" }, "memory": { "title": "ಮೆಮೊರಿ ಬಳಕೆ", diff --git a/view/lib/i18n/locales/ml.json b/view/lib/i18n/locales/ml.json index 95f6059d..058504d5 100644 --- a/view/lib/i18n/locales/ml.json +++ b/view/lib/i18n/locales/ml.json @@ -809,7 +809,9 @@ "overall": "മൊത്തത്തിൽ", "usage": "ഉപയോഗം (%)", "cores": "കോറുകൾ", - "perCore": "ഓരോ കോറിനും" + "perCore": "ഓരോ കോറിനും", + "temperature": "CPU താപനില", + "current_temp": "നിലവിലെ താപനില" }, "memory": { "title": "മെമ്മറി ഉപയോഗം", diff --git a/view/redux/types/monitor.ts b/view/redux/types/monitor.ts index 9011d377..c7f8fceb 100644 --- a/view/redux/types/monitor.ts +++ b/view/redux/types/monitor.ts @@ -64,6 +64,7 @@ export interface CPUCore { export interface CPUStats { overall: number; per_core: CPUCore[]; + temperature: number; } export interface NetworkInterface {