r113467 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r113466‎ | r113467 | r113468 >
Date:14:48, 9 March 2012
Author:ezachte
Status:new
Tags:
Comment:
presentation of traffic counts now per day or month normalized or month raw, errata moved to bottom of page, static texts tweaks, new functions to generate html form and head section
Modified paths:
  • /trunk/wikistats/squids/SquidReportArchive.pl (modified) (history)

Diff [purge]

Index: trunk/wikistats/squids/SquidReportArchive.pl
@@ -103,6 +103,8 @@
104104 }
105105 &Log ("Report month = $reportmonth\n") ;
106106
 107+ $days_in_month = &DaysInMonth (substr ($reportmonth,0,4), substr ($reportmonth,5,2)) ;
 108+
107109 $threshold_mime = 0 ;
108110 $threshold_project = 10 ;
109111
@@ -419,7 +421,7 @@
420422 $timespan = ($timetill - $timefrom) / 3600 ;
421423 $multiplier = (24 * 3600) / ($timetill - $timefrom) ;
422424 &Log ("Multiplier = $multiplier\n") ;
423 - $header =~ s/DATE/Daily averages, based on sample period: $period (yyyy-mm-dd)/ ;
 425+ $header =~ s/DATE/Monthly requests or daily averages, for period: $period (yyyy-mm-dd)/ ;
424426 }
425427
426428 sub SetPeriod
@@ -441,7 +443,7 @@
442444 $multiplier = (24 * 3600) / ($timetill - $timefrom) ;
443445
444446 $period = sprintf ("%d %s %d - %d %s %d", $day_first, month_english_short ($month_first-1), $year_first, $day_last, month_english_short ($month_last-1), $year_last) ;
445 - $header =~ s/DATE/Daily averages, based on sample period: $period/ ;
 447+ $header =~ s/DATE/Monthly requests or daily averages, for period: $period/ ;
