-
-
Notifications
You must be signed in to change notification settings - Fork 71
feat: add cpu temp as optional metric #558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
72e8602
1e559fd
4cd203b
22c67de
b4017b5
612870d
0eaec47
11d3726
e005655
1c2dc92
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<CPUTemperatureDisplayProps> = ({ temperature, label }) => { | ||
| const tempColor = getTemperatureColor(temperature); | ||
| const status = getTemperatureStatus(temperature); | ||
|
|
||
| return ( | ||
| <div className="text-center"> | ||
| <TypographyMuted className="text-xs">{label}</TypographyMuted> | ||
| <div className={`text-4xl font-bold ${tempColor} mt-1`}> | ||
| {temperature > 0 ? `${temperature.toFixed(1)}°C` : 'N/A'} | ||
| </div> | ||
| {temperature > 0 && ( | ||
| <TypographyMuted className="text-xs mt-1">{status}</TypographyMuted> | ||
| )} | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| const TemperatureGauge: React.FC<TemperatureGaugeProps> = ({ temperature }) => { | ||
| // Calculate percentage based on 0-100°C range | ||
| const percentage = Math.min((temperature / 100) * 100, 100); | ||
| const gaugeColor = getTemperatureColor(temperature); | ||
|
|
||
| return ( | ||
| <div className="space-y-2"> | ||
| <div className="flex justify-between text-xs text-muted-foreground"> | ||
| <span>0°C</span> | ||
| <span>50°C</span> | ||
| <span>100°C</span> | ||
| </div> | ||
| <div className="w-full bg-secondary rounded-full h-4 overflow-hidden"> | ||
| <div | ||
| className={`h-full ${gaugeColor} transition-all duration-300 rounded-full`} | ||
| style={{ | ||
| width: `${percentage}%`, | ||
| backgroundColor: 'currentColor' | ||
| }} | ||
| /> | ||
| </div> | ||
| <div className="flex justify-between text-xs"> | ||
| <TypographyMuted>Min: 0°C</TypographyMuted> | ||
| <TypographyMuted>Max: {temperature > 0 ? `${temperature.toFixed(1)}°C` : 'N/A'}</TypographyMuted> | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| const CPUTemperatureCard: React.FC<CPUTemperatureCardProps> = ({ systemStats }) => { | ||
| const { | ||
| data: cpu, | ||
| isLoading, | ||
| t | ||
| } = useSystemMetric({ | ||
| systemStats, | ||
| extractData: (stats) => stats.cpu, | ||
| defaultData: DEFAULT_METRICS.cpu | ||
| }); | ||
|
|
||
| const temperature = cpu.temperature || 0; | ||
|
|
||
| return ( | ||
| <SystemMetricCard | ||
| title={t('dashboard.cpu.temperature')} | ||
| icon={Thermometer} | ||
| isLoading={isLoading} | ||
| skeletonContent={<CPUTemperatureCardSkeletonContent />} | ||
| > | ||
| <div className="space-y-6"> | ||
| <CPUTemperatureDisplay temperature={temperature} label={t('dashboard.cpu.current_temp')} /> | ||
| <TemperatureGauge temperature={temperature} /> | ||
| {temperature === 0 && ( | ||
| <div className="text-center"> | ||
| <TypographySmall className="text-muted-foreground"> | ||
| Temperature sensors not available on this system | ||
| </TypographySmall> | ||
| </div> | ||
| )} | ||
| </div> | ||
| </SystemMetricCard> | ||
| ); | ||
| }; | ||
|
|
||
| export default CPUTemperatureCard; | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 ( | ||
| <div className="space-y-6"> | ||
| <div className="text-center"> | ||
| <TypographyMuted className="text-xs">Current Temperature</TypographyMuted> | ||
| <Skeleton className="h-12 w-32 mx-auto mt-1" /> | ||
| <Skeleton className="h-4 w-16 mx-auto mt-1" /> | ||
| </div> | ||
| <div className="space-y-2"> | ||
| <div className="flex justify-between text-xs text-muted-foreground"> | ||
| <span>0°C</span> | ||
| <span>50°C</span> | ||
| <span>100°C</span> | ||
| </div> | ||
| <Skeleton className="h-4 w-full rounded-full" /> | ||
| <div className="flex justify-between"> | ||
| <Skeleton className="h-3 w-16" /> | ||
| <Skeleton className="h-3 w-16" /> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
|
Comment on lines
+11
to
+33
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use translation key instead of hardcoded text. Line 15 hardcodes "Current Temperature" while the actual component uses Apply this diff: -export function CPUTemperatureCardSkeletonContent() {
+export function CPUTemperatureCardSkeletonContent({ label }: { label: string }) {
return (
<div className="space-y-6">
<div className="text-center">
- <TypographyMuted className="text-xs">Current Temperature</TypographyMuted>
+ <TypographyMuted className="text-xs">{label}</TypographyMuted>
<Skeleton className="h-12 w-32 mx-auto mt-1" />Then pass the translated label from CPUTemperatureCardSkeleton: return (
<SystemMetricCard
title={t('dashboard.cpu.temperature')}
icon={Thermometer}
isLoading={true}
- skeletonContent={<CPUTemperatureCardSkeletonContent />}
+ skeletonContent={<CPUTemperatureCardSkeletonContent label={t('dashboard.cpu.current_temp')} />}
>
🤖 Prompt for AI Agents |
||
|
|
||
| export function CPUTemperatureCardSkeleton() { | ||
| const { t } = useSystemMetric({ | ||
| systemStats: null, | ||
| extractData: (stats) => stats.cpu, | ||
| defaultData: DEFAULT_METRICS.cpu | ||
| }); | ||
|
|
||
| return ( | ||
| <SystemMetricCard | ||
| title={t('dashboard.cpu.temperature')} | ||
| icon={Thermometer} | ||
| isLoading={true} | ||
| skeletonContent={<CPUTemperatureCardSkeletonContent />} | ||
| > | ||
| <div /> | ||
| </SystemMetricCard> | ||
| ); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment is misleading; consider filtering by sensor name.
The comment on line 201 states "Filter for CPU-related sensors" but the code only filters by temperature range (0-150°C) and doesn't distinguish between CPU, GPU, disk, or other thermal sensors. This can result in an average that includes non-CPU temperatures, making the "CPU Temperature" metric inaccurate.
Consider filtering by sensor name/type to only include CPU sensors:
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 + // Filter for CPU-related sensors by name and valid temperature readings + sensorName := strings.ToLower(temp.SensorKey) + isCPUSensor := strings.Contains(sensorName, "cpu") || + strings.Contains(sensorName, "core") || + strings.Contains(sensorName, "proc") + if isCPUSensor && temp.Temperature > 0 && temp.Temperature < 150 { totalTemp += temp.Temperature validReadings++ } }You'll need to add
"strings"to the imports if not already present.🤖 Prompt for AI Agents