
    biY                         S r SSKrSSKrSSKrSSKJr  SSKJrJr  SSKJ	r	J
r
JrJr  \R                  " \5      r " S S5      rg)zI
SonarQube trend report generator for analyzing metric trends over time.
    N)Path)datetime	timedelta)DictListOptionalTuplec                      \ rS rSrSr/ SQr1 SkrS!S\S\S\4S jjr S"S	\S
\	\   S\
S\\\	\   4   4S jjrS\\\	\   4   S\\\4   4S jrS\\   S\\   4S jrS\S\4S jrS\S\\\4   4S jr   S#S	\S\\   S\\\4   S\
S\4
S jjrS	\S\S\\\4   S\
S\4
S jrS\\   S\S\4S jrS\S\	\   S\4S jrS"S	\S\
S\\   4S jjrS	\S\\   4S jrS rg)$TrendReportGenerator   z?Generates HTML trend reports from SonarQube historical metrics.)bugsvulnerabilitiescode_smellscoverageduplicated_lines_densityncloc>   r   r   r   r   	sonar_urlsonar_tokenreports_dirc                     UR                  S5      U l        X l        [        U5      U l        U R                  R                  SSS9  SSU R                   30U l        g)z
Initialize trend report generator.

Args:
    sonar_url: SonarQube server URL
    sonar_token: SonarQube authentication token
    reports_dir: Directory where trend reports will be saved
