From 8aaf2fb76ed196aa34079ca0e96b2f254bb40557 Mon Sep 17 00:00:00 2001 From: iipeace Date: Mon, 23 Sep 2024 23:30:09 +0900 Subject: [PATCH] draw: Add per-resource filters Signed-off-by: iipeace --- guider/guider.py | 225 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 167 insertions(+), 58 deletions(-) diff --git a/guider/guider.py b/guider/guider.py index a991622f..a9884ce3 100755 --- a/guider/guider.py +++ b/guider/guider.py @@ -7,7 +7,7 @@ __credits__ = "Peace Lee" __license__ = "GPLv2" __version__ = "3.9.8" -__revision__ = "240921" +__revision__ = "240923" __maintainer__ = "Peace Lee" __email__ = "iipeace5@gmail.com" __repository__ = "https://github.com/iipeace/guider" @@ -28772,6 +28772,15 @@ def killProcGroup(pid, sig=None): except: pass + @staticmethod + def getMaxPidLen(pidList): + try: + return max(map(lambda x: len(x), pidList)) + except SystemExit: + sys.exit(0) + except: + return SysMgr.pidDigit + @staticmethod def getSysSummary(length=0): # get system info # @@ -38624,8 +38633,12 @@ def printHelp(force=False, isExit=True): # {0:1} {1:1} {4:1} -a # {0:1} {1:1} {3:1} -a - - {2:1} with I/O filter - # {0:1} {1:1} {4:1} -q IOFILTER:"[BR]", IOFILTER:"[NI]", IOFILTER:lo + - {2:1} with per-resource filters + # {0:1} {1:1} {4:1} -q CPUPROCFILTER:"*system*" + # {0:1} {1:1} {4:1} -q GPUFILTER:"*nvidia*" + # {0:1} {1:1} {4:1} -q MEMFILTER:"Available", MEMFILTER:"User" + # {0:1} {1:1} {4:1} -q MEMPROCFILTER:"*system*" + # {0:1} {1:1} {4:1} -q IOFILTER:"BR", IOFILTER:"NI", IOFILTER:lo # {0:1} {1:1} {4:1} -q IOPROCFILTER:"*system*" - {2:1} except for load plots including CPU and I/O usage @@ -38671,9 +38684,11 @@ def printHelp(force=False, isExit=True): - {2:1} with stacked stats # {0:1} {1:1} {4:1} -q STACKEDPLOT + # {0:1} {1:1} {4:1} -q STACKEDDIFFPLOT - {2:1} with accumulated stats # {0:1} {1:1} {4:1} -q STACKEDPLOT, ACCUMULATE + # {0:1} {1:1} {4:1} -q STACKEDDIFFPLOT, ACCUMULATE - {2:1} without system info # {0:1} {1:1} {4:1} -q NOSYSINFO @@ -43034,6 +43049,9 @@ def _getDesc(s, t=0): - {2:1} with maximum file count # {0:1} {1:1} "tc*.out" -q MAXFILE:4 + - {2:1} with maximum comm length + # {0:1} {1:1} "tc*.out" -q COMMLEN:4 + - {2:1} with error range # {0:1} {1:1} "tc*.out" -q CPUERRRANGE:1, GPUERRRANGE:10, MEMERRRANGE:20, SDERRRANGE:1 @@ -119542,6 +119560,7 @@ def getStatsFile( netWrite = [] gpuUsage = {} psiUsage = {} + coreUsage = {} cpuProcUsage = {} cpuProcDelay = {} cpuProcPrio = {} @@ -119616,6 +119635,11 @@ def getStatsFile( # define shortcuts # convSize = UtilMgr.convUnit2Size + # get comm length limit # + commLen = SysMgr.environList.get("COMMLEN", [None])[0] + if commLen: + commLen = long(commLen) + curSize = 0 for idx, line in enumerate(fd): # check EOF # @@ -119822,7 +119846,7 @@ def getStatsFile( continue d = m.groupdict() - comm = d["comm"].strip() + comm = d["comm"].strip()[:commLen] if SysMgr.filterGroup: if not TaskAnalyzer.checkFilter(comm, d["pid"]): @@ -119970,7 +119994,7 @@ def getStatsFile( continue d = m.groupdict() - comm = d["comm"].strip("^ ") + comm = d["comm"].strip("^ ")[:commLen] if not SysMgr.filterGroup: pid = d["pid"] @@ -120011,7 +120035,7 @@ def getStatsFile( continue d = m.groupdict() - comm = d["comm"].strip("^ ") + comm = d["comm"].strip("^ ")[:commLen] if not SysMgr.filterGroup: pid = d["pid"] @@ -120065,7 +120089,7 @@ def getStatsFile( continue d = m.groupdict() - comm = d["comm"].strip() + comm = d["comm"].strip()[:commLen] if not SysMgr.filterGroup: pid = d["pid"] @@ -120105,14 +120129,14 @@ def getStatsFile( # Storage # elif context == "Storage": if slen == 3: - sname = sline[0].strip() + gname = sline[0].strip() intervalList = sline[2] elif slen == 2: if intervalList: intervalList += sline[1] - elif intervalList and not sname in ("Device", "Storage"): + elif intervalList and not gname in ("Device", "Storage"): # define arrays # - storageUsage.setdefault(sname, {}) + storageUsage.setdefault(gname, {}) busyList = [] readList = [] writeList = [] @@ -120130,23 +120154,23 @@ def getStatsFile( freeList.append(convSize(free) >> 10) # save previous info # - storageUsage[sname]["busy"] = busyList - storageUsage[sname]["read"] = readList - storageUsage[sname]["write"] = writeList - storageUsage[sname]["free"] = freeList + storageUsage[gname]["busy"] = busyList + storageUsage[gname]["read"] = readList + storageUsage[gname]["write"] = writeList + storageUsage[gname]["free"] = freeList intervalList = None # Network # elif context == "Network": if slen == 3: - sname = sline[0].strip() + gname = sline[0].strip() intervalList = sline[2] elif slen == 2: if intervalList: intervalList += sline[1] - elif intervalList and not sname in ("Device", "Network"): + elif intervalList and not gname in ("Device", "Network"): # define arrays # - networkUsage.setdefault(sname, {}) + networkUsage.setdefault(gname, {}) recvList = [] tranList = [] @@ -120160,8 +120184,8 @@ def getStatsFile( tranList.append(convSize(tran) >> 10) # save previous info # - networkUsage[sname]["recv"] = recvList - networkUsage[sname]["tran"] = tranList + networkUsage[gname]["recv"] = recvList + networkUsage[gname]["tran"] = tranList intervalList = None # Memory # @@ -120173,7 +120197,7 @@ def getStatsFile( if m: d = m.groupdict() pid = d["pid"] - comm = d["comm"].strip() + comm = d["comm"].strip()[:commLen] pname = "%s(%s)" % (comm, pid) chartStats[pname] = {} @@ -120212,7 +120236,7 @@ def getStatsFile( if slen == 3: if not sline[0].startswith("Cgroup"): - comm = sline[0].strip() + comm = sline[0].strip()[:commLen] if SysMgr.filterGroup: if not TaskAnalyzer.checkFilter(comm, pid): @@ -120283,6 +120307,19 @@ def getStatsFile( tdict[statNames["avg"]] = sum(rlist) / len(rlist) tdict[statNames["max"]] = max(rlist) + # Core # + elif context == "Core": + if slen == 3: + gname = sline[0].strip() + intervalList = sline[2] + elif slen == 2: + if intervalList: + intervalList += sline[1] + elif intervalList: + # save previous info # + coreUsage[gname] = intervalList + intervalList = None + # Event # elif context == "Event": if slen != 4: @@ -120417,7 +120454,7 @@ def getStatsFile( value[nmUsage] = value[nmUsage].split()[imin:imax] value[nmUsage] = " ".join(value[nmUsage]) - for resUsage in (gpuUsage, psiUsage): + for resUsage in (gpuUsage, psiUsage, coreUsage): for name, value in resUsage.items(): value = value.split()[imin:imax] resUsage[name] = " ".join(value) @@ -120466,6 +120503,7 @@ def getStatsFile( "timeline": timeline[imin:imax], "eventList": eventList[imin:imax], "cpuUsage": cpuUsage[imin:imax], + "coreUsage": coreUsage, "cpuProcUsage": cpuProcUsage, "cpuProcDelay": cpuProcDelay, "cpuProcPrio": cpuProcPrio, @@ -121485,7 +121523,7 @@ def drawYticks( rymin = SysMgr.maxSize rymax = -(SysMgr.maxSize) for l in ax.get_lines(): - yvals = l.get_data()[1] + yvals = list(map(lambda x: x if x else 0, l.get_data()[1])) rymin = min(rymin, min(yvals)) rymax = max(rymax, max(yvals)) @@ -123652,6 +123690,9 @@ def _drawCpu(graphStats, xtype, pos, size, delay=False): labelList = [] hasLabel = not "NOLABEL" in SysMgr.environList + # get GPU filter # + gpuFilter = SysMgr.environList.get("GPUFILTER", []) + # get minimum timeline # timeline = None for key, val in graphStats.items(): @@ -123664,7 +123705,9 @@ def _drawCpu(graphStats, xtype, pos, size, delay=False): lent = len(timeline) # get stacked plot option # - stacked = "STACKEDPLOT" in SysMgr.environList and not diffOpt + stacked = ( + "STACKEDPLOT" in SysMgr.environList and not diffOpt + ) or "STACKEDDIFFPLOT" in SysMgr.environList stackedStats = [] stackedTexts = [] @@ -123722,6 +123765,12 @@ def _drawCpu(graphStats, xtype, pos, size, delay=False): if not delay and isVisibleTotal and SysMgr.gpuEnable: # ------------------ Total GPU usage ------------------ # for gpu, stat in gpuUsage.items(): + # check skip condition # + if gpuFilter and not UtilMgr.isValidStr( + gpu, gpuFilter + ): + continue + # get stats # stat = list(map(long, stat.split()))[:lent] @@ -123814,6 +123863,8 @@ def _drawCpu(graphStats, xtype, pos, size, delay=False): # get stats # for idx, item in enumerate(blkWait): blkWait[idx] += cpuUsage[idx] + else: + blkWait = [0] * len(blkWait) # define PSI colors # psiColors = { @@ -124085,6 +124136,9 @@ def _drawCpu(graphStats, xtype, pos, size, delay=False): else: minCpuCond = 0 + # get process filter # + cpuProcFilter = SysMgr.environList.get("CPUPROCFILTER", []) + # Process CPU usage # for idx, item in sorted( targetList.items(), @@ -124103,6 +124157,12 @@ def _drawCpu(graphStats, xtype, pos, size, delay=False): ): continue + # check process filter # + if cpuProcFilter and not UtilMgr.isValidStr( + idx, cpuProcFilter + ): + continue + # check max cpu condition # if item["maximum"] < maxCpuCond: continue @@ -124340,7 +124400,9 @@ def _drawPrio(graphStats, xtype, pos, size): lent = len(timeline) # get stacked plot option # - stacked = "STACKEDPLOT" in SysMgr.environList and not diffOpt + stacked = ( + "STACKEDPLOT" in SysMgr.environList and not diffOpt + ) or "STACKEDDIFFPLOT" in SysMgr.environList stackedStats = [] stackedTexts = [] @@ -124611,7 +124673,9 @@ def __drawSystemIo( ): if not statList: return -1, ymax - elif ioFilter and not UtilMgr.isValidStr(name, ioFilter): + elif ioFilter and not UtilMgr.isValidStr( + name.strip("[]"), ioFilter + ): return -1, ymax usage = list(map(long, statList))[:lent] @@ -124734,7 +124798,9 @@ def __drawSystemIo( convSize = UtilMgr.convSize2Unit # get stacked plot option # - stacked = "STACKEDPLOT" in SysMgr.environList and not diffOpt + stacked = ( + "STACKEDPLOT" in SysMgr.environList and not diffOpt + ) or "STACKEDDIFFPLOT" in SysMgr.environList stackedStats = [] stackedTexts = [] @@ -124872,7 +124938,7 @@ def __drawSystemIo( if usage[minIdx] == usage[maxIdx] == 0: addLabel = False elif ioFilter and ( - not UtilMgr.isValidStr(ptype, ioFilter) + not UtilMgr.isValidStr(ptype.strip("[]"), ioFilter) or not UtilMgr.isValidStr(idx, ioFilter) ): addLabel = False @@ -124961,7 +125027,7 @@ def __drawSystemIo( if usage[minIdx] == usage[maxIdx] == 0: addLabel = False elif ioFilter and ( - not UtilMgr.isValidStr(ptype, ioFilter) + not UtilMgr.isValidStr(ptype.strip("[]"), ioFilter) or not UtilMgr.isValidStr(idx, ioFilter) ): addLabel = False @@ -125020,7 +125086,7 @@ def __drawSystemIo( ), reverse=True, ): - # check skip condition # + # check process filter # if ioProcFilter and not UtilMgr.isValidStr( idx, ioProcFilter ): @@ -125291,6 +125357,10 @@ def __drawSystemMem(statList, color, ymax, name): # set label variable # hasLabel = not "NOLABEL" in SysMgr.environList + # get mem filter # + memFilter = SysMgr.environList.get("MEMFILTER", []) + memProcFilter = SysMgr.environList.get("MEMPROCFILTER", []) + # draw title # ax = subplot2grid((6, 1), (pos, 0), rowspan=size, colspan=1) ax.xaxis.set_major_locator(MaxNLocator(integer=True)) @@ -125317,7 +125387,9 @@ def __drawSystemMem(statList, color, ymax, name): tcnt = 0 # get stacked plot option # - stacked = "STACKEDPLOT" in SysMgr.environList and not diffOpt + stacked = ( + "STACKEDPLOT" in SysMgr.environList and not diffOpt + ) or "STACKEDDIFFPLOT" in SysMgr.environList stackedStats = [] stackedTexts = [] @@ -125408,9 +125480,14 @@ def __drawMemPlots(ymax, stacked=False): __drawSysMem = __drawSystemMem # System Available(Free) Memory # - lastsize, ymax = __drawSysMem( - memFree, "blue", ymax, "[RA]" - ) + if memFilter and not UtilMgr.isValidStr( + "Available", memFilter + ): + lastsize = None + else: + lastsize, ymax = __drawSysMem( + memFree, "blue", ymax, "[RA]" + ) if lastsize is not None: if totalRam: label = "%s< RAM Total > - %s" % ( @@ -125432,36 +125509,52 @@ def __drawMemPlots(ymax, stacked=False): ) # System User(Anon) Memory # - lastsize, ymax = __drawSysMem( - memAnon, "skyblue", ymax, "[RU]" - ) + if memFilter and not UtilMgr.isValidStr("User", memFilter): + lastsize = None + else: + lastsize, ymax = __drawSysMem( + memAnon, "skyblue", ymax, "[RU]" + ) if lastsize is not None: labelList.append( "%sRAM User - %s" % (prefix, lastsize) ) # System Cache Memory # - lastsize, ymax = __drawSysMem( - memCache, "darkgray", ymax, "[RC]" - ) + if memFilter and not UtilMgr.isValidStr( + "Cache", memFilter + ): + lastsize = None + else: + lastsize, ymax = __drawSysMem( + memCache, "darkgray", ymax, "[RC]" + ) if lastsize is not None: labelList.append( "%sRAM Cache - %s" % (prefix, lastsize) ) # System Kernel Memory # - lastsize, ymax = __drawSysMem( - memKernel, "purple", ymax, "[RK]" - ) + if memFilter and not UtilMgr.isValidStr( + "Kernel", memFilter + ): + lastsize = None + else: + lastsize, ymax = __drawSysMem( + memKernel, "purple", ymax, "[RK]" + ) if lastsize is not None: labelList.append( "%sRAM Kernel - %s" % (prefix, lastsize) ) # System Swap Memory # - lastsize, ymax = __drawSysMem( - swapUsage, "orange", ymax, "[RS]" - ) + if memFilter and not UtilMgr.isValidStr("Swap", memFilter): + lastsize = None + else: + lastsize, ymax = __drawSysMem( + swapUsage, "orange", ymax, "[RS]" + ) if lastsize is not None: if totalSwap: label = "%s< Swap Total > - %s" % ( @@ -125512,6 +125605,12 @@ def __drawMemPlots(ymax, stacked=False): ), reverse=True, ): + # check process filter # + if memProcFilter and not UtilMgr.isValidStr( + key, memProcFilter + ): + continue + usage = list(map(long, item["vssUsage"].split()))[ :lent ] @@ -125521,7 +125620,7 @@ def __drawMemPlots(ymax, stacked=False): if ymax < maxusage: ymax = maxusage - # check max vss conditino # + # check max vss condition # if maxusage < maxVssCond: continue @@ -125613,6 +125712,12 @@ def __drawMemPlots(ymax, stacked=False): ), reverse=True, ): + # check process filter # + if memProcFilter and not UtilMgr.isValidStr( + key, memProcFilter + ): + continue + usage = list(map(long, item["vssUsage"].split()))[ :lent ] @@ -125759,6 +125864,12 @@ def __drawMemPlots(ymax, stacked=False): ), reverse=True, ): + # check process filter # + if memProcFilter and not UtilMgr.isValidStr( + key, memProcFilter + ): + continue + try: rssList = item["rssUsage"].split() usage = list(map(long, rssList))[:lent] @@ -127166,7 +127277,7 @@ def __drawSystemMem(statList, color, ymax): ymax = maxUsage maxIdx = usage.index(maxUsage) - # check max vss conditino # + # check max vss condition # if maxUsage < maxVssCond: continue @@ -127228,7 +127339,7 @@ def __drawSystemMem(statList, color, ymax): ymax = maxUsage maxIdx = usage.index(maxUsage) - # check max rss conditino # + # check max rss condition # if maxUsage < maxRssCond: continue @@ -133263,10 +133374,8 @@ def printCoreInterval(): TA = TaskAnalyzer - # set comm and pid size # - _printer("\n[Top Core Info] (Unit: %%)\n%s\n" % twoLine) - # Print menu # + _printer("\n[Top Core Info] (Unit: %%)\n%s\n" % twoLine) procInfo = "{0:>4} | {1:>4} |".format("Core", "Avg") procInfoLen = len(procInfo) maxLineLen = SysMgr.lineLength @@ -133365,7 +133474,7 @@ def _conv(val): TA = TaskAnalyzer # set comm and pid size # - pd = SysMgr.pidDigit + pd = SysMgr.getMaxPidLen(TA.procTotData) cl = 26 - (pd * 2) _printer( @@ -133708,7 +133817,7 @@ def printRssInterval(): TA = TaskAnalyzer # set comm and pid size # - pd = SysMgr.pidDigit + pd = SysMgr.getMaxPidLen(TA.procTotData) cl = 26 - (pd * 2) # check memory type # @@ -133873,7 +133982,7 @@ def printVssInterval(): TA = TaskAnalyzer # set comm and pid size # - pd = SysMgr.pidDigit + pd = SysMgr.getMaxPidLen(TA.procTotData) cl = 26 - (pd * 2) if SysMgr.jsonEnable: @@ -134024,7 +134133,7 @@ def printGpuMemInterval(): TA = TaskAnalyzer # set comm and pid size # - pd = SysMgr.pidDigit + pd = SysMgr.getMaxPidLen(TA.procTotData) cl = 26 - (pd * 2) if SysMgr.jsonEnable: @@ -134115,7 +134224,7 @@ def printBlkInterval(): TA = TaskAnalyzer # set comm and pid size # - pd = SysMgr.pidDigit + pd = SysMgr.getMaxPidLen(TA.procTotData) cl = 26 - (pd * 2) if SysMgr.jsonEnable: @@ -135932,7 +136041,7 @@ def printMemAnalysis(): convNum = UtilMgr.convNum # set comm and pid size # - pd = SysMgr.pidDigit + pd = SysMgr.getMaxPidLen(SysMgr.procInstance) cl = 26 - (pd * 2) SysMgr.printPipe(