446448 &Log ("Sample period: $period => for daily averages multiplier = " . sprintf ("%.2f",$multiplier) . "\n") ;
447449 }
448450
@@ -450,61 +452,30 @@
451453 &Log ("\nPrepHtml\n\n") ;
452454
453455 $language = "en" ;
454 - $header = "<!DOCTYPE FILE_HTML PUBLIC '-//W3C//DTD FILE_HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>\n" .
455 - "<html lang='en'>\n" .
456 - "<head>\n" .
457 - "<title>TITLE</title>\n" .
458 - "<meta http-equiv='Content-type' content='text/html; charset=iso-8859-1'>\n" .
459 - "<meta name='robots' content='index,follow'>\n" .
460 - "<script language='javascript' type='text/javascript' src='../WikipediaStatistics13.js'></script>\n" .
461 - "<style type='text/css'>\n" .
462 - "<!--\n" .
463 - "body {font-family:arial,sans-serif; font-size:12px }\n" .
464 - "h2 {margin:0px 0px 3px 0px; font-size:18px}\n" .
465 - "table {font-size:12px ;}\n" .
466 - "td {white-space:wrap; text-align:right; padding-left:2px; padding-right:2px; padding-top:1px;padding-bottom:0px ; font-size:12px ; vertical-align:middle}\n" .
467 - "th {white-space:nowrap; text-align:right; padding-left:2px; padding-right:2px; padding-top:1px;padding-bottom:0px ; font-size:12px ; vertical-align:top ; font-width:bold}\n" .
468 - "th.small {white-space:wrap; text-align:right; padding-left:2px; padding-right:2px; padding-top:1px;padding-bottom:0px ; font-size:11px ; vertical-align:top ; font-width:bold}\n" .
469 - "td.hl {text-align:left;vertical-align:top;}\n" .
470 - "td.hr {text-align:right;vertical-align:top;}\n" .
471 - "td.hc {text-align:center;vertical-align:top;}\n" .
472 - "td.r {text-align:right; border: inset 1px #FFFFFF}\n" .
473 - "td.c {text-align:center; border: inset 1px #FFFFFF}\n" .
474 - "td.l {text-align:left; border: inset 1px #FFFFFF}\n" .
475 - "th.c {text-align:center; border: inset 1px #FFFFFF}\n" .
476 - "th.l {text-align:left; border: inset 1px #FFFFFF}\n" .
477 - "th.r {text-align:right; border: inset 1px #FFFFFF}\n" .
478 - "th.lh3 {text-align:left; border: inset 1px #FFFFFF ; font-size:14px}\n" .
479 - "a:link { color:blue;text-decoration:none;}\n" .
480 - "a:visited {color:#0000FF;text-decoration:none;}\n" .
481 - "a:active {color:#0000FF;text-decoration:none;}\n" .
482 - "a:hover {color:#FF00FF;text-decoration:underline}\n" .
483 - "-->\n" .
484 - "</style>\n" .
485 - "<body bgcolor='\#FFFFDD'>\n<table width=100%>\n<tr><td class=hl>\n<h2>HEADER</h2>\n<b>DATE</b>\n</td>\n<td class=hr>" .
486 - "<input type='button' value=' Archive ' onclick='window.location=\"http://stats.wikimedia.org/archive/squid_reports\"'> " .
487 - "<input type='button' value=' Wikimedia Statistics ' onclick='window.location=\"http://stats.wikimedia.org\"'>" .
488 - "</td></tr>\n</table><hr>" .
489 - # "&nbsp;This analysis is based on a 1:1000 sampled server log (squids) X1000\nALSO<p>" ;
490 - "&nbsp;This analysis is based on a 1:1000 sampled server log (squids) X1000\nALSO<br>" ;
 456+ $header = &HtmlHead ;
 457+ $form = &HtmlForm ;
 458+ $header.= "<body bgcolor='\#FFFFDD'>\n$form\n<hr>" .
 459+ # "&nbsp;This analysis is based on a 1:1000 sampled server log (squids) X1000\nALSO<br>" ; # X1000 obsolete (may become a toggle ?)
 460+ "&nbsp;This analysis is based on a 1:1000 sampled server log (squids)<p>\nALSO, and <a href='#errata'><b>notes about reliability of these data<\/b><\/a><br><br>" ;
491461
492462 if ($reportcountries)
493463 {
494 - $header .= "<p>&nbsp;<font color=#900000>WMF traffic logging service suffered from server capacity problems from Nov 2009 till July 2010 and again in Aug/Sep/Oct 2011.<br>" .
 464+ $errata .= "<p>&nbsp;<font color=#900000>WMF traffic logging service suffered from server capacity problems from Nov 2009 till July 2010 and again in Aug/Sep/Oct 2011.<br>" .
495465 "&nbsp;Data loss only occurred during peak hours. It therefore may have had somewhat different impact for traffic from different parts of the world." ;
496466 }
497467 else
498468 {
499 - $header .= "<font color=#900000>WMF traffic logging service suffered from server capacity problems in Aug/Sep/Oct 2011.<br>" .
 469+ $errata .= "<font color=#900000>WMF traffic logging service suffered from server capacity problems in Aug/Sep/Oct 2011.<br>" .
500470 "Absolute traffic counts for October 2011 are approximatly 7% too low.<br>" .
501471 "Data loss only occurred during peak hours. It therefore may have had somewhat different impact for traffic from different parts of the world.<br>" .
502472 "and may have also skewed relative figures like share of traffic per browser or operating system.</font><p>" ;
503 - $header .= "<font color=#900000>From mid September till late November squid log records for mobile traffic were in invalid format.<br>" .
504 - "Data could be repaired for logs from mid October onwards. Older logs were no longer available.<p>" ;
505 - $header .= "<font color=#900000>In a an unrelated server outage precisely half of traffic to WMF mobile sites was not counted from Oct 16 - Nov 29 (one of two load-balanced servers did not report traffic).<br>" .
 473+ $errata .= "<font color=#900000>From mid September till late November squid log records for mobile traffic were in invalid format.<br>" .
 474+ "Data could be repaired for logs from mid October onwards. Older logs were no longer available.</font><p>" ;
 475+ $errata .= "<font color=#900000>In a an unrelated server outage precisely half of traffic to WMF mobile sites was not counted from Oct 16 - Nov 29 (one of two load-balanced servers did not report traffic).<br>" .
506476 "WMF has since improved server monitoring, so that similar outages should be detected and fixed much faster from now on.</font><p>" ;
507477 }
508478 # to be localized some day like any reports
 479+ $out_explorer = "<font color=#800000>Note: page may load slower on Microsoft Internet explorer than on other major browsers</font>" ;
