diff options
-rw-r--r-- | mirrors/templatetags/mirror_status.py | 25 | ||||
-rw-r--r-- | mirrors/utils.py | 29 | ||||
-rw-r--r-- | templates/mirrors/status.html | 55 | ||||
-rw-r--r-- | templates/mirrors/status_table.html | 6 |
4 files changed, 90 insertions, 25 deletions
diff --git a/mirrors/templatetags/mirror_status.py b/mirrors/templatetags/mirror_status.py index 09c5b331..0031d83b 100644 --- a/mirrors/templatetags/mirror_status.py +++ b/mirrors/templatetags/mirror_status.py @@ -1,15 +1,36 @@ +from datetime import timedelta from django import template +from django.template.defaultfilters import floatformat register = template.Library() @register.filter def duration(value): - if not value: - return u'\u221e' + if not value and type(value) != timedelta: + return u'' # does not take microseconds into account total_secs = value.seconds + value.days * 24 * 3600 mins, secs = divmod(total_secs, 60) hrs, mins = divmod(mins, 60) return '%d:%02d' % (hrs, mins) +@register.filter +def hours(value): + if not value and type(value) != timedelta: + return u'' + # does not take microseconds into account + total_secs = value.seconds + value.days * 24 * 3600 + mins, secs = divmod(total_secs, 60) + hrs, mins = divmod(mins, 60) + if hrs == 1: + return '%d hour' % hrs + return '%d hours' % hrs + +@register.filter +def percentage(value, arg=-1): + if not value and type(value) != float: + return u'' + new_val = value * 100.0 + return floatformat(new_val, arg) + '%' + # vim: set ts=4 sw=4 et: diff --git a/mirrors/utils.py b/mirrors/utils.py index cdb705b2..0463247a 100644 --- a/mirrors/utils.py +++ b/mirrors/utils.py @@ -16,7 +16,9 @@ def get_mirror_statuses(cutoff=default_cutoff): mirror__active=True, mirror__public=True, protocol__in=protocols, logs__check_time__gte=cutoff_time).annotate( - check_count=Count('logs'), last_sync=Max('logs__last_sync'), + check_count=Count('logs'), + success_count=Count('logs__duration'), + last_sync=Max('logs__last_sync'), last_check=Max('logs__check_time'), duration_avg=Avg('logs__duration'), duration_stddev=StdDev('logs__duration') @@ -32,17 +34,6 @@ def get_mirror_statuses(cutoff=default_cutoff): d = log.check_time - log.last_sync delays.setdefault(log.url_id, []).append(d) - for url in urls: - if url.id in delays: - url_delays = delays[url.id] - d = sum(url_delays, datetime.timedelta()) / len(url_delays) - url.delay = d - hours = d.days * 24.0 + d.seconds / 3600.0 - url.score = hours + url.duration_avg + url.duration_stddev - else: - url.delay = None - url.score = None - if urls: last_check = max([u.last_check for u in urls]) num_checks = max([u.check_count for u in urls]) @@ -55,7 +46,21 @@ def get_mirror_statuses(cutoff=default_cutoff): num_checks = 0 check_frequency = None + for url in urls: + url.completion_pct = float(url.success_count) / num_checks + if url.id in delays: + url_delays = delays[url.id] + d = sum(url_delays, datetime.timedelta()) / len(url_delays) + url.delay = d + hours = d.days * 24.0 + d.seconds / 3600.0 + url.score = hours + url.duration_avg + url.duration_stddev + else: + url.delay = None + url.score = None + url.completion = 0.0 + return { + 'cutoff': cutoff, 'last_check': last_check, 'num_checks': num_checks, 'check_frequency': check_frequency, diff --git a/templates/mirrors/status.html b/templates/mirrors/status.html index 8dbecc07..1111d047 100644 --- a/templates/mirrors/status.html +++ b/templates/mirrors/status.html @@ -8,7 +8,7 @@ <h2>Mirror Status</h2> <p>This page reports the status of all known, public, and active Arch Linux mirrors. All data on this page reflects the status of the mirrors within - the <em>last 24 hours</em>. All listed times are UTC. The check script runs + the <em>last {{ cutoff|hours }}</em>. All listed times are UTC. The check script runs on a regular basis and polls for the <tt>lastsync</tt> file in the root of our repository layout. This file is regularly updated on the central repository, so checking the value within allows one to see if the mirror @@ -21,6 +21,9 @@ <tt>lastsync</tt> file on the mirror. If this file could not be retrieved or contained data we didn't recognize, this column will show 'unknown'.</li> + <li><em>Completion %:</em> The number of mirror checks that have + successfully connected and disconnected from the given URL. If this is + below 100%, the mirror may be unreliable.</li> <li><em>μ Delay:</em> The calculated average mirroring delay; e.g. the mean value of <tt>last check − last sync</tt> for each check of this mirror URL. Due to the timing of mirror checks, any value under @@ -38,7 +41,7 @@ </ul> <p>The final table on this page is an error log, which shows any errors that occurred while contacting mirrors. This only shows errors that - occurred within the last 24 hours.</p> + occurred within the last {{ cutoff|hours }}.</p> <ul> <li><a href="#outofsync">Out of Sync Mirrors</a></li> <li><a href="#successful">Successfully Syncing Mirrors</a></li> @@ -46,7 +49,7 @@ </ul> <p>The last mirror check ran at {{ last_check|date:'Y-m-d H:i' }} UTC. - Checks have ran {{ num_checks }} times in the last 24 hours at an average + Checks have ran {{ num_checks }} times in the last {{ cutoff|hours }} at an average interval of {{ check_frequency|duration }} (hh:mm).</p> <a name="outofsync" id="outofsync"></a> @@ -75,7 +78,7 @@ <th>Country</th> <th>Error Message</th> <th>Last Occurred</th> - <th>Occurrences (last 24 hours)</th> + <th>Occurrences (last {{ cutoff|hours }})</th> </tr> </thead> <tbody> @@ -96,12 +99,46 @@ {% load cdn %}{% jquery %} <script type="text/javascript" src="/media/jquery.tablesorter.min.js"></script> <script type="text/javascript"> +$.tablesorter.addParser({ + /* sorts numeric, but put '', 'unknown', and '∞' last. */ + id: 'mostlydigit', + is: function(s,table) { + var special = ['', 'unknown', '∞']; + var c = table.config; + return ($.inArray(s, special) > -1) || $.tablesorter.isDigit(s,c); + }, + format: function(s) { + var special = ['', 'unknown', '∞']; + if($.inArray(s, special) > -1) return Number.MAX_VALUE; + return $.tablesorter.formatFloat(s); + }, + type: 'numeric' +}); +$.tablesorter.addParser({ + /* sorts duration; put '', 'unknown', and '∞' last. */ + id: 'duration', + is: function(s,table) { + var special = ['', 'unknown', '∞']; + return ($.inArray(s, special) > -1) || /^[0-9]+:[0-5][0-9]$/.test(s); + }, + format: function(s) { + console.log('duration: ' + s); + var special = ['', 'unknown', '∞']; + if($.inArray(s, special) > -1) return Number.MAX_VALUE; + matches = /^([0-9]+):([0-5][0-9])$/.exec(s); + console.log(s, matches[1] * 60 + matches[2]); + return matches[1] * 60 + matches[2]; + }, + type: 'numeric' +}); $(document).ready(function() { - $("#outofsync_mirrors").tablesorter( - {widgets: ['zebra'], sortList: [[3,1], [5,1]]}); - $("#successful_mirrors").tablesorter( - {widgets: ['zebra'], sortList: [[7,0]]}); - $("#errorlog_mirrors").tablesorter( + $("#outofsync_mirrors:has(tbody tr)").tablesorter( + {widgets: ['zebra'], sortList: [[3,1]], + headers: { 6: { sorter: 'mostlydigit' }, 7: { sorter: 'mostlydigit' }, 8: { sorter: 'mostlydigit' } } }); + $("#successful_mirrors:has(tbody tr)").tablesorter( + {widgets: ['zebra'], sortList: [[8,0]], + headers: { 6: { sorter: 'mostlydigit' }, 7: { sorter: 'mostlydigit' }, 8: { sorter: 'mostlydigit' } } }); + $("#errorlog_mirrors:has(tbody tr)").tablesorter( {widgets: ['zebra'], sortList: [[4,1], [5,1]]}); }); </script> diff --git a/templates/mirrors/status_table.html b/templates/mirrors/status_table.html index 75157765..240a5452 100644 --- a/templates/mirrors/status_table.html +++ b/templates/mirrors/status_table.html @@ -6,6 +6,7 @@ <th>Protocol</th> <th>Country</th> <th>Last Sync</th> + <th>Completion %</th> <th>μ Delay (hh:mm)</th> <th>μ Duration (secs)</th> <th>σ Duration (secs)</th> @@ -19,9 +20,10 @@ <td>{{ m_url.protocol }}</td> <td>{{ m_url.mirror.country }}</td> <td>{{ m_url.last_sync|date:'Y-m-d H:i'|default:'unknown' }}</td> + <td>{{ m_url.completion_pct|percentage:1 }}</td> <td>{{ m_url.delay|duration|default:'unknown' }}</td> - <td>{{ m_url.duration_avg|floatformat:2|default:'unknown' }}</td> - <td>{{ m_url.duration_stddev|floatformat:2|default:'unknown' }}</td> + <td>{{ m_url.duration_avg|floatformat:2 }}</td> + <td>{{ m_url.duration_stddev|floatformat:2 }}</td> <td>{{ m_url.score|floatformat:1|default:'∞' }}</td> </tr> {% endfor %} |