/T)parentsexist_okAuthorizationzBearer N)rstripr   r   r   r   mkdirheaders)selfr   r   r   s       6C:\wamp64\www\sonar_scan\src\trend_report_generator.py__init__TrendReportGenerator.__init__   s\     #))#.&,td;'743C3C2D)EF    project_keymetric_keysdaysreturnc                 <   0 n[         R                  " 5       nU[        US9-
  n[        R	                  SU SUR                  5        SUR                  5        35        U GH  n U R                   S3nUUUR                  S5      UR                  S5      S.n	[        R                  " XU R                  SS	9n
U
R                  S
:X  a  U
R                  5       nUR                  S/ 5      nU(       af  US   nUR                  S/ 5      nU(       a*  XU'   [        R                  S[        U5       SU 35        M  [        R                  SU 35        / XG'   M  [        R                  SU 35        / XG'   GM  U
R                  S:X  a  [        R                  SU 35        / XG'   GMF  [        R                  SU SU
R                   SU
R                   SS
  35        / XG'   GM     U$ ! ["         a+  n[        R%                  SU SU 35        / XG'    SnAGM  SnAff = f)a  
Fetch historical metric data from SonarQube API.

Args:
    project_key: SonarQube project key
    metric_keys: List of metric keys to fetch
    days: Number of days of history to fetch
    
Returns:
    Dictionary mapping metric keys to lists of historical data points
)r%   z Fetching historical metrics for z from z to z/api/measures/search_history%Y-%m-%d)	componentmetricsfromto   paramsr   timeout   measuresr   historyzFetched z data points for z"No history array found for metric zNo measures found for metric i  zProject or metric not found: zFailed to fetch z: HTTP z - Nz#Error fetching historical data for : )r   nowr   loggerinfodater   strftimerequestsgetr   status_codejsondebuglenwarningtext	Exceptionerror)r   r#   r$   r%   historical_datato_date	from_date
metric_keyurlr/   responsedatar2   metric_datar3   es                   r   fetch_historical_metrics-TrendReportGenerator.fetch_historical_metrics-   s   "  ,,.iT22	6{m6)..JZI[[_`g`l`l`n_opq%J%1((DE "-)%..z:!**:6	 $<<DLLZ\]''3.#==?D#xx
B7H&.qk"-//)R"@":AJ7"LL8CL>ARS]R^)_`"NN-OPZ|+\]:<O7)Fzl'ST683))S0NN%B:,#OP24O/NN%5j\I]I]H^^abjboboptqtbuav#wx24O/E &P 	  1B:,bQRPSTU.0++1s1   %CG&:G&G&7,G&&9G&&
H0HHrD   c           	      \   0 nUR                  5        GH  u  p4U(       a  [        U5      S:  a  SSSSSSS.X#'   M)  [        US SS9nUS   n[        U5      S	:  a  US
   OUS   nU R                  UR	                  S5      5      nU R                  UR	                  S5      5      n	Ub  U	c  UU	SSSSS.X#'   M  X-
  n
U	S:w  a  X-  S-  nOU
S:  a  SO	U
S:  a  SOSnX0R
                  ;   nU(       a  U
S:  nOU
S:  n[        U5      S:  a  SnOU(       a  SnOSnUU	U
UUUUS.X#'   GM     U$ )z
Calculate upward/downward trends for each metric.

Args:
    historical_data: Dictionary mapping metric keys to historical data points
    
Returns:
    Dictionary with trend information for each metric
   Ninsufficient_data)currentpreviouschangechange_percenttrendis_improvingc                 &    U R                  SS5      $ Nr8    r;   xs    r   <lambda>7TrendReportGenerator.calculate_trends.<locals>.<lambda>   s    155;Lr"   T)keyreverser      valueno_datad   g      Y@g      Yg        g{Gz?stable	improving	degrading)rR   rS   rT   rU   rV   rW   r3   )itemsr?   sorted_parse_metric_valuer;   LOWER_IS_BETTERabs)r   rD   trendsrG   r3   sorted_historycurrent_pointprevious_pointcurrent_valueprevious_valuerT   rU   is_lower_betterrW   rV   s                  r   calculate_trends%TrendReportGenerator.calculate_trendsp   s    #2#8#8#:Jc'lQ.  $ $"&*0$(&"  $G1LVZ[N +1-M36~3F3J^B/P^_`PaN 44]5F5Fw5OPM!55n6H6H6QRN$(>, ."&*&$(&"  #3F ""("9S!@*01*FQJ&TW
 ),@,@@O%z%z >"T) ## )* "0 ,)"F{ $;N r"   rd   c                     Uc  g [        U[        5      (       a0  UR                  S5      (       a  [        UR	                  S5      5      $ [        U5      $ ! [
        [        4 a     gf = f)z
Parse metric value from string to float.

Args:
    value: Metric value as string
    
Returns:
    Float value or None if invalid
N%)
isinstancestrendswithfloatr   
ValueError	TypeError)r   rd   s     r   rl   (TrendReportGenerator._parse_metric_value   sa     =	%%%%..*=*=U\\#.//<I& 		s   AA 
A A)(A)rG   c                 B    UR                  SS5      R                  5       $ )zFormat metric key for display._ )replacetitle)r   rG   s     r   _format_metric_name(TrendReportGenerator._format_metric_name   s    !!#s+1133r"   
trend_datac                 t    UR                  SS5      nUR                  S5      nUS:X  a  gUS:X  a  gUS:X  a  g	g
)zT
Get trend indicator symbol and color.

Returns:
    Tuple of (symbol, color_class)
rV   unknownrW   rh   )u   ↑ztext-successri   )u   ↓ztext-dangerrg   )u   →ztext-secondary)u   —z
text-mutedr[   )r   r   rV   rW   s       r   _get_trend_indicator)TrendReportGenerator._get_trend_indicator   sF     w	2!~~n5K*k!)h,(r"   Nproject_nametrends_datac                 v   Uc  Un[         R                  " 5       R                  S5      nU SU S3nU R                  U-  n[        R                  SU 35        U R                  XX45      n[        USSS9 n	U	R                  U5        SSS5        [        R                  S	U 35        U$ ! , (       d  f       N(= f)
z
Generate HTML trend report.

Args:
    project_key: SonarQube project key
    project_name: Project display name (optional)
    trends_data: Calculated trends data
    days: Number of days analyzed
    
Returns:
    Path to generated HTML file
Nz%Y%m%d_%H%M%S_trends_z.htmlzGenerating HTML trend report: wzutf-8)encodingz%Trend report generated successfully: )	r   r5   r9   r   r6   r7   _build_html_contentopenwrite)
r   r#   r   r   r%   	timestampfilenamefilepathhtml_contentfs
             r   generate_html_report)TrendReportGenerator.generate_html_report   s    & &LLLN++O<	!](9+U;##h.4XJ?@ //;] (C'2aGGL! 3 	;H:FG	 32s   6B**
B8c                    Sn/ nU R                    GH+  nUR                  U0 5      nU R                  U5      u  pUR                  S5      nUR                  S5      nUR                  S5      nUR                  S5      nU R                  X5      nU R                  X5      nUb.  Ub+  [	        U[
        5      (       a  US O
[        U5      nUS S3nOSnSnUS	U R                  U5       S
U SU SU SU SU
 SU	 S3-  nUR                  S/ 5      nU(       d  GM
  UR                  U R                  UU5      5        GM.     SnU(       a9  [        U5       H)  u  nnSU 3nUSU R                  US   5       SU S3-  nM+     OSnSnU(       a5  [        U5       H&  u  nnSU 3nUSU SU SU SUS    SU SU S3-  nM(     SU SU S U S![        R                  " 5       R                  S"5       S#U S$U S%U S&U S'3nU$ )(zBuild complete HTML content.rZ   rR   rS   rT   rU   z+.2fry   N/Az.
            <tr>
                <td><strong>z#</strong></td>
                <td>z</td>
                <td>z!</td>
                <td class="z
"><strong>z-</strong></td>
            </tr>
            r3   chart_z
                <div class="col-md-6 mb-4">
                    <div class="card">
                        <div class="card-header">
                            <h5 class="mb-0">metricz}</h5>
                        </div>
                        <div class="card-body">
                            <canvas id="zm"></canvas>
                        </div>
                    </div>
                </div>
                zf<div class="col-12"><div class="alert alert-info">No historical data available for charts.</div></div>z
                var ctx_z = document.getElementById('z0').getContext('2d');
                var config_z = configz ;
                new Chart(ctx_z	, config_z);
                z<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SonarQube Trend Report - a  </title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
    <style>
        body {
            background-color: #f8f9fa;
            padding: 20px 0;
        }
        .card {
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            margin-bottom: 20px;
        }
        .card-header {
            background-color: #0891b2;
            color: white;
        }
        .table-responsive {
            background: white;
            border-radius: 8px;
            padding: 20px;
        }
        .trend-up {
            color: #28a745;
        }
        .trend-down {
            color: #dc3545;
        }
        .trend-stable {
            color: #6c757d;
        }
        h1 {
            color: #0891b2;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-12">
                <h1 class="mb-4">SonarQube Trend Report</h1>
                <div class="card mb-4">
                    <div class="card-body">
                        <h5 class="card-title">Project Information</h5>
                        <p class="mb-1"><strong>Project Key:</strong> zL</p>
                        <p class="mb-1"><strong>Project Name:</strong> zK</p>
                        <p class="mb-1"><strong>Report Date:</strong> z%Y-%m-%d %H:%M:%SzT</p>
                        <p class="mb-0"><strong>Analysis Period:</strong> Last a   days</p>
                    </div>
                </div>
                
                <div class="table-responsive">
                    <h3 class="mb-3">Trend Summary</h3>
                    <table class="table table-striped table-hover">
                        <thead class="table-dark">
                            <tr>
                                <th>Metric</th>
                                <th>Current Value</th>
                                <th>Previous Value</th>
                                <th>Change</th>
                                <th>Change %</th>
                                <th>Trend</th>
                            </tr>
                        </thead>
                        <tbody>
                            a!  
                        </tbody>
                    </table>
                </div>
                
                <div class="row mt-4">
                    <div class="col-12">
                        <h3 class="mb-3">Trend Charts</h3>
                    </div>
                    z
                </div>
            </div>
        </div>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        z
    </script>
</body>
</html>
)CORE_METRICSr;   r   _format_valuerz   r}   r{   r   append_build_chart_config	enumerater   r5   r9   )r   r#   r   r   r%   summary_rowschart_configsrG   
trend_infosymbolcolor_classrR   rS   rT   rU   current_strprevious_str
change_strchange_percent_strr3   charts_htmlichart_configchart_idchart_jshtmls                             r   r   (TrendReportGenerator._build_html_content  s    ++J$R8J"&";";J"GF nnY/G!~~j1H^^H-F'^^,<=N ,,WAK--hCL!n&@1;FE1J1Jt}PSTZP[
(6t'<A%>""
%*" !!55jAB C M "!N #L !'( )'=
6( ;	 	L !nnY3Gw$$T%=%=j'%RSE ,J #,]#;<#A3< $. /3.F.F|T\G].^-_ `) *2
 3   $< CK #,]#;<#A3< !7z B3c,x"8!9 : c1# .  $<%
 &2N +3GV HSm THHT~ VGGO||~G^G^_rGsFt uPPTv V$ *N 	+ !M "	 

 mZv r"   c                    Uc  gUS:X  d  US:X  a  US S3$ US:X  a3  [        U[        [        45      (       a  [        U5      S $ [        U5      $ [        U[        [        45      (       a  U[        U5      :X  a  [        U5      S $ US $ )z Format metric value for display.r   r   r   z.2fry   r   ,)rz   intr}   r{   )r   rd   rG   s      r   r   "TrendReportGenerator._format_value  s    = #z5O'OC[?"7"(253,(G(Gc%j^WSQVZW(253,(G(GEUXY^U_L_c%j^shmnqgrsr"   r3   c           
      (   [        US S9n/ n/ nU H  nUR                  SS5      nU R                  UR                  S5      5      nU(       d  M>  Uc  MC   SU;   a'  [        R                  " UR                  SS	5      5      n	O[        R                  " USS
 S5      n	UR                  U	R                  S5      5        UR                  U5        M     XR                  ;   nU(       a  SOSnU(       a  SOSnSUU R                  U5      UUUSSSS./S.SSSSS00SSS00S.S.nU[        R                   " U5      S.$ ! [         aJ  n
[        R                  SU SU
 35        UR                  [        U5      S
:  a  USS
 OU5         Sn
A
NSn
A
ff = f) z*Build Chart.js configuration for a metric.c                 &    U R                  SS5      $ rY   r[   r\   s    r   r^   :TrendReportGenerator._build_chart_config.<locals>.<lambda>  s    quuVR7Hr"   )r`   r8   rZ   rd   NTZz+00:00
   r(   zDate parsing error for r4   zrgb(220, 53, 69)zrgb(40, 167, 69)zrgba(220, 53, 69, 0.1)zrgba(40, 167, 69, 0.1)linerP   Tg?)labelrJ   borderColorbackgroundColorborderWidthfilltension)labelsdatasetsybeginAtZeroFlegenddisplay)
responsivemaintainAspectRatioscalesplugins)typerJ   options)r   r   )rk   r;   rl   r   fromisoformatr   strptimer   r9   rB   r6   r>   r?   rm   r   r=   dumps)r   rG   r3   rp   r   rJ   pointdate_strrd   date_objrL   ru   border_colorbackground_colorr   s                  r   r   (TrendReportGenerator._build_chart_config  s     -HI #Eyy,H,,UYYw-?@ExE-Vh#+#9#9(:J:J3PX:Y#Z $,#4#4Xcr]J#OMM("3"3J"?@ E") $. %(<(<<-<)BT7F3Ld  !55jA #/'7#$ "  #'+%u !4
> !jj(
 	
U ! VLL#:8*Bqc!JKMM3x=B3F(3B-HUUVs   A'D==
FA FFc                     U R                  U5      n[        R                  SU 35        U R                  UU R                  U5      n[        R                  S5        U R                  U5      n[        R                  S5        U R                  UUUU5      nU$ ! [         a"  n[        R                  SU 35         SnAgSnAff = f)z
Main entry point to generate trend report.

Args:
    project_key: SonarQube project key
    days: Number of days of history to analyze
    
Returns:
    Path to generated HTML file or None if failed
z)Fetching historical metrics for project: zCalculating trends...zGenerating HTML report...z!Failed to generate trend report: N)	_get_project_namer6   r7   rM   r   rv   r   rB   rC   )r   r#   r%   r   rD   r   report_pathrL   s           r   generate_report$TrendReportGenerator.generate_report  s    	11+>L KKCK=QR";;!!O KK/0//@K KK3433	K  	LL<QC@A	s   BB 
C#C  Cc                     U R                    S3nSU0n[        R                  " X#U R                  SS9nUR                  S:X  aT  UR                  5       nUR                  S/ 5      nU H,  nUR                  S5      U:X  d  M  UR                  SU5      s  $    U$ ! [         a$  n[        R                  S	U 35        Us S
nA$ S
nAff = f)z$Get project name from SonarQube API.z/api/projects/searchprojectsr-   r.   r1   
componentsr`   namezFailed to fetch project name: N)	r   r:   r;   r   r<   r=   rB   r6   r@   )	r   r#   rH   r/   rI   rJ   r   r)   rL   s	            r   r   &TrendReportGenerator._get_project_nameC  s    	^^$$89C +.F||CVXYH##s*}}!XXlB7
!+I }}U+{:(}}V[AA ",  	NN;A3?@	s*   A=B B B 
C	%C>C	C	)r   r   r   r   )z./reports/trends)r-   )NNr-   )__name__
__module____qualname____firstlineno____doc__r   rm   r{   r    r   r   r   rM   rv   r   r}   rl   r   r	   r   r   r   r   r   r   r   r   __static_attributes__ r"   r   r   r      s   IL ]OG# GC Gc G& 	AA #YA 	A
 
c4:o	AFSS$t*_0E S$sTXy/ Sj# 8E? *4c 4c 4)t )c3h ), '+'+$$ sm$ #t)_	$
 $ 
$Lll l #t)_	l
 l 
l\t8E? t t tE
c E
DJ E
4 E
N(3 (c (8D> (TS Xc] r"   r   )r   loggingr:   r=   pathlibr   r   r   typingr   r   r   r	   	getLoggerr   r6   r   r   r"   r   <module>r      s=        ( . .			8	$G	 G	r"   