509480 $out_license = "All data and images on this page are in the public domain." ;
510481 $out_generated = "Generated on " ;
511482 $out_author = "Author" ;
@@ -514,12 +485,13 @@
515486 $out_mymail = "ezachte@### (no spam: ### = wikimedia.org)" ;
516487 $out_mysite = "http://infodisiac.com/" ;
517488
518 - $colophon = "<p>\n" .
 489+ $colophon = "<p><a id='errata' name='errata'><b>Errata:</b><p>$errata<p>" .
519490 $out_generated . date_time_english (time) . "\n<br>" .
520491 $out_author . ":" . $out_myname .
521492 " (<a href='" . $out_mysite . "'>" . $out_site . "</a>)\n<br>" .
522493 "$out_mail: $out_mymail<br>\n" .
523 - "$out_license" .
 494+ "$out_license<br>" .
 495+ "$out_explorer" .
524496 "</small>\n" .
525497 "</body>\n" .
526498 "</html>\n" ;
@@ -2107,6 +2079,22 @@
21082080 $html =~ s/LINKS/$link_requests $link_origins \/ $link_methods \/ $link_scripts \/ $link_skins \/ $link_crawlers \/ $link_opsys \/ $dummy_browsers \/ $link_google/ ;
21092081 $html =~ s/X1000/&rArr; <font color=#008000><b>all counts x 1000<\/b><\/font>.<br>/ ;
21102082
 2083+# test code, all counts from csv files are in thousands (from 1:1000 sampled page file) and will be scaled x 1000
 2084+# thus scale these test figures in reverse direction first
 2085+# $html .= &ShowCount (891234567890/1000) . "<br>" ;
 2086+# $html .= &ShowCount (91234567890/1000) . "<br>" ;
 2087+# $html .= &ShowCount (1234567890/1000) . "<br>" ;
 2088+# $html .= &ShowCount (234567890/1000) . "<br>" ;
 2089+# $html .= &ShowCount (34567890/1000) . "<br>" ;
 2090+# $html .= &ShowCount (4567890/1000) . "<br>" ;
 2091+# $html .= &ShowCount (567890/1000) . "<br>" ;
 2092+# $html .= &ShowCount (67890/1000) . "<br>" ;
 2093+# $html .= &ShowCount (7890/1000) . "<br>" ;
 2094+# $html .= &ShowCount (890/1000) . "<br>" ;
 2095+# $html .= &ShowCount (90/1000) . "<br>" ;
 2096+# $html .= &ShowCount (1/1000) . "<br>" ;
 2097+# $html .= &ShowCount (0) . "<br>" ;
 2098+
