From 1480a47acb359aac8f29cb61e89a44da69ef1e4b Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 31 Mar 2019 13:43:57 +0200 Subject: [PATCH] Add new historical data view - Re-implement home page using a class view and add settings-based context --- codespeed/settings.py | 8 +++- codespeed/urls.py | 3 +- codespeed/views.py | 93 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 98 insertions(+), 6 deletions(-) diff --git a/codespeed/settings.py b/codespeed/settings.py index 4e3b5d5..42a3867 100644 --- a/codespeed/settings.py +++ b/codespeed/settings.py @@ -8,7 +8,7 @@ DEF_BASELINE = None # Which executable + revision should be default as a baseline # Given as the name of the executable and commitid of the revision - # Example: defaultbaseline = {'executable': 'myexe', 'revision': '21'} + # Example: DEF_BASELINE = {'executable': 'baseExe', 'revision': '444'} TREND = 10 # Default value for the depth of the trend # Used by reports for the latest runs and changes view @@ -20,10 +20,14 @@ # over a number of revisions is significant TREND_THRESHOLD = 5.0 +## Home view options ## +SHOW_REPORTS = True # Show report tables +SHOW_HISTORICAL = False # Show historical graphs + ## Changes view options ## DEF_EXECUTABLE = None # Executable that should be chosen as default in the changes view # Given as the name of the executable. - # Example: defaultexecutable = "myexe" + # Example: DEF_EXECUTABLE = "myexe O3 64bits" SHOW_AUTHOR_EMAIL_ADDRESS = True # Whether to show the authors email address in the # changes log diff --git a/codespeed/urls.py b/codespeed/urls.py index 4fe7705..af61e5e 100644 --- a/codespeed/urls.py +++ b/codespeed/urls.py @@ -6,7 +6,7 @@ from codespeed.feeds import LatestEntries, LatestSignificantEntries urlpatterns = [ - url(r'^$', TemplateView.as_view(template_name='home.html'), name='home'), + url(r'^$', views.HomeView.as_view(), name='home'), url(r'^about/$', TemplateView.as_view(template_name='about.html'), name='about'), # RSS for reports @@ -16,6 +16,7 @@ ] urlpatterns += [ + url(r'^historical/json/$', views.gethistoricaldata, name='gethistoricaldata'), url(r'^reports/$', views.reports, name='reports'), url(r'^changes/$', views.changes, name='changes'), url(r'^changes/table/$', views.getchangestable, name='getchangestable'), diff --git a/codespeed/views.py b/codespeed/views.py index abf868f..b498bdb 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -3,8 +3,8 @@ import json import logging -import django +import django from django.conf import settings from django.urls import reverse from django.core.exceptions import ValidationError, ObjectDoesNotExist @@ -14,6 +14,7 @@ from django.shortcuts import get_object_or_404, render_to_response from django.views.decorators.http import require_GET, require_POST from django.views.decorators.csrf import csrf_exempt +from django.views.generic.base import TemplateView from .auth import basic_auth_required from .models import (Environment, Report, Project, Revision, Result, @@ -61,6 +62,92 @@ def no_data_found(request): }) +class HomeView(TemplateView): + template_name = "home.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['show_reports'] = settings.SHOW_REPORTS + context['show_historical'] = settings.SHOW_HISTORICAL + historical_settings = ['SHOW_HISTORICAL', 'DEF_BASELINE', 'DEF_EXECUTABLE'] + if not all(getattr(settings, var) for var in historical_settings): + context['show_historical'] = False + return context + + baseline_exe = Executable.objects.get( + name=settings.DEF_BASELINE['executable']) + context['baseline'] = baseline_exe + default_exe = Executable.objects.get(name=settings.DEF_EXECUTABLE) + context['default_exe'] = default_exe + return context + + +@require_GET +def gethistoricaldata(request): + data = {'results': {}, 'benchmarks': []} + env = Environment.objects.all() + if settings.DEF_ENVIRONMENT: + env = env.get(name=settings.DEF_ENVIRONMENT) + else: + env = env.first() + + # Fetch Baseline data + baseline_exe = Executable.objects.get( + name=settings.DEF_BASELINE['executable']) + baseline_lastrev = Revision.objects.filter( + branch__project=baseline_exe.project).order_by('-date')[0] + data['baseline'] = '{} {}'.format( + settings.DEF_BASELINE['executable'], baseline_lastrev.tag) + baseline_results = Result.objects.filter( + executable=baseline_exe, revision=baseline_lastrev, environment=env) + + default_exe = Executable.objects.get(name=settings.DEF_EXECUTABLE) + default_branch = Branch.objects.get( + name=default_exe.project.default_branch, + project=default_exe.project) + + # Fetch tagged revisions for default executable + default_taggedrevs = Revision.objects.filter( + branch=default_branch + ).exclude(tag="").order_by('date') + data['tagged_revs'] = [rev.tag for rev in default_taggedrevs] + default_results = {} + for rev in default_taggedrevs: + default_results[rev.tag] = Result.objects.filter( + executable=default_exe, revision=rev, environment=env) + + # Fetch data for latest results + revs = Revision.objects.filter( + branch=default_branch).order_by('-date')[:5] + default_lastrev = None + for i in range(4): + default_lastrev = revs[i] + if default_lastrev.results.filter(executable=default_exe): + break + default_lastrev = None + if default_lastrev is None: + return HttpResponse(json.dumps(data)) + default_results['latest'] = Result.objects.filter( + executable=default_exe, revision=default_lastrev, environment=env) + + # Collect data + benchmarks = [] + for res in baseline_results: + if res == 0: + continue + benchmarks.append(res.benchmark.name) + data['results'][res.benchmark.name] = {data['baseline']: res.value} + for rev_name in default_results: + val = 0 + for default_res in default_results[rev_name]: + if default_res.benchmark.name == res.benchmark.name: + val = default_res.value + data['results'][res.benchmark.name][rev_name] = val + benchmarks.sort() + data['benchmarks'] = benchmarks + return HttpResponse(json.dumps(data)) + + @require_GET def getcomparisondata(request): executables, exekeys = getcomparisonexes() @@ -75,8 +162,8 @@ def getcomparisondata(request): for env in environments: compdata[exe['key']][env.id] = {} - # Load all results for this env/executable/revision in a dict - # for fast lookup + # Load all results for this env/executable/revision in a + # dict for fast lookup results = dict(Result.objects.filter( environment=env, executable=exe['executable'],