
    W&Jj                    T   % S SK Jr  S SKrS SKrS SKrS SKrS SKrS SKrS SKrS SK	J
r
  S SKJr  S SKJrJr  S SKJr  \" S5      r0 qS\S	'   \R*                  " 5       rSqS
\S'   \R0                  " 5       qSqS\S'   SqS\S'   \R*                  " 5       rSqS\S'   SqS\S'   \R*                  " 5       rSq S\S'   Sq!S\S'   0 q"S\S'   Sq#S\S'   S,S jr$S-S jr%S.S jr&S/S jr'S/S jr(S0S  jr)S0S! jr*S/S" jr+S1S# jr,S0S$ jr-S0S% jr.S2S& jr/S3S4S' jjr0S5S( jr1S6S5S) jjr2S7S* jr3S/S+ jr4g)8    )annotationsN)Path)Any)ThreadPoolExecutoras_completed)
get_loggermetricsdict[str, Any]_metrics_cachezthreading.Thread | None_updater_threadzlist[dict[str, Any]] | None_docker_cache_data        float_docker_cache_time_ssl_cache_data_ssl_cache_timez(tuple[float, float, float, float] | None_last_cpu_timesz dict[str, dict[str, Any]] | None_last_net_statszdict[int, dict[str, Any]]_last_proc_statsztuple[float, float] | None_last_disk_statsc                 8   0 n  [        SSSS9 nU HH  nUR                  5       R                  S5      n[        U5      S:  d  M3   US   U [	        US   5      '   MJ     S	S	S	5        U $ ! [
         a     Mc  f = f! , (       d  f       U $ = f! [         a     U $ f = f)
z1Parse /etc/passwd into a uid -> username mapping.z/etc/passwdrutf-8encoding:   r      N)openstripsplitlenint
ValueError	Exception)uid_mapflinepartss       1D:\Programs\laragon\www\wolf\agent\src\metrics.pyget_uid_mapr+   (   s    G
-w71

**3/u:?16qE!H.	  8 N	 &  87 N  NsR   B 2A9A(A9B (
A62A95A66A99
BB B 
BBc                    SSK n[        R                  " U S   5      (       d  g UR                  U SSSSS9nUR                  S:w  a  gUR
                  $ ! [         a     gf = f)zGHelper to run command and capture output (similar to discovery.system).r   NT   F)capture_outputtexttimeoutcheck)
subprocessshutilwhichrun
returncodestdoutr%   )cmdr2   results      r*   run_readonlyr:   9   sq    <<A   
 !}} s   #A 	A 
A"!A"c                   U (       d  g[         R                  " S5      nUR                  SU 5      n U R                  5       n/ nSn1 Skn[	        U5       GH]  u  pgU(       ad  SnUR                  S5      (       a  SnO1UR                  S5      (       a  SnOUR                  S5      (       a  SnUR                  S	U-   5        SnMq  UR                  5       n	X;   a'  UR                  U5        US
-   [        U5      :  a  SnM  UR                  S5      (       a"  [        U5      S:  a  UR                  S5        M  Sn
U HU  nU	R                  UR                  5       S-   5      (       d  M,  UR                  UR                  SS
5      S   S-   5        Sn
  O   U
(       a  GML  UR                  U5        GM`     SR                  U5      $ )z3Mask sensitive parameters in process command lines. z(?i)(password|passwd|pwd|token|secret|api_key|apikey|access_token|refresh_token|authorization|bearer|--password|--token)\s*=\s*(\S+)z\1=***F>   pwdtokenapikeybearerpasswdsecretapi_keypasswordaccess_tokenauthorizationrefresh_token-p--pwd--token--apikey--passwd--secret	--api-key	--api_key
--password'")z***   TrH   r   z-p***r   r   z:*** )recompilesubr!   	enumerateendswithappendlowerr"   
startswithjoin)cmdline
pattern_eqr)   	sanitized	skip_nextsensitive_keysipartsuffix
part_lower
matched_eqks               r*   sanitize_cmdlinerj   M   s     	PJ nnY0G MMOEIIN U#F}}S!!s##s##UV^,IZZ\
'T"1us5z! 	??4  SY]W%
A$$QWWY_55  C!3A!6!?@!
	  
 C $F 88I    c                    [         R                  " 5       =(       d    Sn / n [        [         R                  " 5       5      nSnSnSn [         R                  R                  S5      (       Ga  [        SSSS9 nUR                  5       nSSS5        WR                  S5      (       Gat  UR                  5       R                  5       nUS	S  Vs/ sH  n[        U5      PM     n	nU	SS
 u  pppnnX-   n[        U	SS
 5      n[        c  UUUU4q[         R"                  " S5        [        SSSS9 nUR                  5       nSSS5        WR                  S5      (       aX  UR                  5       R                  5       nUS	S  Vs/ sH  n[        U5      PM     n	nU	SS
 u  pppnnX-   n[        U	SS
 5      n[        bZ  [        u  nnnnUU-
  nUS:  aD  UU-
  n[%        SUU-  -
  S-  S	5      n[%        UU-
  U-  S-  S	5      n[%        UU-
  U-  S-  S	5      nUUUU4q[-        S[/        SU5      5      U U[-        S[/        SU5      5      [-        S[/        SU5      5      S.$ ! [        [
        4 a     GN2f = f! , (       d  f       GN= fs  snf ! , (       d  f       GNV= fs  snf ! [&         a   n[(        R+                  SU5         SnANSnAff = f)zFCollect CPU usage percent, core count, load average, steal and iowait.r   r   
/proc/statr   r   r   Nzcpu rT      皙?g      ?      Y@zCPU collector error: %s)usage_percentcoresload_averagesteal_percentiowait_percent)os	cpu_countlist
getloadavgOSErrorAttributeErrorpathexistsr   readliner]   r    r!   r   sumr   timesleeproundr%   logdebugmaxmin)rr   load_avgrq   rt   ru   r'   r(   r)   xvalsusernicesystemidleiowaitirqsoftirqstealidle_alltotalf2line2
last_totallast_idle_all
last_steallast_iowait
total_diff	idle_diffexcs                                r*   collect_cpur      s    LLNaEH( MMN%277>>,''lC':azz| ;v&&

**,*/)4)Qa)4HLRaEF&w=D!H #*',hv&FOJJt$lC'Bb " C''// % 3 3 527)<)Qa)<PTUWVWPXMF&w#'= #D!H".IXFJz;!&!3J!A~$,}$<	(-si*6L/MQV.VXY(Z(-
0Bj/PTY.Y[\(]).+1E0SW\/\^_)`#((E6"B
 S#e]";< S#e]";<c3un#=> ] ^$  ;:
 5 CB  =  2		+S112su   I 0J$ 7I6AJ$ J AJ$ -J>AJ$ JBJ$ I32I36
J J$ 
JJ$ $
K.K		Kc            	        SSSSSSSSS.S.n  0 n[         R                  R                  S5      (       Ga;  [        SSSS9 nU Hv  nUR	                  S5      n[        U5      S	:X  d  M%  US   R                  5       nUS
   R                  5       R	                  5       nU(       d  Mb   [        US   5      S-  X'   Mx     SSS5        UR                  SS5      nUR                  SS5      nUR                  SS5      n	UR                  SS5      n
[        SXx-
  U
-
  U	-
  5      nUR                  SS5      nUR                  SS5      n[        SX-
  5      nXpS'   XS'   XS'   XS'   XS'   UUUS.U S'   U $ ! [         a     GM=  f = f! , (       d  f       N= f! [         a!  n[        R                  SU5         SnAU $ SnAff = f)z0Collect RAM and Swap metrics from /proc/meminfo.r   )r   usedfree)r   r   r   cachedbuffersswapz/proc/meminfor   r   r   r   r   rT   i   NMemTotalMemFreeCachedBuffers	SwapTotalSwapFreer   r   r   r   r   r   zRAM collector error: %s)rv   r|   r}   r   r!   r"   r    r#   r$   getr   r%   r   r   )ram_infovaluesr'   r(   r)   key	val_partsr   r   r   r   r   
swap_total	swap_free	swap_usedr   s                   r*   collect_ramr      s    Q2H$277>>/**osW=D JJsOE5zQ#Ahnn.$)!HNN$4$:$:$<	$9%.1)A,.?$.F  > JJz1-E::i+DZZ!,FjjA.Gq%,069:DK3J

:q1IAz56I %W#V#V!'X")Y#!! HV O3 $. % $% >=@  2		+S11O2sZ   2F $F)9F'E3:F>B3F 3
F=FFF
FF 
G F<<Gc                    / n  [         R                  R                  S5      (       Ga  [        SSSS9 nU GH  nUR	                  5       R                  5       n[        U5      S:  d  M3  US   US   US   penUR                  S	5      =(       d    US
;   nU(       d  Mg  UR                  S5      (       a  M   [        R                  " U5      n[         R                  " U5      n	U	R                  n
U	R                  nX-
  nU R                  UUUUR                  UR                  UR                   U
UUS.	5        GM     SSS5        U $  [        R                  " S5      nU R                  SSSUR                  UR                  UR                   SSSS.	5        U $ ! ["         a     GMp  f = f! , (       d  f       U $ = f! ["         a     U $ f = f! ["         a!  n[$        R'                  SU5         SnAU $ SnAff = f)z8Collect disk usage and inode count for each mount point.z/proc/mountsr   r   r   r   r   rT   r   z/dev/)zfsbtrfsxfsext4ext3ext2f2fs)z	/boot/efiz/var/lib/docker)	mount_pointdevice
filesystemr   r   r   inodes_totalinodes_usedinodes_freeN/rootunknownzDisk collector error: %s)rv   r|   r}   r   r    r!   r"   r]   r3   
disk_usagestatvfsf_filesf_ffreer[   r   r   r   r%   r   r   )mountsr'   r(   r)   devr   fs_typeis_physicalusagestatvr   r   r   r   s                 r*   collect_diskr      s   F3377>>.))ncG<D JJL..0E5zQ49!HeAha'NN73 _#'^^ $ ';{/E/EFf/g/g%(.(9(9+(F(*

;(?/4}}.3mm.:.H &3>.129-2[[,1JJ,1JJ4@3>3>
/" 
!##  =d M#))#.#&$"+"[[!JJ!JJ$%#$#$
 
 M+ $- % $%; =<d M	   M	 3		,c22M3s   0G 2F+*0F+F+7BF8F+=G AF= 
F(#F+'F((F++
F:5G :G =
GG 
GG 
G9G44G9c                    / n [         R                   " 5       n 0 n[        R                  R                  S5      (       GaR  [	        SSSS9 nUR                  5       nSSS5        WSS  H  nUR                  S5      n[        U5      S:X  d  M%  US   R                  5       nUS	:X  a  M@  US
   R                  5       R                  5       n[        U5      S:  d  Mr   [        US   5      n	[        US
   5      n
[        US   5      n[        US   5      n[        US   5      n[        US   5      n[        US   5      n[        US   5      nU	U
UUUUUUUS.	X''   M     UR                  5        GH  u  nnSnSn[        (       aQ  U[        ;   aG  [        U   nUUS   -
  nUS:  a0  [        SUS   US   -
  U-  5      n[        SUS   US   -
  U-  5      nSnSU S3n[        R                  R                  U5      (       a<   [	        USSS9 n[        UR                  5       R                  5       5      nSSS5        U R!                  UUS   US   US   US   US   US   US   US   [        US-  5      [        US-  5      US.5        GM      UqU $ ! , (       d  f       GN?= f! [         a     GMK  f = f! , (       d  f       N= f! [         a     Nf = f! [         a!  n["        R%                  S U5         SnAU $ SnAff = f)!zDCollect network traffic details and rate metrics for each interface.z/proc/net/devr   r   r   Nr   r   r   lorT      r   rn   	   
      )	rx_bytes
rx_packets	rx_errorsrx_dropstx_bytes
tx_packets	tx_errorstx_drops	timestampr   r   r   r   z/sys/class/net/z/speedr   r   r   r   r   r   )	interfacer   r   r   r   r   r   r   r   rx_rate_bpstx_rate_bps
speed_mbpszNetwork collector error: %s)r   rv   r|   r}   r   	readlinesr!   r"   r    r#   r$   itemsr   r   readr%   r[   r   r   )
interfacesnowcurrent_statsr'   linesr(   r)   ifacecolsr   r   r   r   r   r   r   r   statsrx_ratetx_ratelast	time_diffr   
speed_pathsfr   s                             r*   collect_networkr   5  s    J
))+CI677>>/**osW= >ab	

3u:?!!HNN,E}  8>>+113D4yB!'*47|H),T!WJ(+DGI'*47|H'*47|H),T!WJ(+DHI'*48}H -5.8-6,4,4.8-6,4-0
4M0% "@ !. 3 3 5u"?u'?*51D #d;&7 7I 1}"%cE*,=Z@P,PT]+]"^"%cE*,=Z@P,PT]+]"^
.ugV<
77>>*--!*cGD),RWWY__->)?J E
 !!!& %j 1 %j 1"'"5"'"5!&{!3!&{!3 %j 1 %j 1#&w{#3#&w{#3",# ' !6D ,O O >=>  * ! !" ED$ &  6		/556s   2K J.K A	K A>J&B'K K	(J85K	=AK 
J#K &
J50K 4J55K 8
K	K	K K		
KK KK 
L#K??Lc                 |   / n / n[         R                   " 5       n  [        R                  " S5      n [        R                  " S5      nSn[        R
                  R                  S5      (       a`  [        SSSS	9 nU HF  nUR                  S
5      (       d  M   [        UR                  5       R                  5       S   5      n  O   SSS5        [        5       n/ n	[        R
                  R                  S5      (       Ga  [        R                  " S5       GH  n
U
R                  5       (       d  M  [!        U
5      nSU
 3n [        U S3SSS9 nUR#                  5       R                  5       nSSS5        WR%                  S5      nUS:w  a1  USU nXR'                  S5      S-   S nXS-   S R                  5       nO+UR                  5       n[)        U5      S:  a  US   OSnUSS n[)        U5      S:  a  [!        US   5      n[!        US   5      n[!        US   5      n[!        US   5      nUU-   nUU-  nUUU-  -   nSn[*        (       a>  U[*        ;   a4  [*        U   nUUS   -
  nUUS   -
  nUS:  a  [-        UU-  U-  S-  S5      nU	R/                  UU
UUUUUUS .5        GM  GM     U	(       d  / / S!.$ [5        U	S" S#S$9SS% n[5        U	S& S#S$9SS% n[7        5       n/ n UU-    H3  n!U!S'   U;  d  M  UR9                  U!S'   5        U R/                  U!5        M5     0 n"U  GH  n!U!S'   nU!S(   nSn# [        U S)3SSS9 n$U$ HF  nUR                  S*5      (       d  M   [!        UR                  5       R                  5       S   5      n#  O   SSS5        Sn%Sn& [        U S+3SSS9 n'U' H  nUR                  S,5      (       a,  [!        UR                  5       R                  5       S   5      n%ME  UR                  S-5      (       d  M]  [!        UR                  5       R                  5       S   5      n&M     SSS5        S.n( [        U S/3SSS9 n)U)R#                  5       R=                  S0S15      R                  5       n(SSS5        U((       a  [?        U(5      n(U((       a  U(OU!S2   n*U!S2   RA                  5       n+S3U+;   a  S4n,S5/n-OS6U+;   d  S7U+;   a  S4n,S8/n-OvS9U+;   a  S:n,S;/n-OjS<U+;   d  S=U+;   a  S>n,S?/n-OXS@U+;   a  S>n,SA/n-OLSBU+;   a  S>n,SC/n-O@SDU+;   a  S4n,SE/n-O4SFU+;   a  S4n,SG/n-O(SHU+;   a  S4n,SI/n-OSJU+;   a  S:n,SK/n-OSLU+;   a  S:n,SM/n-OSNn,/ n-Sn.[*        (       aG  U[*        ;   a=  [*        U   nUUS   -
  nUS:  a&  SOU;   a   U%USO   -
  U&USP   -
  -   n/[C        SU/U-  5      n.U*U,U-URE                  U#[G        U#5      5      U!S   U!SQ   U!SR   U%U&UU!SS   U.ST.U"U'   GM     0 n0U	 H4  n!U!S'   nUU";   a  U!S   UU"U   SO   U"U   SP   SU.U0U'   M)  U!S   USV.U0U'   M6     [*        (       d)  U	(       a"  U0q[         RH                  " SW5        [K        5       $ U0q/ n1U"RM                  5        H  u  nn2UU2SR   -
  n3U3SX:  a  SYn4OAU3SZ:  a  [!        U3SX-  5       S[3n4O)U3S\:  a  [!        U3SZ-  5       S]3n4O[!        U3S\-  5       S^3n4U1R/                  0 S_[G        U5      _S'[G        U5      _S2U2S2   _S`U2S`   _SaU2Sa   _SbU2SS    Sc3_SSU2SS   _Sd[-        U2SQ   Se-  S5       Sf3_SQU2SQ   _SgS#_ShSY_SiU4_Sj[-        U2Sk   Se-  S5       Sl3_SmU2S`    SnU2Sa    3_SoU2So   _Sp/ _5        M     [5        U1Sq S#S$9SSr n [5        U1Ss S#S$9SSr nU US!.$ ! [        [        4 a    Sn GNdf = f! [        [        4 a    Sn GNff = f! [        [        4 a     GNf = f! , (       d  f       GN
= f! , (       d  f       GNt= f! [0        [2        [        [        4 a     GM  f = f! [        [        4 a     GNf = f! , (       d  f       GN= f! [:         a     GNf = f! , (       d  f       GN= f! [:         a     GN&f = f! , (       d  f       GN= f! [:         a     GNf = f! [:         a!  n5[N        RQ                  StU55         Sn5A5GN:Sn5A5ff = f)uz/Collect Top 10 CPU and RAM consuming processes.SC_PAGE_SIZEi   
SC_CLK_TCKd   r   rm   r   r   r   zbtime rT   Nz/procz/proc/z/statignore)errorsrS   r   (r   r      r   r         r   cpu_timer   rp   )pidpid_dirproc_dirnamer   	ram_bytes
start_timecpu_percent)top_cputop_ramc                    U S   $ Nr   r   s    r*   <lambda>!collect_process.<locals>.<lambda>  s	    a>Nrk   T)r   reverse   c                    U S   $ Nr  r
  r  s    r*   r  r    s    anrk   r   r  z/statuszUid:z/iozread_bytes:zwrite_bytes:r<   z/cmdline rU   r  nginxServiceNginxapachehttpdApachephpRuntimePHPmysqlmariadbDatabaseMySQLpostgres
PostgreSQLredisRedisdockerDockerfail2banFail2BancronCronnodezNode.jspythonPythonSystemread_io_byteswrite_io_bytesr  r  r  )r  typeruntimesr   r   r  r  r.  r/  r   r  disk_io_rate)r   r   r.  r/  )r   r   ro   <   zjust nowi  zm agoiQ zh agozd agoidr0  r   cpu%ram   z MBrunningupdatedstarteddiskIor2  z MB/sdescriptionz process running under r1  domainsc                    U S   $ r	  r
  r  s    r*   r  r    s	    !M2Brk   r   c                    U S   $ r  r
  r  s    r*   r  r    s    !K.rk   zProcess collector error: %s))r   rv   sysconfr{   r$   r|   r}   r   r]   r   r    r!   
IndexErrorr+   listdirisdigitr#   r   rfindfindr"   r   r   r[   FileNotFoundErrorPermissionErrorsortedsetaddr%   replacerj   r\   r   r   strr   collect_processr   r   r   )6r  r  r   	page_sizeclk_tckbtimer'   r(   r&   
candidatesr   r   r  stat_contentrpar_idx	name_partr  r   utimestimerss	starttimer   r  start_timestampr  r   r   cpu_difftop_cpu_candidatestop_ram_candidatesselected_pidsselected_candidatesccurrent_proc_statsuidr   r.  r/  iofr_   cfp_name
short_namep_typer1  r2  io_diffnext_proc_stats	proc_listselapsedr;  r   s6                                                         r*   rN  rN    s<
    GG
))+CC6	

>2I	jj.G
 77>>,''lC':aDx00!$)$**,*<*<*>q*A$BE   ; - 
77>>'""::g.??$$g,C!'y1H+!!XJe"4c(Kq+,668>>+;L L#/#5#5c#:#r>(4Yh(?I#,^^C-@1-D-E#FD#/1#>#D#D#FD#/#5#5#7D.1$i!m47D#'8Dt9?$'RME$'RME"%d2h-C(+DHI',u}H(+iI.3y77J.KO +.K//C;K4K'7'<,/${2C,C	+3d:6F+F#,q=27G9Ky8X[`8`bc2dK&--'*+2,4(,,4-6.=/:	/ 	' +# /b !b11 $J4NX\]^a_ab#J4LVZ[\_]_` #&88Ax},!!!E(+#**1- 9  $AE(C}H C
XJg.HE "??622%&)$**,*<*<*>q*A&B " !# F MNXJc*CAS #??=99,/

0B0B0DQ0G,HM!__^<<-01C1C1Ea1H-IN	 !$ B GXJh/XF" ggi//<BBDG G
 *73 'WQvYF 6*J*$"#9Z'7j+@"$:*$"!7J&)z*A##9z)#(>J&##9Z'"$:z)"&<:%""8:%"%;Z'"$:! LC+;$;',${"33	q=_%<,tO/DDZ^_oZpIpqG#&sGi,?#@L $CS2jM{^o!."0  / ,'s#w %V AE(C(( !*!$%7%<_%M&8&=>N&O	($ !"*!$($    J.JJt"$$* 	(..0FCAlO+G|$4 B/065 D12%8 E!12359 c#hs3x &	 &		
 &	 !M*+1- q/ %++ >BC3G Q{^ 4 : 7 U1^#4#DaHIO !F),CAfI;O AjM  2!  1< (BDQRUSUV(@$OPSQST  E 
+ 	I	 
+ 	G	 !+J7 ! ! ;:& LKR .
JW ! !> %/
#; % $% FE   BA  
 GF F  6		/556s  ^ ^ 	1b :_
*^3_
A&b 1b _._/D9_.(b <9b 9=b 7`9`'$*``'`9b a-Aa
.a
;ab a?/a-a?Gb D*b ^b ^b ^0,b /^00b 3__
__


_b 
_+	&_..`b `b `$	 `'#`$	$`''
`6	1`94b 6`99
ab ab 

a	ab a
a*&b )a**b -
a<	7a?:b <a??
b	b bb 
b;b66b;c            	        SSSSSSSSS	.n S
/SS/S/S/S.nU  Vs0 sH  o"S_M     nn[        / SQ5      nU(       Ga
  0 nUR                  5        HL  nUR                  SS9n[        U5      S:  d  M#  US   R	                  S5      (       d  M>  US   nUS   n	XU'   MN     U R                  5        H  u  pX;   a  X[   X:'   M  SnX;   a  X    H  nX;   d  M
  X]   X:'   Sn  O   U(       a  M<  U
S:X  d  MD  UR                  5        H<  u  pUR                  S5      (       d  M  UR	                  S5      (       d  M5  XU
'   Sn  M     M     U$ s  snf )z1Collect health status of common systemd services.znginx.servicezapache2.servicezphp-fpm.servicezmysql.servicezredis-server.servicezdocker.servicezfail2ban.servicezcron.service)r  r  r  r  r"  r$  r&  r(  zhttpd.servicezmariadb.servicezmysqld.servicezredis.servicezcrond.service)r  r  r"  r(  inactive)	systemctlz
list-unitsz--type=servicez--allz--no-legendz
--no-pager   )maxsplitr   z.servicer   FTr  z-fpm.service)r:   
splitlinesr!   r"   rZ   r   r]   )servicesalt_servicesr  
status_mapoutputactive_unitsr(   fields	unit_nameactive_stater   unitfoundalt_unitactive_unitstates                   r*   collect_servicesr    s    !#  '"&	H ###%56!" !	L 088xt
"xJ8mnF%%'DZZZ+F6{aF1I$6$6z$B$B"1I	%ay*6Y' ( ")IC#"."4
&$0$5#3.:.DJO$(E!	 %6
 u.:.@.@.B*&11%88[=Q=QR`=a=a.3sO$(E!	 /C *" ; 9s   E
c            
        Sn [         R                   " 5       n[           [        b  U[        -
  U :  a  [        sSSS5        $ SSS5        [        R
                  " S5      (       d  / $  [        / SQ5      nU(       d  / $ / n/ nUR                  5        Hj  nUR                  5       R                  S5      n[        U5      S:  d  M3  US   US   US	   pnUR                  UUU	SS
SS.5        UR                  U5        Ml     U(       Ga  / SQU-   n
[        U
5      n0 nU(       a`  UR                  5        HL  nUR                  5       R                  S5      n[        U5      S	:X  d  M3  US   US   p[        U5      XSS '   MN     / SQn[        U5      n0 nU(       a  UR                  5        Ht  nUR                  5       R                  S5      n[        U5      S:X  d  M3  US   US   US	   nnnSU;   a"  UR                  S5      S   R                  5       OUnUUS.UU'   Mv     U Hz  nUS   SS nSnUR                  5        H6  u  nnUR                  U5      (       d  UR                  U5      (       d  M4  Un  O   UUS'   UU;   d  Md  UU   S   US'   UU   S   US'   M|     [           UqUqSSS5        U$ ! , (       d  f       GN}= f! , (       d  f       U$ = f! [         a_  n[         R#                  SU5        [           [        b  [        sSSS5        s SnA$  SSS5        O! , (       d  f       O= f/ s SnA$ SnAff = f)z,Collect details of active Docker containers.g     r@Nr$  )r$  psz-a--formatz{{.ID}}	{{.Names}}	{{.State}}	r   r   rT   r   z0.0%0B)r4  r  statusrestart_countr  	ram_usage)r$  inspectr  z{{.Id}}	{{.RestartCount}}r   )r$  r   z--no-streamr  z"{{.ID}}	{{.CPUPerc}}	{{.MemUsage}}r   )r5  r7  r4  r  r5  r  r7  r  z2Docker collector failed, falling back to cache: %s)r   _docker_cache_lockr   r   r3   r4   r:   rr  r    r!   r"   r[   r#   r   r]   r%   r   r   )ttlr   containers_jsoncontainers_listidsr(   r)   cidr  r  inspect_cmdinspect_outputrestart_countsfull_idrcount	stats_cmdstats_outputdocker_statsr5  memmem_usedr`  short_idkidvalr   s                             r*   collect_dockerr    s   
 C
))+C	)s5G/G3.N% 
		 <<!!	G&'lmI#..0DJJL&&t,E5zQ#(8U1XuQx5&& #%&#)!%(  

3 1 Y\__K)+6NN*557D JJL..t4E5zQ*/(E!H7:6{s|4	 8 oI'	2LL(335D JJL..t4E5zQ(-a%(E!H#S@Cs
399S>!#4#:#:#<PS#&#+-S) 6 %T73B< . 4 4 6HC~~h//83F3Fs3K3K!$ !7 &,/"|+'3H'=e'DAm$%1(%;E%BAkN %  !0!$   O 
	H    		FL!-)  -   	s   J8(K >AK BK &A4K BK 6K 	 K )K
.	K 8
K

KK K 
M&M L(	M M	M (
L6	2M :M Mc                 	   Sn [         R                   " 5       n[           [        b  U[        -
  U :  a  [        sSSS5        $ SSS5        SSKJn  Sn/ n / nU H  n [        U5      nUR                  5       (       d  M&  SU;   aB  UR                  S5       H+  nUR                  5       (       d  M  UR                  U5        M-     Mn  [        UR                  S5      5      SS	  H]  nUR                  5       (       d  M  S
UR                  ;  d  M,  SUR                  R                  5       ;  d  ML  UR                  U5        M_     M     USS  GH  n
 [#        SSSSSS[%        U
5      /5      nU(       Ga  SnSnUR'                  5        GH   nUR)                  S5      (       a  UR+                  SS5      S   R-                  5       n[.        R0                  " SU5      nU(       a!  UR3                  S5      R-                  5       nM|  [.        R0                  " SU5      nU(       a!  UR3                  S5      R-                  5       nM  UnM  UR)                  S5      (       d  M  UR+                  SS5      S   R-                  5       n UR5                  US5      nUR7                  5       S-   nGM#     SnS[%        U
5      ;   a  SOSnSnUS:X  an  [.        R0                  " S [%        U
5      R;                  S!S"5      5      nU(       a7  UR3                  S5      n[        S#U S$35      nUR                  5       (       a  S%nUR                  [%        U
5      UUUS&.5        GM  GM     [           UqUqSSS5        U$ ! , (       d  f       GN;= f! [        [        4 a"  n	[        R!                  SXi5         Sn	A	GM\  Sn	A	ff = f! [8         a    Un GMC  f = f! [        [        4 a"  n	[        R!                  S'X5         Sn	A	GM  Sn	A	ff = f! , (       d  f       U$ = f! [8         a_  n	[        R!                  S(U	5        [           [        b  [        sSSS5        s Sn	A	$  SSS5        O! , (       d  f       O= f/ s Sn	A	$ Sn	A	ff = f))zDCollect SSL certificate expire dates, issuers and auto-renew status.g      @Nr   )datetime)z/etc/letsencrypt/livez/etc/ssl/certsletsencryptz**/fullchain*z**/*.pem   privkeyr   z*SSL path read permission denied for %s: %sr  opensslx509z-nooutz-issuerz-enddatez-inr   zissuer==rT   r   z\bO\s*=\s*([^,]+)z\bCN\s*=\s*([^,]+)z	notAfter=z%b %d %H:%M:%S %Y %ZZFcustomz/etc/letsencrypt/live/([^/]+)\r   z/etc/letsencrypt/renewal/z.confT)r|   expireissuer
auto_renewzFailed to read SSL cert %s: %sz/SSL collector failed, falling back to cache: %s)r   _ssl_cache_lockr   r   r  r   is_dirglobis_filer[   rx   r  r\   rH  rz   r   r   r:   rM  rr  r]   r!   r    rV   searchgroupstrptime	isoformatr%   rL  )r  r   r  	cert_dirscertsfound_paths	directorybasepr   certrv  r  enddater(   
raw_issuermm_cnenddate_strdtr  provider	cert_namerenewal_confs                           r*   collect_sslr  &  s   
 C
))+C	&C/,AS+H" 
 ";IEL"II{{}} I-!YY799;;'..q1 8 "$))J"78"=99;;9AFF+BuTUTZTZT`T`TbGb'..q1 > #"  $D,%y&(Iz[`befjbk&lm&F"G & 1 1 3??955)-C);B)?)E)E)GJ "		*>
 KA )*)9)9);')yy1F
'S#'-1ZZ]-@-@-BF-7F!__[99*.**S!*<R*@*F*F*HK6%-%6%6{DZ%[*,,,.3*>! !4( "'J0=T0J}PXH $I=0II&FD	HYHYZ^`cHde()
I+/2KI;V[0\+]L+3355-1
LL #D	")"(&0	" E  %^ #O!O  [ 
. $W- 		F	W6 $- 6*56( $W- 		:DF _  		CSI*& _* __ 	s  M6P  N=P ?-N0NP 3N>NN0NP D
O!#O%N=*B/OP 'P,	P 6
NN:N5.P 5N::P =O	OOOP!O>7P >PP 
PP P 
R"Q<>Q$	Q<R	Q<$
Q2	.Q<6R<Rc                    [         R                   " 5       n Sn [        R                  R                  S5      (       Gas  [	        SSSS9 nU H  nUR                  5       R                  5       n[        U5      S:  d  M2  US   nUR                  S5      =(       a    US	   R                  5       (       + =(       dT    UR                  S
5      =(       a    US	   R                  5       (       + =(       d    UR                  S5      =(       a    SU;  nU(       d  M  [        US   5      n[        US   5      nXU-   S-  -  nM     SSS5        Sn	[        b#  [        u  pX-
  nUS:  a  [        SX-
  U-  5      n	[        c#  X4q[         R                  " S5        [        5       $ X4q[        U	S-  S5      $  g! , (       d  f       Nx= f! [          a   n["        R%                  SU5         SnAgSnAff = f)z$Collect global Disk IO rate in MB/s.r   z/proc/diskstatsr   r   r   r   r   sdr   vdnvmer  r-   r   i   Nr   ro   r8  zDisk IO collector error: %s)r   rv   r|   r}   r   r    r!   r"   r]   rD  r#   r   r   r   collect_disk_ior   r%   r   r   )r   total_bytesr'   r(   r)   r   is_physical_devsectors_readsectors_writtenr2  
last_bytes	last_timer   r   s                 r*   r  r    s    ))+CK!677>>+,,'w?1D JJL..0E5zR'#Ah ^^D1K#b'//:K6K H ^^D1K#b'//:K6KH ^^F3F3 (
 +?+.uQx=L.1%(mO'?,Jc+QQK  @ L+(8%
O	q=#&s[-E,R#SL  '$/#5 

4 &(( +15q99= -B A @?<  6		/556sC   0G 	1F3>BF3*F3AG G 3
G=G 
G.G))G.c           
        [         [        [        [        [        [
        [        [        [        S.	n0 n[        [        U5      S9 nUR                  5        VVs0 sH  u  pEUR                  U5      U_M     nnn [        X`S9 H  nXg   n UR                  5       X$'   M     UR                  5        HP  u  ptXB;  d  M  UR'                  5       (       d  [         R#                  SU5        SX$'   M=   UR                  5       X$'   MR     SSS5        S	n	 [(        R*                  R-                  S
5      (       a?  [/        S
SSS9 n
[1        U
R3                  5       R5                  5       S   5      n	SSS5        O [7        U	5      US'   U$ s  snnf ! [         a&  n[         R#                  SXH5        SX$'    SnAGM2  SnAff = f! [$         a    [         R#                  SU 5         GN?f = f! [         a&  n[         R#                  SXH5        SX$'    SnAGM^  SnAff = f! , (       d  f       GN= f! , (       d  f       N= f! [         a     Nf = f)zExecute all collectors concurrently using a ThreadPoolExecutor with global timeout.

Individually catches collector exceptions so a failure does not block/affect others.
)	r5  r7  disknetworkprocessrs  r$  ssldisk_io)max_workersr0   z&Collector %s failed with exception: %sNz8Metrics collection exceeded global timeout of %s secondszCollector %s timed outzCollector %s failed late: %sr   z/proc/uptimer   r   r   r   uptime)r   r   r   r   rN  r  r  r  r  r   r"   r   submitr   r9   r%   r   warningTimeoutErrordonerv   r|   r}   r   r   r~   r!   r#   )r0   
collectorsresultsexecutorr  funcfuturesfuturer   r  r'   s              r*   collect_allr    s    ""$ "
J !G	J	8HAKAQAQASTAS:48??4($.AST		]&w@)$*MMOGM A $MMOLF"{{}}KK 8$?$(GM-(. , 
98 F77>>.))ncG<qzz|113A67 =< *
 FGHNI U ! )KK H$T$(GMM)  	]KKRT[\	] % -$BDN(,-/ 
9	8> =< s   HF6H:F=F
F=!H=1H/G$H/H: ?+H)*H: H

F:F5.F=5F::F== G!H G!!H$
H.HHHH
H&)
H73H: 7H: :
IIc                   [         R                  SU 5        [        R                  5       (       d   [        R                  " 5       n[        [        U S-
  S5      S9n[           UqSSS5        [        R                  " 5       U-
  n[        SX-
  5      n[        [        US-  5      5       H4  n[        R                  5       (       a    O[        R                  " S5        M6      [        R                  5       (       d  M  gg! , (       d  f       N= f! [         a6  n[         R                  S	U5        [        R                  " S
5         SnANiSnAff = f)z0Daemon thread loop that keeps the cache updated.z3Metrics cache updater thread started (interval=%ss)rT         @r  Ng?r   g      ?z!Error in metrics updater loop: %s      @)r   info_stop_eventis_setr   r  r   _cache_lockr   r   ranger#   r   r%   error)intervalr  datarl  
sleep_time_r   s          r*   _update_loopr    s    HHBHM  ""	Js8a<'=>D!%  iikJ.GS("45J3zA~./%%''

3 0   ""   	II93?JJsOO	s6   1D "D %A"D D  
D
D 
E,EEc                    [            [        b#  [        R                  5       (       a
   SSS5        g[        R	                  5         [
        R                  " [        U 4SSS9q[        R                  5         SSS5        g! , (       d  f       g= f)z8Start the background thread updater if it isn't running.NWolfMetricsUpdaterT)targetargsr  daemon)	r  r   is_aliver  clear	threadingThreadr  start)r  s    r*   start_updaterr    si     
&?+C+C+E+E 
 	#**%	
 	 
s   "A?AA??
Bc                 f    [         R                  5         [        b  [        R                  SS9  Sqgg)z#Stop the background thread updater.Ng       @r  )r  rJ  r   r^   r
  rk   r*   stop_updaterr    s/     OO"S) #rk   c                     [            [        (       a  [        R                  5       sSSS5        $  SSS5        [        R	                  S5        [        SS9$ ! , (       d  f       N,= f)zHRetrieve metrics from the cache, or collect them synchronously if empty.Nz6Metrics cache empty; performing synchronous collectionr  r  )r  r   copyr   r   r  r
  rk   r*   get_metricsr    sG    	>!&&( 
 

 IIFGs## 
s   A
A%)returnzdict[int, str])r8   z	list[str]r  z
str | None)r_   rM  r  rM  )r  r
   )r  zlist[dict[str, Any]])r  zdict[str, str])r  r   )r  )r0   r   r  r
   )r  r#   r  None)   )r  r  )5
__future__r   loggingrv   rV   r3   socketr   r  pathlibr   typingr   concurrent.futuresr   r   loggerr   r   r   __annotations__Lockr  r   Eventr  r   r   r  r   r   r  r   r   r   r   r+   r:   rj   r   r   r   r   rN  r  r  r  r  r  r  r  r  r  r
  rk   r*   <module>r     s>   "  	 	       ?  "$ #nn+/( /oo 37 / 6 E ^^% /3, 3 .." =A9 @481 8.0 + 0/3 , 3"(9|;|/d7tPfOd0fVr\~'X7t,  $rk   