21112099 $html .= "<table border=1>\n" ;
21122100 $html .= "<tr><td class=l colspan=99 wrap>The following overview of page requests per client (~browser) application is based on the <a href='http://en.wikipedia.org/wiki/User_agent'>user agent</a> information that accompanies most server requests.<br>" .
21132101 "Please note that agent information does not follow strict guidelines and some programs may provide wrong information on purpose.<br>" .
@@ -2462,8 +2450,7 @@
24632451 $perc = sprintf ("%.1f",100*$total_clients_non_mobile / ($total_clients_mobile + $total_clients_non_mobile + $total_clients_wiki_mobile)) ;
24642452
24652453 $total_html_only = &FormatCount ($total_clients_non_mobile_html_only) ;
2466 - $perc_html_only = sprintf ("%.1f",100*$total_clients_non_mobile_html_only / ($total_clients_mobile_html_only + $total_clients_non_mobile_html_only +
2467 -$total_clients_wiki_mobile_html_only)) ;
 2454+ $perc_html_only = sprintf ("%.1f",100*$total_clients_non_mobile_html_only / ($total_clients_mobile_html_only + $total_clients_non_mobile_html_only + $total_clients_wiki_mobile_html_only)) ;
24682455
24692456 $html .= "<tr><th class=l>Total</th>" . &ShowCountBold ($total) . "<th class=r>$perc\%</th>" . &ShowCountBold ($total_html_only) . "<th class=r>$perc_html_only\%</th></tr>\n" ;
24702457
@@ -2488,8 +2475,7 @@
24892476 $perc = sprintf ("%.1f",100*$total_clients_mobile / ($total_clients_mobile + $total_clients_non_mobile + $total_clients_wiki_mobile)) ;
24902477
24912478 $total_html_only = &FormatCount ($total_clients_mobile_html_only) ;
2492 - $perc_html_only = sprintf ("%.1f",100*$total_clients_mobile_html_only / ($total_clients_mobile_html_only + $total_clients_non_mobile_html_only +
2493 -$total_clients_wiki_mobile_html_only)) ;
 2479+ $perc_html_only = sprintf ("%.1f",100*$total_clients_mobile_html_only / ($total_clients_mobile_html_only + $total_clients_non_mobile_html_only + $total_clients_wiki_mobile_html_only)) ;
24942480
24952481 $html .= "<tr><th class=l>Total</th>" . &ShowCountBold ($total) . "<th class=r>$perc\%</th>" . &ShowCountBold ($total_html_only) . "<th class=r>$perc_html_only\%</th></tr>\n" ;
24962482
@@ -3875,7 +3861,7 @@
38763862 {
38773863 ($script2,$action) = split (',', $key) ;
38783864 if (($script eq $script2) && ($actions {$key} < $scripts_php {$script}))
3879 - { $html .= "<tr><td class=l>&nbsp;&nbsp;&nbsp;<small>$action</small></td>" . &ShowCountSmall (&FormatCount ($actions {$key})) . "</td></tr>\n" ; }
 3865+ { $html .= "<tr><td class=l>&nbsp;&nbsp;&nbsp;- $action</td>" . &ShowCount (&FormatCount ($actions {$key})) . "</tr>\n" ; }
38803866 }
38813867 }
38823868 $total_php = &FormatCount ($total_php) ;
@@ -3921,7 +3907,7 @@
39223908 {
39233909 ($script2,$action) = split (',', $key) ;
39243910 if (($script eq $script2) && ($actions {$key} < $scripts_php {$script}))
3925 - { $html .= "<tr><td class=l>&nbsp;&nbsp;&nbsp;<small>$action</small></td>" . &ShowCountSmall (&FormatCount ($actions {$key})) . "</tr>\n" ; }
 3911+ { $html .= "<tr><td class=l>&nbsp;&nbsp;&nbsp;- $action</td>" . &ShowCount (&FormatCount ($actions {$key})) . "</tr>\n" ; }
39263912 }
39273913 }
39283914 $html .= "<tr><th class=l>total php</th>" . &ShowCountBold ($total_php) . "</tr>\n" ;
@@ -5800,28 +5786,30 @@
58015787 return ($count) ;
58025788 }
58035789
5804 -sub ShowCount
 5790+sub ShowCount # qqq2
58055791 {
5806 - my ($num, $color) = @_ ;
5807 - if (! defined $color)
5808 - { return ("<td class=r>$num</td>") ; }
5809 - else
5810 - { return ("<td class=r><font color=$color>$num</font></td>") ; }
5811 -}
 5792+ my ($num) = @_ ;
 5793+ $num =~ s/,//g ;
