nohang/tools/psi2log
Alexey Avramov 013a73bcd3 fix psi2log
2019-11-24 06:42:38 +09:00

368 lines
9.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""psi2log"""
import os
from time import sleep
from ctypes import CDLL
from sys import stdout, exit
from argparse import ArgumentParser
from signal import signal, SIGTERM, SIGINT, SIGQUIT, SIGHUP
def form(num):
"""
"""
s = str(num).split('.')
return '{}.{:0<2}'.format(s[0], s[1])
def signal_handler(signum, frame):
"""
"""
def signal_handler_inner(signum, frame):
pass
for i in sig_list:
signal(i, signal_handler_inner)
log('')
lpd = len(peaks_dict)
if lpd != 15:
exit()
log('Peak values: avg10 avg60 avg300')
log('----------- ------ ------ ------')
log('some cpu {:>6} {:>6} {:>6}'.format(
form(peaks_dict['c_some_avg10']),
form(peaks_dict['c_some_avg60']),
form(peaks_dict['c_some_avg300']),
))
log('----------- ------ ------ ------')
log('some memory {:>6} {:>6} {:>6}'.format(
form(peaks_dict['m_some_avg10']),
form(peaks_dict['m_some_avg60']),
form(peaks_dict['m_some_avg300']),
))
log('full memory {:>6} {:>6} {:>6}'.format(
form(peaks_dict['m_full_avg10']),
form(peaks_dict['m_full_avg60']),
form(peaks_dict['m_full_avg300']),
))
log('----------- ------ ------ ------')
log('some io {:>6} {:>6} {:>6}'.format(
form(peaks_dict['i_some_avg10']),
form(peaks_dict['i_some_avg60']),
form(peaks_dict['i_some_avg300']),
))
log('full io {:>6} {:>6} {:>6}'.format(
form(peaks_dict['i_full_avg10']),
form(peaks_dict['i_full_avg60']),
form(peaks_dict['i_full_avg300']),
))
exit()
def cgroup2_root():
"""
"""
with open(mounts) as f:
for line in f:
if cgroup2_separator in line:
return line.partition(cgroup2_separator)[0].partition(' ')[2]
def mlockall():
"""
"""
MCL_CURRENT = 1
MCL_FUTURE = 2
MCL_ONFAULT = 4
CDLL('libc.so.6').mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT)
def psi_file_mem_to_metrics(psi_path):
"""
"""
with open(psi_path) as f:
psi_list = f.readlines()
some_list, full_list = psi_list[0].split(' '), psi_list[1].split(' ')
some_avg10 = some_list[1].split('=')[1]
some_avg60 = some_list[2].split('=')[1]
some_avg300 = some_list[3].split('=')[1]
full_avg10 = full_list[1].split('=')[1]
full_avg60 = full_list[2].split('=')[1]
full_avg300 = full_list[3].split('=')[1]
return (some_avg10, some_avg60, some_avg300,
full_avg10, full_avg60, full_avg300)
def psi_file_cpu_to_metrics(psi_path):
"""
"""
with open(psi_path) as f:
psi_list = f.readlines()
some_list = psi_list[0].split(' ')
some_avg10 = some_list[1].split('=')[1]
some_avg60 = some_list[2].split('=')[1]
some_avg300 = some_list[3].split('=')[1]
return (some_avg10, some_avg60, some_avg300)
def log(*msg):
"""
"""
print(*msg)
if separate_log:
logging.info(*msg)
parser = ArgumentParser()
parser.add_argument(
'-t',
'--target',
help="""target (cgroup2 or SYTSTEM_WIDE)""",
default='SYSTEM_WIDE',
type=str
)
parser.add_argument(
'-p',
'--period',
help="""period in sec""",
default=2,
type=float
)
parser.add_argument(
'-l',
'--log',
help="""path to log file""",
default=None,
type=str
)
args = parser.parse_args()
target = args.target
period = args.period
log_file = args.log
if log_file is None:
separate_log = False
else:
separate_log = True
import logging
sig_list = [SIGTERM, SIGINT, SIGQUIT, SIGHUP]
for i in sig_list:
signal(i, signal_handler)
if separate_log:
logging.basicConfig(
filename=log_file,
level=logging.INFO,
format="%(asctime)s: %(message)s")
log('Starting psi2log')
log('target: {}'.format(target))
log('period: {}'.format(period))
if log_file is not None:
log('log file: {}'.format(log_file))
if not os.path.exists('/proc/pressure'):
log('ERROR: /proc/pressure does not exist, PSI is not supported, exit')
exit()
if target == 'SYSTEM_WIDE':
cpu_file = "/proc/pressure/cpu"
memory_file = "/proc/pressure/memory"
io_file = "/proc/pressure/io"
else:
mounts = '/proc/mounts'
cgroup2_separator = ' cgroup2 rw,'
cgroup2_mountpoint = cgroup2_root()
if cgroup2_mountpoint is None:
log('ERROR: unified cgroup hierarchy is not mounted, exit')
exit()
else:
log('cgroup2 mountpoint: {}'.format(cgroup2_mountpoint))
cpu_file = cgroup2_mountpoint + target + "/cpu.pressure"
memory_file = cgroup2_mountpoint + target + "/memory.pressure"
io_file = cgroup2_mountpoint + target + "/io.pressure"
mlockall()
log('----------------------------------------------------------------------'
'--------------------------------------------')
log(' some cpu pressure || some memory pressure | full memory pressure ||'
' some io pressure | full io pressure')
log('---------------------||----------------------|----------------------||'
'----------------------|---------------------')
log(' avg10 avg60 avg300 || avg10 avg60 avg300 | avg10 avg60 avg300 ||'
' avg10 avg60 avg300 | avg10 avg60 avg300')
log('------ ------ ------ || ------ ------ ------ | ------ ------ ------ ||'
' ------ ------ ------ | ------ ------ ------')
peaks_dict = dict()
while True:
if not os.path.exists(cpu_file):
log('ERROR: cpu pressure file does not exist: {}'.format(cpu_file))
sleep(period)
continue
if not os.path.exists(memory_file):
log('ERROR: memory pressure file does not exist: {}'.format(
memory_file))
sleep(period)
continue
if not os.path.exists(io_file):
log('ERROR: io pressure file does not exist: {}'.format(cpu_file))
sleep(period)
continue
(c_some_avg10, c_some_avg60, c_some_avg300
) = psi_file_cpu_to_metrics(cpu_file)
(m_some_avg10, m_some_avg60, m_some_avg300,
m_full_avg10, m_full_avg60, m_full_avg300
) = psi_file_mem_to_metrics(memory_file)
(i_some_avg10, i_some_avg60, i_some_avg300,
i_full_avg10, i_full_avg60, i_full_avg300
) = psi_file_mem_to_metrics(io_file)
log('{:>6} {:>6} {:>6} || {:>6} {:>6} {:>6} | {:>6} {:>6} {:>6} || {:>6}'
' {:>6} {:>6} | {:>6} {:>6} {:>6}'.format(
c_some_avg10, c_some_avg60, c_some_avg300,
m_some_avg10, m_some_avg60, m_some_avg300,
m_full_avg10, m_full_avg60, m_full_avg300,
i_some_avg10, i_some_avg60, i_some_avg300,
i_full_avg10, i_full_avg60, i_full_avg300
))
c_some_avg10 = float(c_some_avg10)
if ('c_some_avg10' not in peaks_dict or
peaks_dict['c_some_avg10'] < c_some_avg10):
peaks_dict['c_some_avg10'] = c_some_avg10
c_some_avg60 = float(c_some_avg60)
if ('c_some_avg60' not in peaks_dict or
peaks_dict['c_some_avg60'] < c_some_avg60):
peaks_dict['c_some_avg60'] = c_some_avg60
c_some_avg300 = float(c_some_avg300)
if ('c_some_avg300' not in peaks_dict or
peaks_dict['c_some_avg300'] < c_some_avg300):
peaks_dict['c_some_avg300'] = c_some_avg300
#######################################################################
m_some_avg10 = float(m_some_avg10)
if ('m_some_avg10' not in peaks_dict or
peaks_dict['m_some_avg10'] < m_some_avg10):
peaks_dict['m_some_avg10'] = m_some_avg10
m_some_avg60 = float(m_some_avg60)
if ('m_some_avg60' not in peaks_dict or
peaks_dict['m_some_avg60'] < m_some_avg60):
peaks_dict['m_some_avg60'] = m_some_avg60
m_some_avg300 = float(m_some_avg300)
if ('m_some_avg300' not in peaks_dict or
peaks_dict['m_some_avg300'] < m_some_avg300):
peaks_dict['m_some_avg300'] = m_some_avg300
m_full_avg10 = float(m_full_avg10)
if ('m_full_avg10' not in peaks_dict or
peaks_dict['m_full_avg10'] < m_full_avg10):
peaks_dict['m_full_avg10'] = m_full_avg10
m_full_avg60 = float(m_full_avg60)
if ('m_full_avg60' not in peaks_dict or
peaks_dict['m_full_avg60'] < m_full_avg60):
peaks_dict['m_full_avg60'] = m_full_avg60
m_full_avg300 = float(m_full_avg300)
if ('m_full_avg300' not in peaks_dict or
peaks_dict['m_full_avg300'] < m_full_avg300):
peaks_dict['m_full_avg300'] = m_full_avg300
#######################################################################
i_some_avg10 = float(i_some_avg10)
if ('i_some_avg10' not in peaks_dict or
peaks_dict['i_some_avg10'] < i_some_avg10):
peaks_dict['i_some_avg10'] = i_some_avg10
i_some_avg60 = float(i_some_avg60)
if ('i_some_avg60' not in peaks_dict or
peaks_dict['i_some_avg60'] < i_some_avg60):
peaks_dict['i_some_avg60'] = i_some_avg60
i_some_avg300 = float(i_some_avg300)
if ('i_some_avg300' not in peaks_dict or
peaks_dict['i_some_avg300'] < i_some_avg300):
peaks_dict['i_some_avg300'] = i_some_avg300
i_full_avg10 = float(i_full_avg10)
if ('i_full_avg10' not in peaks_dict or
peaks_dict['i_full_avg10'] < i_full_avg10):
peaks_dict['i_full_avg10'] = i_full_avg10
i_full_avg60 = float(i_full_avg60)
if ('i_full_avg60' not in peaks_dict or
peaks_dict['i_full_avg60'] < i_full_avg60):
peaks_dict['i_full_avg60'] = i_full_avg60
i_full_avg300 = float(i_full_avg300)
if ('i_full_avg300' not in peaks_dict or
peaks_dict['i_full_avg300'] < i_full_avg300):
peaks_dict['i_full_avg300'] = i_full_avg300
stdout.flush()
sleep(period)