MjUdZdZddlZddlZddlZddlmZddlmZm Z m Z ddl m Z m Z ddl mZddlmZmZmZmZmZdd lmZddlZdd lmZdd lmZdd lmZdd lm Z m!Z!ddl"m#Z#m$Z$m%Z%ddl&m'Z'ddl(m)Z)ddl*m+Z+m,Z,ddl-m.Z.dZ/ ddl0m1Z2n#e3$rZ4e4Z/dZ2YdZ4[4ndZ4[4wwxYweGddZ5eGddZ6eGddZ7GddeZ8de9de8fdZ:GddeZ;de9fd Zd#krHe.ej?e=e<ej@$e;ZAeAdSdS)%z' This module contains Autotracer class z ssa.modulesN) defaultdict) dataclassfieldasdict)datetime timedelta) fnmatchcase)IteratorOptional NamedTupleListIterable)urlparse)setup_database)SSAError)Common)iter_domains_dataiter_domain_url_data)statusdisabled_usersmisconfiguration_checks) load_tunables)autotracing_tunables_schema)autotracing_logautotracing_stats_file) sentry_initcZeZdZUdZeed<eed<eed<eed<eed<eed<eed<d S) URLzURL data containeruri avg_duration max_durationtotal_slow_reqs total_reqs belongs_tobelongs_to_userN)__name__ __module__ __qualname____doc__str__annotations__intM/opt/cloudlinux/venv/lib64/python3.11/site-packages/ssa/modules/autotracer.pyrr,sc HHHOOOOOOr.rceZdZUdZdZeed<dZeed<dZeed<dZ eed<dZ eed<dZ eed<dZ eed <dZ eed <dZeed <dZeed <dZeed <dS) RulesRejectszRejects counters containerrnon_wp throttleddensityslowness max_slownessdisablednginx frequency server_limit domain_limit no_domainN)r&r'r(r)r2r,r+r3r4r5r6r7r8r9r:r;r<r-r.r/r1r19s$$FCOOOIsGSHcL#HcE3NNNIsL#L#Isr.r1c\eZdZUdZeed<dZeed<dZeed<e e Z e ed<dS) StatszAutoTracer statistics container rules_versionrurls_processed urls_selected)default_factoryrejectsN) r&r'r(r)r*r+r@r,rArr1rCr-r.r/r>r>Jsa))NCM3!E,???G\?????r.r>c(eZdZUdZeed<eed<dS)URLSz" Representation of an URL domain_nameuri_pathN)r&r'r(r)r*r+r-r.r/rErETs1MMMMMr.rEurlreturnct|}|jr d|jnd}|jr |j|nd}|jdd}|dd}t ||S)z Split URL into domain_name and uripath including query string :param url: URL of format protocol://domain/path;parameters?query#fragment :return: namedtuple URL(domain_name, uripath) ?/zwww.:r)rquerypathnetlocreplacesplitrE)rH fragmentsqsr_no_www_netloc_no_port_netlocs r/ url_splitrX]s  I"+/ 9 Y_   rB%.^ r?rfurls_scheduledrrArequest_number Exceptionsave_iteration_stats)rhexc start_toolrHeris r/__call__zAutoTracer.__call__zs  # % % % %    K  5sz B B B FFFFF   w~~?@@ L !!G)**    !JKKK F/  ! K  1 2 2 2 GG      K   Says if nginx is enabled for a specific user NF) skip_nginxrnNginxUserCache is_enabled)rhrs r/nginx_is_enabledzAutoTracer.nginx_is_enableds3 ? Au*955@ @ur.ctd|jD}|jd||j|z S)z>Recalculate limit per server taking into account running taskscBg|]}|ddk|ddk|S)rrunninguserz *autotracing*r-).0tasks r/ z.s8 q q qdh91L1LQUV\Q]apQpQpTQpQpQpr.z&Number of running autotracing tasks %s)lenrerartper_server_limit)rh running_counts r/per_server_limit_recalculatedz(AutoTracer.per_server_limit_recalculatedsM q qdo q q q   BMRRR$}44r. full_listc|.tj}|jd|t jt |jz fd|DS)zQ Excludes tasks older than N days from the general list of tasks NzTask list loaded %s)dayscg|]S}|d|dndtkQ|TS) createtimeNr)getr, timestamp)rr n_days_agos r/rz1AutoTracer.excludes_old_tasks..sg   *.((<*@*@*L&&&RSWZ[e[o[o[q[qWrWrrr rrrr.)rnrerartrnowrmin_retracing_interval)rhrrs @r/excludes_old_taskszAutoTracer.excludes_old_taskss{   +--I K  3Y ? ? ?\^^iT5P&Q&Q&QQ     !    r. current_urlc\t|}|jD]}t|d}|j|jko|j|jk}t |j|jot |j|j}|s|r%|jd||ddSdS)z Excludes url from the list if it completely matches the current url or if domain names match and "*" follows the domain name in the list rHz2Skipped: URL %s was traced recently. Matched by %sTF)rXrerFrGr rart)rhrc task_datat direct_matchwildcard_matchs r/exclude_thesame_urlszAutoTracer.exclude_thesame_urlss k " "  I)E*++A=AM9VajAJ>VL( FFn;WXWacdcmKnKnN ~  !!He$ tt  ur.url_total_reqsdomain_total_reqsc|jrMtjtj||}|jd|||jkSdS)z-Check that URL density passes given thresholdzCalculated density %sT)r4npamincorrcoefrartdensity_threshold)rhrr url_densitys r/pass_by_densityzAutoTracer.pass_by_densitysT < 8'"+n>O"P"PQQK K  5{ C C C!77 7tr. url_durationscd|jz }tj||}|jd||||jkS)z The measure of "slowness" for URL is: at least N% of its requests take more than X seconds. N% -- self.slow_duration_percentage X -- self.slow_duration_threshold dz.Calculated %sth percentile %s for min duration)slow_duration_percentager percentilerartslow_duration_threshold)rhrreversed_percentilereversed_percentile_values r/pass_by_slowness_percentilez&AutoTracer.pass_by_slowness_percentilesX"D$AA$&M-AT$U$U!  <  %   )D,HHHr.ctj||j}|jd|j|||jkS)a The opposite to pass_by_slowness_percentile method. The measure of "much slowness" for URL is: at least N% of its requests must take less than X seconds. N% -- self.max_slow_duration_percentage X -- self.max_slow_duration_threshold z.Calculated %sth percentile %s for max duration)rrmax_slow_duration_percentagerartmax_slow_duration_threshold)rhrpercentile_values r/pass_by_max_slowness_percentilez*AutoTracer.pass_by_max_slowness_percentilesO=8YZZ  <  -     4#CCCr.url_throttled_reqsc|dSt|t|z dz}|jd|||jkS)zY Check that percent of throttled requests per URL passes given threshold NFrzCalculated throttled percent %s)sumrartallowed_throttling_percentage)rhrrthrottled_percents r/pass_by_allowed_throttlingz%AutoTracer.pass_by_allowed_throttling sX  %5 !344s>7J7JJcQ ;=NOOO D$FFFr. wp_statusc2|jrt|SdS)zx Check that URLs of a particular domain should be analyzed. For now we skip non-wordpress sites T)only_wpbool)rhrs r/pass_by_enginezAutoTracer.pass_by_engines < # ?? "tr.c #Kt|jD]}d}||jsQ|jd|j}|jjxj |z c_ |jxj |z c_ pt|j|j D][\}}}||j vr|jd||jxj dz c_ ||d|ds5|jd|jjxjdz c_||d|js5|jd|jjxjdz c_||s6|jd |jjxjdz c_F||s6|jd |jjxjdz c_|Y||j }|6|jd |jjxjdz c_|j}t7|t9t;j|t?|d t?|dtA||j | V]dS)a  Select all URLs suitable for auto tracing by very basic rules: - WP site - suitable throttling - suitable density - measure of "slow" URL ORDER OF RULES MUST NOT BE CHANGED: IT AFFECTS STATISTICS COUNTERS Nz Skipped by engine: non-wordpresszProcessing URL %srkrrzSkipped by throttled percentzSkipped by densityzSkipped by slowness percentilez"Skipped by max slowness percentilez"Skipped by unavailable domain info url_slow_reqs)r r"r#r!r$r%)!rrgris_a_wordpress_domainrart urls_numberrfrCr2r@rrFnon_url_fieldsrrr3rrr4rr5rr6rr<rrr,rmeanrmax)rh domain_data domain_owner skipped_countrH durationsdatars r/urls_computationally_filteredz(AutoTracer.urls_computationally_filtered"s.-T[99J J KL&&{'HII  !!"DEEE!, 7  "))]:)) ))]:)) )=T[+Ja(b(b8 8 $Y$--- !!"5s;;; ))Q.))66txx@T7U7UW[\lWmnnK%%&DEEEJ&00A500++D1A,BKDabbK%%&:;;;J&..!3..77 BBK%%&FGGGJ&//14//;;IFFK%%&JKKKJ&33q833 '"&"6"6{7N"O"OK"* ))*NOOO *44944 '2'7 !$RWY%7%7!8!8$'_(=$>$>"4(8#9::!$Y*6$0a8 %J J r.stats_collectedc#K||D]}|j|jvr;|jd|j|jjxjdz c_K| |jr;|jd|j|jjxj dz c_ |VdS)z From selected by computed thresholds URLs take those for which: - autotracing enabled - nginx disabled ORDER OF RULES MUST NOT BE CHANGED: IT AFFECTS STATISTICS COUNTERS z'Skipped: autotracing is disabled for %srkz Skipped: nginx is enabled for %sN) fill_in_disabled_usersrr%rrartrfrCr7rr8)rhrrHs r/rAzAutoTracer.urls_selectedws ##%%%5577  C"d&999 !!"KSM`aaa "++q0++$$S%899  !!"DcFYZZZ "((A-((IIII  r.c#Kd}tt}|}|jd|||_|}|D]}||j r|j j xj dz c_ 7||krv||j |jkr|dz }||j xxdz cc<|Vr|jd|j |j|j j xjdz c_|jd|j ||j j xjdz c_dS)a= Schedule autotracing by sorted list taking into account the limits: - no same task for 10 days - limit per server - limit per domain ORDER OF RULES MUST NOT BE CHANGED: IT AFFECTS STATISTICS COUNTERS Return resulting list of URLs scheduled for auto tracing rzSorted scheduled list %srkz#Skipped URL %s by domain limit (%s)z#Skipped URL %s by server limit (%s)N)rr, urls_sortedrartrrerrrrfrCr9r$per_domain_limitr;r:)rhgeneral_tasks_countertasks_counter_per_domain sorted_urlsper_server_smart_limitrHs r/rvzAutoTracer.urls_scheduleds!"#.s#3#3 &&((  4kBBB1133!%!C!C!E!E 5 5C((11  ",,1,,$'===+CN;d>SSS)Q.),S^<<<A<<<IIIIK%%=- J&33q8333 !!9G*  "//14///9 5 5r.ctt|dd}t|ddS)zd Sort URLs by total number of requests first and by average duration second c|jSN)r us r/z(AutoTracer.urls_sorted..sq~r.T)keyreversec|jSr)r#rs r/rz(AutoTracer.urls_sorted..sr.)sortedrdrA)rh first_series r/rzAutoTracer.urls_sortedsJ T$"4"4"6"677=U=U_cddd k'='=tLLLLr.c,t|_dS)z6 Fill internal list of disabled users N)r)rhs r/rz!AutoTracer.fill_in_disabled_userss-..r.cD|j ttd5}tjt |j|ddddS#1swxYwYdS#t $r3}|jdt|Yd}~dSd}~wwxYwdS)zI Save collected statistics for current iteration to file Nwz*Unable to save iteration stats to file: %s) rfopenrjsondumprOSErrorrawarningr*)rh stats_filer|s r/ryzAutoTracer.save_iteration_statss : ! Z0#66>*IfTZ00*===>>>>>>>>>>>>>>>>>> Z Z Z ##$PRUVWRXRXYYYYYYYYY Z " !s:A (A A AA AA B*(BBc x tt5}tj|}t |d|d|dt di|d}dddn #1swxYwYn6#t tjtf$rt |j }YnwxYwt|S)z@ Load statistics for latest iteration from file r?r@rArCNr-) rrrloadr>r1rJSONDecodeErrorKeyErrorr?r)rhr_data stat_datas r/load_iteration_statszAutoTracer.load_iteration_statss 2,--  *--!/**+/* 445#344                 -x8 2 2 2d011III 2i   s5A7A A+ A7+A//A72A/3A770B*)B*c |}|ttdt t |S)rLr)rdisabled_users_quantity)rupdatedictrrr)rh stats_loadeds r/ get_statszAutoTracer.get_statssS0022 D SQ_QaQaMbMbcccdddr.r)rIN)&r&r'r(r)r^r} staticmethodrrr*r objectrrrr,rrdrrrrrrrrr rrrArvr rrryrr __classcell__)ris@r/rZrZks#======#$#$#$#$#$JNtNNN\N 1S1Xf-=111\1#$5s5555   HTN  d     *dtPTI#I4IIII DXc]DtDDDD GXd^ G]a Gfj G G G G4Sx}SSSSjXd^xPS}2.5 .5.5.5.5`MT#YMMMM//// Z Z Z Z!d!!!!"4r.rZctjtjtdS)a=Absolute path of the standalone auto-tracer log. Always resolves inside the fixed, root-owned clos_ssa log directory (derived from ``autotracing_log``) rather than against the caller's cwd, so the destination cannot be redirected by the directory the dev entry point happens to be launched from. zauto_tracer_standalone.log)rorPjoindirnamerr-r.r/standalone_log_pathrs) 7<<88:V W WWr.log_pathctj|tjtjztjztjzd}tj|dS)aOpen ``log_path`` for appending and return the file object. Uses ``O_NOFOLLOW`` so a symlink pre-planted at the target is refused rather than followed: the open raises instead of appending through the link to an arbitrary root-owned file. ia)rorO_WRONLYO_CREATO_APPEND O_NOFOLLOWfdopen)rlog_fds r/open_standalone_logrsAWXr{RZ7"+E UW\ ] ]F 9VS ! !!r.__main__)streamlevel)Br)rcrr_ro collectionsr dataclassesrrrrrfnmatchr typingr r r r r urllib.parsernumpyrssa.dbrssa.internal.exceptionsrssa.modules.commonrssa.modules.storagerrssa.autotracingrrrssa.configurationrssa.configuration.schemesrssa.internal.constantsrrssa.internal.utilsrrrxray.shared_libraryshared_libraryrn ImportErrorr|rr1r>rEr*rXrZrrr& basicConfigDEBUGrr-r.r/r)s  ######0000000000((((((((AAAAAAAAAAAAAA!!!!!!!!!!!!,,,,,,%%%%%%GGGGGGGGKKKKKKKKKK++++++AAAAAAJJJJJJJJ*************HHHHHH                       @@@@@@@ @: &3 &4 & & & &DDDDDDDDN XSXXXX"#"""" zKMMMG223F3F3H3HIIQXQ^____ AACCCCCsBB"BB"