58125794
5813 -sub ShowCountSmall
5814 -{
5815 - my ($num, $color) = @_ ;
5816 - &ShowCount ("<small>" . &ShowCount ($num,$color) . "</small>") ;
 5795+ if ($num eq '&nbsp;') # to do: remove &nbsp;'s from perl code, send 0 instead, formatting in javascript
 5796+ { $num = 0 ; }
 5797+
 5798+ if ($num =~ /^[\d\.]+$/) # numeric string
 5799+ { $num *= 1000 ; }
 5800+
 5801+ if ($num =~ /\D/) # contains non-digit ? enclose in double quotes
 5802+ { $num ="\"$num\"" ; }
 5803+
 5804+ $num = "<script>showCount($num);</script>" ;
 5805+ return ("<td class=r>$num</td>") ;
58175806 }
58185807
58195808 sub ShowCountBold
58205809 {
5821 - my ($num, $color) = @_ ;
5822 - if (! defined $color)
5823 - { return ("<th class=r>$num</th>") ; }
5824 - else
5825 - { return ("<th class=r><font color=$color>$num</font></th>") ; }
 5810+ my ($num) = @_ ;
 5811+ $num = &ShowCount ($num) ;
 5812+ $num =~ s/td/th/g ;
 5813+ return ($num) ;
58265814 }
58275815
58285816 sub SortMime
@@ -6536,6 +6524,203 @@
65376525 close HTML_CSV ;
65386526 }
65396527
 6528+sub HtmlHead
 6529+{
 6530+# substitute this with this
 6531+ $regexp_from1 = '/(\d)(\d\d\d)$/' ; $regexp_to1 = '"$1,$2"' ;
 6532+ $regexp_from2 = '/(\d)(\d\d\d)(\d\d\d)$/' ; $regexp_to2 = '"$1,$2,$3"' ;
 6533+ $regexp_from3 = '/(\d)(\d\d\d)(\d\d\d)(\d\d\d)$/' ; $regexp_to3 = '"$1,$2,$3,$4"' ;
 6534+ $regexp_from4 = '/(\d)(\d\d\d)\&/' ; $regexp_to4 = '"$1,$2\&"' ;
 6535+
 6536+ my $html = <<__HTML_HEAD__ ;
 6537+
 6538+<!DOCTYPE FILE_HTML PUBLIC '-//W3C//DTD FILE_HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>
 6539+<html lang='en'>
 6540+
 6541+<head>
 6542+
 6543+<title>TITLE</title>
 6544+
 6545+<meta http-equiv='Content-type' content='text/html; charset=iso-8859-1'>
 6546+<meta name='robots' content='index,follow'>
 6547+
 6548+<style type='text/css'>
 6549+<!--
 6550+body {font-family:arial,sans-serif; font-size:12px }
 6551+h2 {margin:0px 0px 3px 0px; font-size:18px}
 6552+table {font-size:12px ;}
 6553+td {white-space:wrap; text-align:right; padding-left:2px; padding-right:2px; padding-top:1px;padding-bottom:0px ; font-size:12px ; vertical-align:middle}
 6554+th {white-space:nowrap; text-align:right; padding-left:2px; padding-right:2px; padding-top:1px;padding-bottom:0px ; font-size:12px ; vertical-align:top ; font-width:bold}
 6555+th.small {white-space:wrap; text-align:right; padding-left:2px; padding-right:2px; padding-top:1px;padding-bottom:0px ; font-size:11px ; vertical-align:top ; font-width:bold}
 6556+td.hl {text-align:left;vertical-align:top;}
 6557+td.hr {text-align:right;vertical-align:top;}
 6558+td.hc {text-align:center;vertical-align:top;}
 6559+td.r {text-align:right; border: inset 1px #FFFFFF}
 6560+td.c {text-align:center; border: inset 1px #FFFFFF}
 6561+td.l {text-align:left; border: inset 1px #FFFFFF}
 6562+th.c {text-align:center; border: inset 1px #FFFFFF}
 6563+th.l {text-align:left; border: inset 1px #FFFFFF}
 6564+th.r {text-align:right; border: inset 1px #FFFFFF}
 6565+th.lh3 {text-align:left; border: inset 1px #FFFFFF ; font-size:14px}
 6566+a:link { color:blue;text-decoration:none;}
 6567+a:visited {color:#0000FF;text-decoration:none;}
 6568+a:active {color:#0000FF;text-decoration:none;}
 6569+a:hover {color:#FF00FF;text-decoration:underline}
 6570+-->
 6571+</style>
 6572+
 6573+<script>
 6574+
 6575+var calls = 0 ;
 6576+
 6577+var show_count_short = (getCookie ('show_count_short') == 'true') || (getCookie ('show_count_short') == '');
 6578+var show_count_mode = (getCookie ('select_period') || 0) ;
 6579+var show_count_monthly_normalized = (show_count_mode == 0) ;
 6580+var show_count_monthly_raw = (show_count_mode == 1) ;
 6581+var show_count_daily = (show_count_mode == 2) ;
 6582+
 6583+var char_million = 'M' ;
 6584+var char_thousand = 'k' ;
 6585+var nbsp = '&nbsp;' ;
 6586+var checked = false;
 6587+var element ;
 6588+var index ;
 6589+
 6590+//qqq1
 6591+
 6592+window.onload =
 6593+ function()
 6594+ {
 6595+ // alert ('window.onload') ;
 6596+ // alert (document.cookie) ;
 6597+ checked = getCookie ('show_count_short') ;
 6598+ element = document.getElementById ('form_show_count_short');
 6599+
 6600+ if (checked == 'false')
 6601+ { element.checked = false ; show_count_short = false ; }
 6602+ else
 6603+ { element.checked = true ; show_count_short = true ; }
 6604+
 6605+ index = getCookie ('select_period') || 0 ;
 6606+ element = document.getElementById ('form_select_period');
 6607+ element.selectedIndex = parseInt(index);
 6608+ }
 6609+
 6610+function setCookie (name, value, expires, path, domain, secure)
 6611+{
 6612+ var curCookie = name + "=" + escape(value) + ((expires) ? "; expires=" + expires.toGMTString() : "") + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + ((secure) ? "; secure" : "");
 6613+ document.cookie = curCookie;
 6614+}
 6615+
 6616+function getCookie (name)
 6617+{
 6618+ var prefix = name + "=" ;
 6619+ var cookieStartIndex = document.cookie.indexOf (prefix);
 6620+ if (cookieStartIndex == -1)
 6621+ { return "" ; }
 6622+ var cookieEndIndex = document.cookie.indexOf (";", cookieStartIndex + prefix.length);
 6623+ if (cookieEndIndex == -1)
 6624+ { cookieEndIndex = document.cookie.length ; }
 6625+ result = document.cookie.substring (cookieStartIndex + prefix.length, cookieEndIndex);
 6626+ return unescape (result) ;
 6627+}
 6628+
 6629+
 6630+function refreshPage ()
 6631+{
 6632+ // alert ('refreshPage') ;
 6633+ var element = document.getElementById ('form_select_period');
 6634+ setCookie ('select_period', element.selectedIndex) ;
 6635+
 6636+ var element = document.getElementById ('form_show_count_short');
 6637+ if (element.checked)
 6638+ { setCookie ('show_count_short', 'true') ; }
 6639+ else
 6640+ { setCookie ('show_count_short', 'false') ; }
 6641+
 6642+ // alert (document.cookie) ;
 6643+ window.location.reload();
 6644+}
 6645+
 6646+function showCount (count)
 6647+{
 6648+ // if (++ calls == 1)
 6649+ // { alert ('showCount() show_count_short '+show_count_short) ; }
 6650+
 6651+ if (count == 0)
 6652+ { count = '-' ; }
 6653+
 6654+ else if (show_count_daily)
 6655+ { ; }
 6656+ else if (show_count_monthly_normalized)
 6657+ { count *= 30 ; }
 6658+ else if (show_count_monthly_raw)
 6659+ { count *= $days_in_month ; }
 6660+
 6661+ if (show_count_short)
 6662+ {
 6663+ if (count >= 100000000)
 6664+ { count = Math.round (count/1000000) + nbsp + char_million ; }
 6665+ else if (count >= 1000000)
 6666+ { count = (Math.round (count/100000) / 10) + nbsp + char_million ; }
 6667+ else if (count >= 10000)
 6668+ { count = Math.round (count/1000) + nbsp + char_thousand ; }
 6669+ else if (count >= 1000)
 6670+ { count = (Math.round (count/100) / 10) + nbsp + char_thousand ; }
 6671+ count += '' ; // make string
 6672+ count = count.replace ($regexp_from4,$regexp_to4) ;
 6673+ }
 6674+ else
 6675+ {
 6676+ // add 1000 separators
 6677+ count += '' ; // make string
 6678+ count = count.replace ($regexp_from3,$regexp_to3) ;
 6679+ count = count.replace ($regexp_from2,$regexp_to2) ;
 6680+ count = count.replace ($regexp_from1,$regexp_to1) ;
 6681+ }
 6682+
 6683+ document.write (count) ;
 6684+}
 6685+
 6686+</script>
 6687+
 6688+__HTML_HEAD__
 6689+ return ($html) ;
 6690+}
 6691+
 6692+sub HtmlForm
 6693+{
 6694+ my $html = <<__HTML_FORM__ ;
 6695+
 6696+<table width=100%>
 6697+<tr>
 6698+<td class=hl>
 6699+ <h2>HEADER</h2>
 6700+ <b>DATE</b>
 6701+</td>
 6702+<td class=hr>
 6703+<form name = 'form'>
 6704+ <select name='period' id='form_select_period' size='1' onchange='refreshPage()'>
 6705+ <option value='1'>Monthly requests, normalized</option>
 6706+ <option value='2'>Monthly requests, raw</option>
 6707+ <option value='3'>Average daily requests</option>
 6708+ </select>
 6709+
 6710+ <input type='checkbox' id='form_show_count_short' onchange='refreshPage()' /><strike>000</strike> &rArr; k
 6711+
 6712+ <input type='button' value=' Archive ' onclick='window.location=\"http://stats.wikimedia.org/archive/squid_reports\"'>
 6713+ <input type='button' value=' Wikimedia Statistics ' onclick='window.location=\"http://stats.wikimedia.org\"'>
 6714+</form>
 6715+ </td>
 6716+ </tr>
 6717+</table>
 6718+
 6719+__HTML_FORM__
 6720+
 6721+return ($html) ;
 6722+
 6723+}
 6724+
65406725 sub HtmlSortTable
65416726 {
65426727 my $html = <<__HTML_SORT_TABLE__ ;
@@ -6677,6 +6862,23 @@
66786863 return ($html) ;
66796864 }
66806865
 6866+sub DaysInMonth
 6867+{
 6868+ my $year = shift ;
 6869+ my $month = shift ;
 6870+
 6871+ my $month2 = $month+1 ;
 6872+ my $year2 = $year ;
 6873+ if ($month2 > 12)
 6874+ { $month2 = 1 ; $year2++ }
 6875+
 6876+ my $timegm1 = timegm (0,0,0,1,$month-1,$year-1900) ;
 6877+ my $timegm2 = timegm (0,0,0,1,$month2-1,$year2-1900) ;
 6878+ $days = ($timegm2-$timegm1) / (24*60*60) ;
 6879+
 6880+ return ($days) ;
 6881+}
 6882+
66816883 sub hsv_to_rgb {
66826884
66836885 my $h = shift;

Status & tagging log