summaryrefslogtreecommitdiffstats
path: root/mirrors
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2010-09-12 10:14:34 -0500
committerDan McGee <dan@archlinux.org>2010-09-21 09:10:33 -0500
commit40ac4818aa7812a5399a0d4c176137984d5cfd30 (patch)
treec02e2a6865cf3067703c9b27150bc306367fc546 /mirrors
parent3d8bc07622561028dbca9c709470accf79c95bd6 (diff)
downloadarchweb-40ac4818aa7812a5399a0d4c176137984d5cfd30.tar.gz
archweb-40ac4818aa7812a5399a0d4c176137984d5cfd30.zip
Add mirror status view
Signed-off-by: Dan McGee <dan@archlinux.org>
Diffstat (limited to 'mirrors')
-rw-r--r--mirrors/templatetags/__init__.py0
-rw-r--r--mirrors/templatetags/mirror_status.py15
-rw-r--r--mirrors/views.py50
3 files changed, 65 insertions, 0 deletions
diff --git a/mirrors/templatetags/__init__.py b/mirrors/templatetags/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/mirrors/templatetags/__init__.py
diff --git a/mirrors/templatetags/mirror_status.py b/mirrors/templatetags/mirror_status.py
new file mode 100644
index 00000000..09c5b331
--- /dev/null
+++ b/mirrors/templatetags/mirror_status.py
@@ -0,0 +1,15 @@
+from django import template
+
+register = template.Library()
+
+@register.filter
+def duration(value):
+ if not value:
+ return u'\u221e'
+ # 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)
+
+# vim: set ts=4 sw=4 et:
diff --git a/mirrors/views.py b/mirrors/views.py
index b4c2c2c7..a31c1371 100644
--- a/mirrors/views.py
+++ b/mirrors/views.py
@@ -1,9 +1,14 @@
from django import forms
+from django.db.models import Avg, Count, Max, Min, StdDev
+from django.db.models import Q
from django.views.decorators.csrf import csrf_exempt
from django.views.generic.simple import direct_to_template
from main.utils import make_choice
from .models import Mirror, MirrorUrl, MirrorProtocol
+from .models import MirrorLog
+
+import datetime
class MirrorlistForm(forms.Form):
country = forms.MultipleChoiceField(required=False)
@@ -49,4 +54,49 @@ def find_mirrors(request, countries=None, protocols=None):
},
mimetype='text/plain')
+def status(request):
+ cutoff_time = datetime.datetime.utcnow() - datetime.timedelta(hours=24)
+ bad_timedelta = datetime.timedelta(days=3)
+
+ protocols = MirrorProtocol.objects.exclude(protocol__iexact='rsync')
+ # I swear, this actually has decent performance...
+ urls = MirrorUrl.objects.select_related(
+ 'mirror', 'protocol').filter(
+ mirror__active=True, mirror__public=True,
+ protocol__in=protocols).filter(
+ logs__check_time__gte=cutoff_time).annotate(
+ check_count=Count('logs'), last_sync=Max('logs__last_sync'),
+ last_check=Max('logs__check_time'),
+ duration_avg=Avg('logs__duration'), duration_min=Min('logs__duration'),
+ duration_max=Max('logs__duration'), duration_stddev=StdDev('logs__duration')
+ ).order_by('mirror__country', 'url')
+ # errors during check process go in another table
+ error_logs = MirrorLog.objects.filter(
+ is_success=False, check_time__gte=cutoff_time).values(
+ 'url__url', 'url__protocol__protocol', 'url__mirror__country',
+ 'error').annotate(Count('error'), Max('check_time'))
+
+ good_urls = []
+ bad_urls = []
+ for url in urls:
+ if url.last_check and url.last_sync:
+ d = url.last_check - url.last_sync
+ url.delay = d
+ url.score = d.days * 24 + d.seconds / 3600 + url.duration_avg + url.duration_stddev
+ else:
+ url.delay = None
+ url.score = None
+ # split them into good and bad lists based on delay
+ if not url.delay or url.delay > bad_timedelta:
+ bad_urls.append(url)
+ else:
+ good_urls.append(url)
+
+ context = {
+ 'good_urls': good_urls,
+ 'bad_urls': bad_urls,
+ 'error_logs': error_logs,
+ }
+ return direct_to_template(request, 'mirrors/status.html', context)
+
# vim: set ts=4 sw=4 et: