Using multiple counts for iostat so we get real data about processes waiting.

This commit is contained in:
Roland 2025-01-22 17:18:16 -07:00
parent 47e1e48587
commit e4f490b90a
No known key found for this signature in database
GPG key ID: 1BA620CE6C9A4680
4 changed files with 18 additions and 14 deletions

View file

@ -96,7 +96,7 @@ function FlagsMessages() {
</>
}
function EvaluateForm({defaultEvaluatedValue = 'Enter an equation above.'}) {
function EvaluateForm() {
const helpContents = <span>
<p>Enter an equation above.</p>

View file

@ -121,7 +121,7 @@ export function NavBar() {
const icon = <Link to='/admin/status' color={color}>
<Icon name='microchip' size='large'/>
</Link>;
memoryIcon = <Popup content={`System Memory: ${memoryPercent}%`} trigger={icon}/>
memoryIcon = <Popup content={`System Memory: ${memoryPercent.toFixed()}%`} trigger={icon}/>
}
// Any disk is busy and processes are waiting.
@ -130,10 +130,10 @@ export function NavBar() {
if (percentIOWait >= 50) {
// Processes are waiting on disk, display a warning icon.
const color = percentIOWait > 75 ? highWarningColor : lowWarningColor;
const icon = <Link to='/admin/status' color={color}>
<Icon name='disk' size='large'/>
const icon = <Link to='/admin/status'>
<Icon name='disk' size='large' color={color}/>
</Link>;
diskWaitIcon = <Popup content={`Processes waiting on disk: ${percentIOWait}`} trigger={icon}/>
diskWaitIcon = <Popup content={`Processes waiting on disk: ${percentIOWait.toFixed()}%`} trigger={icon}/>
}
// CPU temperature.
@ -145,7 +145,7 @@ export function NavBar() {
const name = temperature >= criticalTemperature ? 'thermometer' : 'thermometer half';
const icon = <Icon data-testid='cpuTemperatureIcon' name={name} size='large' color={color}/>
const link = <Link to='/admin/status'>{icon}</Link>;
temperatureIcon = <Popup content={`CPU: ${temperature}°C`} trigger={link}/>;
temperatureIcon = <Popup content={`CPU: ${temperature.toFixed()}°C`} trigger={link}/>;
}
// Power issues, this is always displayed if detected.

View file

@ -227,7 +227,6 @@ __all__ = [
'Base',
'ConfigFile',
'DownloadFileInfo',
'DownloadFileInfoLink',
'LOGGING_CONFIG',
'ModelHelper',
'TRACE_LEVEL',

View file

@ -15,7 +15,7 @@ import jc
from wrolpi.api_utils import api_app, perpetual_signal
from wrolpi.cmd import which
from wrolpi.common import logger, get_warn_once, unique_by_predicate
from wrolpi.common import logger, get_warn_once, unique_by_predicate, partition, TRACE_LEVEL
from wrolpi.dates import now
try:
@ -85,11 +85,9 @@ class IostatInfo:
async def get_iostat_stats() -> IostatInfo:
logger.trace(f'get_iostat_stats called')
try:
proc = await asyncio.create_subprocess_shell(
'iostat',
'iostat 3 2', # 3 second interval to gather more data, get 2 count.
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
@ -97,10 +95,14 @@ async def get_iostat_stats() -> IostatInfo:
if stdout and proc.returncode == 0:
iostat_stats = jc.parse('iostat', stdout.decode(), quiet=True)
if iostat_stats:
cpu_stats, *_ = iostat_stats
cpu_statuses, _ = partition(lambda i: i['type'] == 'cpu', iostat_stats)
_, cpu_stats = cpu_statuses # Use the second status because the first is a lie.
logger.trace(
f'get_iostat_stats got percent_iowait={cpu_stats["percent_iowait"]} percent_idle={cpu_stats["percent_idle"]}')
if logger.isEnabledFor(TRACE_LEVEL):
logger.trace(
f'get_iostat_stats'
f' percent_iowait={cpu_stats["percent_iowait"]}'
f' percent_idle={cpu_stats["percent_idle"]}')
# Return only the CPU stats.
return IostatInfo(
percent_idle=cpu_stats['percent_idle'],
@ -111,6 +113,8 @@ async def get_iostat_stats() -> IostatInfo:
percent_user=cpu_stats['percent_user'],
)
except Exception as e:
if logger.isEnabledFor(TRACE_LEVEL):
logger.trace(f'get_iostat_stats failed: {e}')
warn_iostat_once(e)
return IostatInfo()
@ -164,6 +168,7 @@ TOP_REGEX = re.compile(r'^%Cpu\(s\):\s+(\d+\.\d+)', re.MULTILINE)
CORE_COUNT = multiprocessing.cpu_count()
async def get_cpu_stats() -> CPUInfo:
"""Get core count, max freq, min freq, current freq, cpu temperature."""
percent = int(psutil.cpu_percent())