PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /usr/libexec/pcp/bin
Viewing File: /usr/libexec/pcp/bin/pcp-pidstat
#!/usr/bin/pmpython # # Copyright (C) 2020 Red Hat. # Copyright (C) 2017 Alperen Karaoglu. # Copyright (C) 2016 Sitaram Shelke. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # pylint: disable=bad-whitespace,too-many-arguments,too-many-lines # pylint: disable=redefined-outer-name,unnecessary-lambda # import sys import re import time from pcp import pmcc from pcp import pmapi process_state_info = {} # Metric list to be fetched PIDSTAT_METRICS = ['kernel.uname.nodename', 'kernel.uname.release', 'kernel.uname.sysname', 'kernel.uname.machine','hinv.ncpu','proc.psinfo.pid','proc.nprocs','proc.psinfo.utime', 'proc.psinfo.stime','proc.psinfo.guest_time','proc.psinfo.processor', 'proc.id.uid','proc.psinfo.cmd','kernel.all.cpu.user','kernel.all.cpu.vuser', 'kernel.all.cpu.sys','kernel.all.cpu.guest','kernel.all.cpu.nice','kernel.all.cpu.idle', 'proc.id.uid_nm', 'proc.psinfo.rt_priority', 'proc.psinfo.policy', 'proc.psinfo.minflt', 'proc.psinfo.maj_flt', 'proc.psinfo.vsize', 'proc.psinfo.rss', 'mem.physmem', 'proc.memory.vmstack'] PIDSTAT_METRICS_B = ['kernel.uname.nodename', 'kernel.uname.release', 'kernel.uname.sysname', 'kernel.uname.machine','hinv.ncpu','proc.psinfo.pid','proc.nprocs','proc.psinfo.utime', 'proc.psinfo.stime','proc.psinfo.guest_time','proc.psinfo.processor', 'proc.id.uid','proc.psinfo.cmd','kernel.all.cpu.user','kernel.all.cpu.vuser', 'kernel.all.cpu.sys','kernel.all.cpu.guest','kernel.all.cpu.nice','kernel.all.cpu.idle', 'proc.id.uid_nm', 'proc.psinfo.rt_priority', 'proc.psinfo.policy', 'proc.psinfo.minflt', 'proc.psinfo.maj_flt', 'proc.psinfo.vsize', 'proc.psinfo.rss', 'mem.physmem', 'proc.memory.vmstack','proc.psinfo.sname','proc.psinfo.start_time','proc.psinfo.wchan_s'] PIDSTAT_METRICS_L = ['kernel.uname.nodename', 'kernel.uname.release', 'kernel.uname.sysname', 'kernel.uname.machine','hinv.ncpu','proc.psinfo.pid','proc.nprocs','proc.psinfo.utime', 'proc.psinfo.stime','proc.psinfo.guest_time','proc.psinfo.processor', 'proc.id.uid','proc.psinfo.cmd','kernel.all.cpu.user','kernel.all.cpu.vuser', 'kernel.all.cpu.sys','kernel.all.cpu.guest','kernel.all.cpu.nice','kernel.all.cpu.idle', 'proc.id.uid_nm', 'proc.psinfo.rt_priority', 'proc.psinfo.policy', 'proc.psinfo.minflt', 'proc.psinfo.maj_flt', 'proc.psinfo.vsize', 'proc.psinfo.rss', 'mem.physmem', 'proc.memory.vmstack','proc.psinfo.sname','proc.psinfo.start_time','proc.psinfo.wchan_s', 'proc.psinfo.psargs'] #We define a new metric array so that some missing metrics aren't flagged in existing archives using PIDSTAT_METRICS SCHED_POLICY = ['NORMAL','FIFO','RR','BATCH','','IDLE','DEADLINE'] class StdoutPrinter: def Print(self, args): print(args) # After fetching non singular metric values, create a mapping of instance id # to instance value rather than instance name to instance value. # The reason is, in PCP, instance names require a separate pmGetIndom() request # and some of the names may not be available. class ReportingMetricRepository: def __init__(self,group): self.group = group self.current_cached_values = {} self.previous_cached_values = {} def __fetch_current_values(self,metric,instance): if instance: return dict(map(lambda x: (x[0].inst, x[2]), self.group[metric].netValues)) else: return self.group[metric].netValues[0][2] def __fetch_previous_values(self,metric,instance): if instance: return dict(map(lambda x: (x[0].inst, x[2]), self.group[metric].netPrevValues)) else: return self.group[metric].netPrevValues[0][2] def current_value(self, metric, instance): if not metric in self.group: return None if instance: if self.current_cached_values.get(metric, None) is None: lst = self.__fetch_current_values(metric,instance) self.current_cached_values[metric] = lst return self.current_cached_values[metric].get(instance,None) else: if self.current_cached_values.get(metric, None) is None: self.current_cached_values[metric] = self.__fetch_current_values(metric,instance) return self.current_cached_values.get(metric, None) def previous_value(self, metric, instance): if not metric in self.group: return None if instance: if self.previous_cached_values.get(metric, None) is None: lst = self.__fetch_previous_values(metric,instance) self.previous_cached_values[metric] = lst return self.previous_cached_values[metric].get(instance,None) else: if self.previous_cached_values.get(metric, None) is None: self.previous_cached_values[metric] = self.__fetch_previous_values(metric,instance) return self.previous_cached_values.get(metric, None) def current_values(self, metric_name): if self.group.get(metric_name, None) is None: return None if self.current_cached_values.get(metric_name, None) is None: self.current_cached_values[metric_name] = self.__fetch_current_values(metric_name,True) return self.current_cached_values.get(metric_name, None) def previous_values(self, metric_name): if self.group.get(metric_name, None) is None: return None if self.previous_cached_values.get(metric_name, None) is None: self.previous_cached_values[metric_name] = self.__fetch_previous_values(metric_name,True) return self.previous_cached_values.get(metric_name, None) class ProcessCpuUsage: def __init__(self, instance, delta_time, metrics_repository): self.instance = instance self.__delta_time = delta_time self.__metric_repository = metrics_repository def user_percent(self): c_usertime = self.__metric_repository.current_value('proc.psinfo.utime', self.instance) p_usertime = self.__metric_repository.previous_value('proc.psinfo.utime', self.instance) if c_usertime is not None and p_usertime is not None: percent_of_time = 100 * float(c_usertime - p_usertime) / float(1000 * self.__delta_time) return float("%.2f"%percent_of_time) else: return None def guest_percent(self): c_guesttime = self.__metric_repository.current_value('proc.psinfo.guest_time', self.instance) p_guesttime = self.__metric_repository.previous_value('proc.psinfo.guest_time', self.instance) if c_guesttime is not None and p_guesttime is not None: percent_of_time = 100 * float(c_guesttime - p_guesttime) / float(1000 * self.__delta_time) return float("%.2f"%percent_of_time) else: return None def system_percent(self): c_systemtime = self.__metric_repository.current_value('proc.psinfo.stime', self.instance) p_systemtime = self.__metric_repository.previous_value('proc.psinfo.stime', self.instance) if c_systemtime is not None and p_systemtime is not None: percent_of_time = 100 * float(c_systemtime - p_systemtime) / float(1000 * self.__delta_time) return float("%.2f"%percent_of_time) else: return None def total_percent(self): if self.user_percent() is not None and self.guest_percent() is not None and self.system_percent() is not None: return float("%.2f"%(self.user_percent()+self.guest_percent()+self.system_percent())) else: return None def pid(self): return self.__metric_repository.current_value('proc.psinfo.pid', self.instance) def process_name(self): return self.__metric_repository.current_value('proc.psinfo.cmd', self.instance) def process_name_with_args(self): return self.__metric_repository.current_value('proc.psinfo.psargs', self.instance) def cpu_number(self): return self.__metric_repository.current_value('proc.psinfo.processor', self.instance) def user_id(self): return self.__metric_repository.current_value('proc.id.uid', self.instance) def user_name(self): return self.__metric_repository.current_value('proc.id.uid_nm', self.instance) class CpuUsage: def __init__(self, metric_repository): self.__metric_repository = metric_repository def get_processes(self, delta_time): return map(lambda pid: (ProcessCpuUsage(pid,delta_time,self.__metric_repository)), self.__pids()) def __pids(self): pid_dict = self.__metric_repository.current_values('proc.psinfo.pid') return sorted(pid_dict.values()) class ProcessPriority: def __init__(self, instance, metrics_repository): self.instance = instance self.__metric_repository = metrics_repository def pid(self): return self.__metric_repository.current_value('proc.psinfo.pid', self.instance) def user_id(self): return self.__metric_repository.current_value('proc.id.uid', self.instance) def process_name(self): return self.__metric_repository.current_value('proc.psinfo.cmd', self.instance) def process_name_with_args(self): return self.__metric_repository.current_value('proc.psinfo.psargs', self.instance) def priority(self): return self.__metric_repository.current_value('proc.psinfo.rt_priority', self.instance) def policy_int(self): return self.__metric_repository.current_value('proc.psinfo.policy', self.instance) def policy(self): policy_int = self.__metric_repository.current_value('proc.psinfo.policy', self.instance) if policy_int is not None: return SCHED_POLICY[policy_int] return None def user_name(self): return self.__metric_repository.current_value('proc.id.uid_nm', self.instance) class CpuProcessPriorities: def __init__(self, metric_repository): self.__metric_repository = metric_repository def get_processes(self): return map((lambda pid: (ProcessPriority(pid,self.__metric_repository))), self.__pids()) def __pids(self): pid_dict = self.__metric_repository.current_values('proc.psinfo.pid') return sorted(pid_dict.values()) class ProcessMemoryUtil: def __init__(self, instance, delta_time, metric_repository): self.instance = instance self.__metric_repository = metric_repository self.delta_time = delta_time def pid(self): return self.__metric_repository.current_value('proc.psinfo.pid', self.instance) def user_id(self): return self.__metric_repository.current_value('proc.id.uid', self.instance) def process_name(self): return self.__metric_repository.current_value('proc.psinfo.cmd', self.instance) def process_name_with_args(self): return self.__metric_repository.current_value('proc.psinfo.psargs', self.instance) def minflt(self): c_min_flt = self.__metric_repository.current_value('proc.psinfo.minflt', self.instance) p_min_flt = self.__metric_repository.previous_value('proc.psinfo.minflt', self.instance) if c_min_flt is not None and p_min_flt is not None: return float("%.2f" % ((c_min_flt - p_min_flt)/self.delta_time)) else: return None def majflt(self): c_maj_flt = self.__metric_repository.current_value('proc.psinfo.maj_flt', self.instance) p_maj_flt = self.__metric_repository.previous_value('proc.psinfo.maj_flt', self.instance) if c_maj_flt is not None and p_maj_flt is not None: return float("%.2f" % ((c_maj_flt - p_maj_flt)/self.delta_time)) else: return None def vsize(self): return self.__metric_repository.current_value('proc.psinfo.vsize', self.instance) def rss(self): return self.__metric_repository.current_value('proc.psinfo.rss', self.instance) def mem(self): total_mem = self.__metric_repository.current_value('mem.physmem', None) rss = self.__metric_repository.current_value('proc.psinfo.rss', self.instance) if total_mem is not None and rss is not None: return float("%.2f" % (100*float(rss)/total_mem)) else: return None def user_name(self): return self.__metric_repository.current_value('proc.id.uid_nm', self.instance) class CpuProcessMemoryUtil: def __init__(self, metric_repository): self.__metric_repository = metric_repository def get_processes(self, delta_time): return map((lambda pid: (ProcessMemoryUtil(pid, delta_time, self.__metric_repository))), self.__pids()) def __pids(self): pid_dict = self.__metric_repository.current_values('proc.psinfo.pid') return sorted(pid_dict.values()) class ProcessStackUtil: def __init__(self, instance, metric_repository): self.instance = instance self.__metric_repository = metric_repository def pid(self): return self.__metric_repository.current_value('proc.psinfo.pid', self.instance) def user_id(self): return self.__metric_repository.current_value('proc.id.uid', self.instance) def process_name(self): return self.__metric_repository.current_value('proc.psinfo.cmd', self.instance) def process_name_with_args(self): return self.__metric_repository.current_value('proc.psinfo.psargs', self.instance) def stack_size(self): return self.__metric_repository.current_value('proc.memory.vmstack', self.instance) def user_name(self): return self.__metric_repository.current_value('proc.id.uid_nm', self.instance) class CpuProcessStackUtil: def __init__(self, metric_repository): self.__metric_repository = metric_repository def get_processes(self): return map((lambda pid: (ProcessStackUtil(pid, self.__metric_repository))), self.__pids()) def __pids(self): pid_dict = self.__metric_repository.current_values('proc.psinfo.pid') return sorted(pid_dict.values()) # ============================================================================== # process state reporting class ProcessState: # def __init__(self, instance, metric_repository): def __init__(self, instance, delta_time, metric_repository): self.instance = instance self.__metric_repository = metric_repository def pid(self): return self.__metric_repository.current_value('proc.psinfo.pid', self.instance) def user_id(self): return self.__metric_repository.current_value('proc.id.uid', self.instance) def process_name(self): return self.__metric_repository.current_value('proc.psinfo.cmd', self.instance) def process_name_with_args(self): return self.__metric_repository.current_value('proc.psinfo.psargs', self.instance) def s_name(self): return self.__metric_repository.current_value('proc.psinfo.sname', self.instance) def start_time(self): return self.__metric_repository.current_value('proc.psinfo.start_time', self.instance) def wchan_s(self): return self.__metric_repository.current_value('proc.psinfo.wchan_s', self.instance) def user_name(self): return self.__metric_repository.current_value('proc.id.uid_nm', self.instance) #def process_blocked(self): # return self.__metric_repository.current_value('proc.psinfo.blocked', self.instance) def utime(self): #return self.__metric_repository.current_value('proc.psinfo.utime', self.instance) c_usertime = self.__metric_repository.current_value('proc.psinfo.utime', self.instance) p_usertime = self.__metric_repository.previous_value('proc.psinfo.utime', self.instance) # sometimes the previous_value seems to be Nonetype, not sure why if p_usertime is None: # print a '?' here #return c_usertime return '?' else: return c_usertime - p_usertime def stime(self): c_systime = self.__metric_repository.current_value('proc.psinfo.stime', self.instance) p_systime = self.__metric_repository.previous_value('proc.psinfo.stime', self.instance) # sometimes the previous_value seems to be Nonetype, not sure why if p_systime is None: # print a '?' here return '?' else: return c_systime - p_systime class CpuProcessState: def __init__(self, metric_repository): self.__metric_repository = metric_repository # def get_processes(self): # return map((lambda pid: (ProcessState(pid, self.__metric_repository))), self.__pids()) def get_processes(self, delta_time): # return map(lambda pid: (ProcessState(pid,delta_time,self.__metric_repository)), self.__pids()) return map((lambda pid: (ProcessState(pid, delta_time, self.__metric_repository))), self.__pids()) def __pids(self): pid_dict = self.__metric_repository.current_values('proc.psinfo.pid') return sorted(pid_dict.values()) class CpuProcessStateReporter: def __init__(self, process_state, process_filter, delta_time, printer, pidstat_options): self.process_state = process_state self.process_filter = process_filter self.printer = printer self.pidstat_options = pidstat_options self.delta_time = delta_time #TODO: SORTING # for sorting this report, we need to put every process info in a table # without printing individual processes as we run through the for loop below, # then sort as required based on which field we need to sort on, and then # display that entire table for each time print_report is called. def print_report(self, timestamp, header_indentation, value_indentation): #if not "detail" == self.pidstat_options.filterstate: # self.printer ("\nTimestamp" + "\tPID\tState\tUtime\tStime\tTotal Time\tFunction\t\t\tCommand") #else: # self.printer ("\nTimestamp" + "\tPID\t\tR\t\tS\t\tZ\t\tT\t\tD\t\tCommand") # Print out the header only if there are entries for that particular iteration # So this print statement is moved inside the loop protected by a flag print_once print_once = 0 # processes = self.process_filter.filter_processes(self.process_state.get_processes()) processes = self.process_filter.filter_processes(self.process_state.get_processes(self.delta_time)) #print self.pidstat_options.filterstate for process in processes: current_process_sname = process.s_name() if self.pidstat_options.filterstate != "detail": if not "all" in self.pidstat_options.filterstate: if not current_process_sname in self.pidstat_options.filterstate: # if not detailed report (which shows all states), # and we dont find "all" after -B, filter out the processes # in states we dont want continue current_process_pid = process.pid() # tuple key to map to 1-d dictionary of {(pid,state):total_time} key = (current_process_sname,current_process_pid) if key in process_state_info: process_state_info[key]=process_state_info[key] + self.delta_time else: process_state_info[key]=self.delta_time # ------------------------------------------------------------------------------ # TODO : need to add the ability to filter by username #if self.pidstat_options.show_process_user: # self.printer("%s%s%s\t%s\t%s\t%s" % # (timestamp, value_indentation, process.user_name(), # process.pid(), process.process_name(), # process.s_name(), process.start_time(), # process.wchan_s(), process.process_blocked())) #else: # ------------------------------------------------------------------------------ if self.pidstat_options.filterstate != "detail": if print_once == 0: print_once = 1 # dont print ever again for this loop iteration self.printer ("\nTimestamp" + "\tPID\tState\tUtime\tStime\tTotal Time\tFunction\t\t\tCommand") if process.s_name() == 'R': func = "N/A" # if a process is running, there will be no function it's waiting on elif process.s_name is None: func = "?" else: func = process.wchan_s() if process.s_name() is not None and (len(process.wchan_s()) < 8 or func == "N/A"): if self.pidstat_options.process_name_with_args: self.printer("%s\t%s\t%s\t%s\t%s\t%.2f\t\t%s\t\t\t\t%s" % (timestamp, process.pid(), process.s_name(), process.utime(), process.stime(), process_state_info[key], func, process.process_name_with_args())) else: self.printer("%s\t%s\t%s\t%s\t%s\t%.2f\t\t%s\t\t\t\t%s" % (timestamp, process.pid(), process.s_name(), process.utime(), process.stime(), process_state_info[key], func, process.process_name())) elif process.s_name() is not None and (len(process.wchan_s()) < 16 or func == "N/A"): if self.pidstat_options.process_name_with_args: self.printer("%s\t%s\t%s\t%s\t%s\t%.2f\t\t%s\t\t\t%s" % (timestamp, process.pid(), process.s_name(), process.utime(), process.stime(), process_state_info[key], func, process.process_name_with_args())) else: self.printer("%s\t%s\t%s\t%s\t%s\t%.2f\t\t%s\t\t\t%s" % (timestamp, process.pid(), process.s_name(), process.utime(), process.stime(), process_state_info[key], func, process.process_name())) elif process.s_name() is not None and len(process.wchan_s()) < 24: if self.pidstat_options.process_name_with_args: self.printer("%s\t%s\t%s\t%s\t%s\t%.2f\t\t%s\t\t%s" % (timestamp, process.pid(), process.s_name(), process.utime(), process.stime(), process_state_info[key], func, process.process_name_with_args())) else: self.printer("%s\t%s\t%s\t%s\t%s\t%.2f\t\t%s\t\t%s" % (timestamp, process.pid(), process.s_name(), process.utime(), process.stime(), process_state_info[key], func, process.process_name())) else: if process.s_name() is not None: self.printer("%s\t%s\t%s\t%s\t%s\t%.2f\t\t%s\t%s" % (timestamp, process.pid(), process.s_name(), process.utime(), process.stime(), process_state_info[key], func, process.process_name())) #continue else: if print_once == 0: print_once = 1 # dont print again for loop iteration self.printer("\nTimestamp" + "\tPID\t\tR\t\tS\t\tZ\t\tT\t\tD\t\tCommand") # show detailed report of processes with accumulated timings in each state key1 = ("R", current_process_pid) key2 = ("S", current_process_pid) key3 = ("Z", current_process_pid) key4 = ("T", current_process_pid) key5 = ("D", current_process_pid) R = process_state_info.get(key1, 0) S = process_state_info.get(key2, 0) Z = process_state_info.get(key3, 0) T = process_state_info.get(key4, 0) D = process_state_info.get(key5, 0) if self.pidstat_options.process_name_with_args: self.printer("%s\t%s\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f\t\t%s" % (timestamp, process.pid(), R, S, Z, T, D, process.process_name_with_args())) else: self.printer("%s\t%s\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f\t\t%s" % (timestamp, process.pid(), R, S, Z, T, D, process.process_name())) #=============================================================================== class ProcessFilter: def __init__(self,options): self.options = options def filter_processes(self, processes): return filter(lambda p: self.__predicate(p), processes) def __predicate(self, process): return bool(self.__matches_process_username(process) and self.__matches_process_pid(process) and self.__matches_process_name(process) and self.__matches_process_priority(process) and self.__matches_process_memory_util(process) and self.__matches_process_stack_size(process)) def __matches_process_username(self, process): if self.options.filtered_process_user is not None: return self.options.filtered_process_user == process.user_name() return True def __matches_process_pid(self, process): if self.options.pid_filter is not None: pid = process.pid() return bool(pid in self.options.pid_list) return True def __matches_process_name(self, process): name = process.process_name() if name is None: return False # no match if self.options.process_name is not None: return re.search(self.options.process_name, name) return True # all match def __matches_process_priority(self, process): if self.options.show_process_priority and process.priority() is not None: return process.priority() > 0 return True def __matches_process_memory_util(self, process): if self.options.show_process_memory_util and process.vsize() is not None: return process.vsize() > 0 return True def __matches_process_stack_size(self, process): if self.options.show_process_stack_util and process.stack_size() is not None: return process.stack_size() > 0 return True class CpuUsageReporter: def __init__(self, cpu_usage, process_filter, delta_time, printer, pidstat_options): self.cpu_usage = cpu_usage self.process_filter = process_filter self.printer = printer self.delta_time = delta_time self.pidstat_options = pidstat_options def print_report(self, timestamp, ncpu, header_indentation, value_indentation): if self.pidstat_options.show_process_user: self.printer("Timestamp" + header_indentation + "UName\tPID\tusr\tsystem\tguest\t%CPU\tCPU\tCommand") else: self.printer("Timestamp" + header_indentation + "UID\tPID\tusr\tsystem\tguest\t%CPU\tCPU\tCommand") processes = self.process_filter.filter_processes(self.cpu_usage.get_processes(self.delta_time)) for process in processes: user_percent = process.user_percent() guest_percent = process.guest_percent() system_percent = process.system_percent() total_percent = process.total_percent() if self.pidstat_options.per_processor_usage and total_percent is not None: total_percent = float("%.2f"%(total_percent/ncpu)) if self.pidstat_options.show_process_user: if self.pidstat_options.process_name_with_args: self.printer("%s%s%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_name(), process.pid(), user_percent, system_percent, guest_percent, total_percent, process.cpu_number(), process.process_name_with_args())) else: self.printer("%s%s%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_name(), process.pid(), user_percent, system_percent, guest_percent, total_percent, process.cpu_number(), process.process_name())) else: if self.pidstat_options.process_name_with_args: self.printer("%s%s%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_id(), process.pid(), user_percent, system_percent, guest_percent, total_percent, process.cpu_number(), process.process_name_with_args())) else: self.printer("%s%s%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_id(), process.pid(), user_percent, system_percent, guest_percent, total_percent, process.cpu_number(), process.process_name())) class CpuProcessPrioritiesReporter: def __init__(self, process_priority, process_filter, printer, pidstat_options): self.process_priority = process_priority self.process_filter = process_filter self.printer = printer self.pidstat_options = pidstat_options def print_report(self, timestamp, header_indentation, value_indentation): self.printer("Timestamp" + header_indentation + "UID\tPID\tprio\tpolicy\tCommand") processes = self.process_filter.filter_processes(self.process_priority.get_processes()) for process in processes: if self.pidstat_options.show_process_user: if self.pidstat_options.process_name_with_args: self.printer("%s%s%s\t%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_name(), process.pid(), process.priority(), process.policy(), process.process_name_with_args())) else: self.printer("%s%s%s\t%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_name(), process.pid(), process.priority(), process.policy(), process.process_name())) else: if self.pidstat_options.process_name_with_args: self.printer("%s%s%s\t%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_id(), process.pid(), process.priority(), process.policy(), process.process_name_with_args())) else: self.printer("%s%s%s\t%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_id(), process.pid(), process.priority(), process.policy(), process.process_name())) class CpuProcessMemoryUtilReporter: def __init__(self, process_memory_util, process_filter, delta_time, printer, pidstat_options): self.process_memory_util = process_memory_util self.process_filter = process_filter self.printer = printer self.delta_time = delta_time self.pidstat_options = pidstat_options def print_report(self, timestamp, header_indentation, value_indentation): self.printer("Timestamp" + header_indentation + "UID\tPID\tMinFlt/s\tMajFlt/s\tVSize\tRSS\t%Mem\tCommand") processes = self.process_filter.filter_processes(self.process_memory_util.get_processes(self.delta_time)) for process in processes: maj_flt = process.majflt() min_flt = process.minflt() if self.pidstat_options.show_process_user: if self.pidstat_options.process_name_with_args: self.printer("%s%s%s\t%s\t%s\t\t%s\t\t%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_name(), process.pid(), min_flt, maj_flt, process.vsize(), process.rss(), process.mem(), process.process_name_with_args())) else: self.printer("%s%s%s\t%s\t%s\t\t%s\t\t%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_name(), process.pid(), min_flt, maj_flt, process.vsize(), process.rss(), process.mem(), process.process_name())) else: if self.pidstat_options.process_name_with_args: self.printer("%s%s%s\t%s\t%s\t\t%s\t\t%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_id(), process.pid(), min_flt, maj_flt, process.vsize(), process.rss(), process.mem(), process.process_name_with_args())) else: self.printer("%s%s%s\t%s\t%s\t\t%s\t\t%s\t%s\t%s\t%s" % (timestamp, value_indentation,process.user_id(), process.pid(), min_flt, maj_flt, process.vsize(), process.rss(), process.mem(), process.process_name())) class CpuProcessStackUtilReporter: def __init__(self, process_stack_util, process_filter, printer, pidstat_options): self.process_stack_util = process_stack_util self.process_filter = process_filter self.printer = printer self.pidstat_options = pidstat_options def print_report(self, timestamp, header_indentation, value_indentation): self.printer ("Timestamp" + header_indentation + "UID\tPID\tStkSize\tCommand") processes = self.process_filter.filter_processes(self.process_stack_util.get_processes()) for process in processes: if self.pidstat_options.show_process_user: if self.pidstat_options.process_name_with_args: self.printer("%s%s%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_name(), process.pid(), process.stack_size(), process.process_name_with_args())) else : self.printer("%s%s%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_name(), process.pid(), process.stack_size(), process.process_name())) else: if self.pidstat_options.process_name_with_args: self.printer("%s%s%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_id(), process.pid(), process.stack_size(), process.process_name_with_args())) else : self.printer("%s%s%s\t%s\t%s\t%s" % (timestamp, value_indentation, process.user_id(), process.pid(), process.stack_size(), process.process_name())) class NoneHandlingPrinterDecorator: def __init__(self, printer): self.printer = printer def Print(self, args): new_args = args.replace('None','?') self.printer.Print(new_args) class PidstatOptions(pmapi.pmOptions): process_name = None process_name_with_args = False ps_args_flag=False show_process_memory_util = False show_process_priority = False show_process_stack_util = False per_processor_usage = False show_process_user = False show_process_state = False flag_error = False filtered_process_user = None state = "" filterstate = [] pid_filter = None pid_list = [] timefmt = "%H:%M:%S" def checkOptions(self): if self.show_process_priority and self.show_process_memory_util: print("Error: -R is incompatible with -r") return False elif self.show_process_priority and self.show_process_stack_util: print("Error: -R is incompatible with -k") return False elif self.show_process_memory_util and self.show_process_stack_util: print("Error: -r is incompatible with -k") return False elif (self.show_process_memory_util or self.show_process_stack_util or self.show_process_priority) and self.show_process_state: print("Error: Incompatible flags provided") return False elif self.flag_error: print("Error: Incorrect usage of the B flag") return False elif self.ps_args_flag: print("Error: Incorrect usage of the -l flag") return False else: return True def extraOptions(self, opt,optarg, index): if opt == 'k': PidstatOptions.show_process_stack_util = True elif opt == 'r': PidstatOptions.show_process_memory_util = True elif opt == 'R': PidstatOptions.show_process_priority = True #process state elif opt == 'B': if PidstatOptions.show_process_state: #print("Error: Cannot use -B multiple times") PidstatOptions.flag_error = True PidstatOptions.show_process_state = True if optarg in ["All", "all"]: PidstatOptions.filterstate = "all" elif optarg in ["detail", "Detail"]: PidstatOptions.filterstate = "detail" else: # tried to handle the error usage like pcp-pidstat.py -B all R,S # or pcp-pidstat.py -B detail all # or pcp-pidstat.py -B R all, etc but seems like the first optarg is all we have and # we ignore the following ones. So pcp-pidstat.py -B detail all will treat it as # pcp.pidstat.py -B detail #if not PidstatOptions.flag_error: # if (PidstatOptions.filterstate == "all" or PidstatOptions.filterstate == "detail"): # print("Error: Use either all/detail or specific filters for states") # PidstatOptions.flag_error = True # else: # need to put checks for correct states in this string like UN,TT # shouldnt be accepted because TT isnt a valid state # TODO: make sure only R,S,T,D,Z are part of this optarg so if # anything other than these exists in # PidstatOptions.filterstate, we might want to flag error of usage ? PidstatOptions.filterstate += optarg.replace(',', ' ').split(' ') elif opt == 'G': PidstatOptions.process_name = optarg elif opt == 'I': PidstatOptions.per_processor_usage = True elif opt == 'U': PidstatOptions.show_process_user = True PidstatOptions.filtered_process_user = optarg elif opt == 'p': if optarg in ["ALL", "SELF"]: PidstatOptions.pid_filter = optarg else: PidstatOptions.pid_filter = "ALL" try: PidstatOptions.pid_list = list(map(lambda x:int(x),optarg.split(','))) except ValueError: print("Invalid Process Id List: use comma separated pids without whitespaces") sys.exit(1) elif opt == 'f': PidstatOptions.timefmt = optarg elif opt == 'l': if PidstatOptions.process_name_with_args: PidstatOptions.ps_args_flag=True PidstatOptions.process_name_with_args = True def override(self, opt): """ Override standard PCP options to match pidstat(1) """ return bool(opt == 'p') #After reading in the provided command line options #initalize them by passing them in def __init__(self): pmapi.pmOptions.__init__(self,"a:s:t:G:IU::p:RrkVZ:z?:f:B:l") self.pmSetOptionCallback(self.extraOptions) self.pmSetOverrideCallback(self.override) self.pmSetLongOptionHeader("General options") self.pmSetLongOptionArchive() self.pmSetLongOptionSamples() self.pmSetLongOptionInterval() self.pmSetLongOption("process-name", 1, "G", "NAME", "Select process names using regular expression.") self.pmSetLongOption("", 0, "I", "", "Show CPU usage per processor.") self.pmSetLongOption("user-name", 2, "U","[USERNAME]", "Show real user name of the tasks and optionally filter by user name.") self.pmSetLongOption("pid-list", 1, "p", "PID1,PID2.. ", "Show stats for specified pids; " + "use SELF for current process and ALL for all processes.") self.pmSetLongOption("", 0, "R", "", "Report realtime priority and scheduling policy information.") self.pmSetLongOption("", 0,"r","","Report page faults and memory utilization.") self.pmSetLongOption("", 0,"k","","Report stack utilization.") self.pmSetLongOption("", 0,"f","","Format the timestamp output") self.pmSetLongOption("", 0, "B", "state1,state2,..", "Report process state information. " + "Use -B [all] or -B [comma separated states]. " + "Use -B detail for showing time spent in every state per process") self.pmSetLongOptionVersion() self.pmSetLongOptionTimeZone() self.pmSetLongOptionHostZone() self.pmSetLongOption("", 0, "l", "", "Display the process command name and all its arguments.") self.pmSetLongOptionHelp() class PidstatReport(pmcc.MetricGroupPrinter): Machine_info_count = 0 def timeStampDelta(self, group): s = group.timestamp.tv_sec - group.prevTimestamp.tv_sec u = group.timestamp.tv_usec - group.prevTimestamp.tv_usec return s + u / 1000000.0 def print_machine_info(self,group, context): timestamp = context.pmLocaltime(group.timestamp.tv_sec) # Please check strftime(3) for different formatting options. # Also check TZ and LC_TIME environment variables for more # information on how to override the default formatting of # the date display in the header time_string = time.strftime("%x", timestamp.struct_time()) header_string = '' header_string += group['kernel.uname.sysname'].netValues[0][2] + ' ' header_string += group['kernel.uname.release'].netValues[0][2] + ' ' header_string += '(' + group['kernel.uname.nodename'].netValues[0][2] + ') ' header_string += time_string + ' ' header_string += group['kernel.uname.machine'].netValues[0][2] + ' ' print("%s (%s CPU)" % (header_string, self.get_ncpu(group))) def get_ncpu(self,group): return group['hinv.ncpu'].netValues[0][2] def report(self,manager): group = manager['pidstat'] if group['proc.psinfo.utime'].netPrevValues is None: # need two fetches to report rate converted counter metrics return if not group['hinv.ncpu'].netValues or not group['kernel.uname.sysname'].netValues: return try: ncpu = self.get_ncpu(group) if not self.Machine_info_count: self.print_machine_info(group, manager) self.Machine_info_count = 1 except IndexError: # missing some metrics return ts = group.contextCache.pmLocaltime(int(group.timestamp)) timestamp = time.strftime(PidstatOptions.timefmt, ts.struct_time()) interval_in_seconds = self.timeStampDelta(group) header_indentation = " " if len(timestamp)<9 else (len(timestamp)-7)*" " value_indentation = ((len(header_indentation)+9)-len(timestamp))*" " metric_repository = ReportingMetricRepository(group) if PidstatOptions.show_process_stack_util: process_stack_util = CpuProcessStackUtil(metric_repository) process_filter = ProcessFilter(PidstatOptions) stdout = StdoutPrinter() printdecorator = NoneHandlingPrinterDecorator(stdout) report = CpuProcessStackUtilReporter(process_stack_util, process_filter, printdecorator.Print, PidstatOptions) report.print_report(timestamp, header_indentation, value_indentation) elif PidstatOptions.show_process_memory_util: process_memory_util = CpuProcessMemoryUtil(metric_repository) process_filter = ProcessFilter(PidstatOptions) stdout = StdoutPrinter() printdecorator = NoneHandlingPrinterDecorator(stdout) report = CpuProcessMemoryUtilReporter(process_memory_util, process_filter, interval_in_seconds, printdecorator.Print, PidstatOptions) report.print_report(timestamp, header_indentation, value_indentation) elif PidstatOptions.show_process_priority: process_priority = CpuProcessPriorities(metric_repository) process_filter = ProcessFilter(PidstatOptions) stdout = StdoutPrinter() printdecorator = NoneHandlingPrinterDecorator(stdout) report = CpuProcessPrioritiesReporter(process_priority, process_filter, printdecorator.Print, PidstatOptions) report.print_report(timestamp, header_indentation, value_indentation) #=========================================================================================================== elif PidstatOptions.show_process_state: process_state = CpuProcessState(metric_repository) process_filter = ProcessFilter(PidstatOptions) stdout = StdoutPrinter() printdecorator = NoneHandlingPrinterDecorator(stdout) report = CpuProcessStateReporter(process_state, process_filter, interval_in_seconds, printdecorator.Print, PidstatOptions) report.print_report(timestamp, header_indentation, value_indentation) #=========================================================================================================== else: cpu_usage = CpuUsage(metric_repository) process_filter = ProcessFilter(PidstatOptions) stdout = StdoutPrinter() printdecorator = NoneHandlingPrinterDecorator(stdout) report = CpuUsageReporter(cpu_usage, process_filter, interval_in_seconds, printdecorator.Print, PidstatOptions) report.print_report(timestamp, ncpu, header_indentation, value_indentation) if __name__ == "__main__": try: opts = PidstatOptions() manager = pmcc.MetricGroupManager.builder(opts,sys.argv) if not opts.checkOptions(): raise pmapi.pmUsageErr if opts.show_process_state: missing = manager.checkMissingMetrics(PIDSTAT_METRICS_B) elif opts.process_name_with_args: missing = manager.checkMissingMetrics(PIDSTAT_METRICS_L) else: missing = manager.checkMissingMetrics(PIDSTAT_METRICS) if missing is not None: sys.stderr.write('Error: not all required metrics are available\nMissing %s\n' % (missing)) sys.exit(1) if opts.process_name_with_args: manager['pidstat'] = PIDSTAT_METRICS_L elif opts.show_process_state: manager['pidstat'] = PIDSTAT_METRICS_B else: manager['pidstat'] = PIDSTAT_METRICS manager.printer = PidstatReport() sts = manager.run() sys.exit(sts) except pmapi.pmErr as pmerror: sys.stderr.write('%s: %s\n' % (pmerror.progname,pmerror.message())) except pmapi.pmUsageErr as usage: usage.message() sys.exit(1) except KeyboardInterrupt: pass