From 2d9667e25bafbace513902f514948df34ea986da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 31 May 2018 15:48:11 +0200 Subject: [PATCH] new: Add historical graph in ASN view --- bgpranking/querying.py | 13 ++++++-- website/3drparty.sh | 3 +- website/web/__init__.py | 17 +++++++--- website/web/static/linegraph.css | 16 ++++++++++ website/web/static/linegraph.js | 55 ++++++++++++++++++++++++++++++++ website/web/templates/asn.html | 11 +++++++ website/web/templates/main.html | 1 + 7 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 website/web/static/linegraph.css create mode 100644 website/web/static/linegraph.js diff --git a/bgpranking/querying.py b/bgpranking/querying.py index ad5f6ec..e5aa163 100644 --- a/bgpranking/querying.py +++ b/bgpranking/querying.py @@ -3,6 +3,7 @@ from typing import TypeVar import datetime +from datetime import timedelta from dateutil.parser import parse import logging @@ -55,7 +56,7 @@ class Querying(): key = f'{d}|{asn}|{ipversion}' return self.ranking.zrevrange(key, start=0, end=-1, withscores=True) - def asn_rank(self, asn: int, date: Dates= datetime.date.today(), source: str='', ipversion: str='v4'): + def asn_rank(self, asn: int, date: Dates=datetime.date.today(), source: str='', ipversion: str='v4'): '''Get the rank of a single ASN, weighted by source.''' d = self.__normalize_date(date) if source: @@ -64,7 +65,7 @@ class Querying(): key = f'{d}|asns|{ipversion}' return self.ranking.zscore(key, asn) - def get_sources(self, date: Dates= datetime.date.today()): + def get_sources(self, date: Dates=datetime.date.today()): '''Get the sources availables for a specific day (default: today).''' d = self.__normalize_date(date) key = f'{d}|sources' @@ -75,3 +76,11 @@ class Querying(): if all_descriptions or not descriptions: return descriptions return descriptions[sorted(descriptions.keys(), reverse=True)[0]] + + def get_asn_history(self, asn: int, period: int=200, source: str='', ipversion: str='v4'): + to_return = [] + today = datetime.date.today() + for i in range(period): + date = today - timedelta(days=i) + to_return.insert(0, (date.isoformat(), self.asn_rank(asn, date, source, ipversion))) + return to_return diff --git a/website/3drparty.sh b/website/3drparty.sh index 9051bc1..2a9085e 100644 --- a/website/3drparty.sh +++ b/website/3drparty.sh @@ -5,5 +5,4 @@ set -x mkdir -p web/static/ -wget https://code.jquery.com/ui/1.12.1/jquery-ui.js -O web/static/jquery-ui.js -wget https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css -O web/static/jquery-ui.css +wget https://d3js.org/d3.v5.js -O web/static/d3.v5.js diff --git a/website/web/__init__.py b/website/web/__init__.py index 4f543fb..2b85b14 100644 --- a/website/web/__init__.py +++ b/website/web/__init__.py @@ -1,11 +1,12 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +import json + from flask import Flask, render_template, request, session from flask_bootstrap import Bootstrap from bgpranking.querying import Querying -from pathlib import Path from datetime import date, timedelta @@ -16,9 +17,6 @@ app.secret_key = '\xeb\xfd\x1b\xee\xed<\xa5~\xd5H\x85\x00\xa5r\xae\x80t5@\xa2&>\ Bootstrap(app) app.config['BOOTSTRAP_SERVE_LOCAL'] = True -jquery_js = Path('static', 'jquery-ui.js') -jquery_css = Path('static', 'jquery-ui.css') - def load_session(): if request.method == 'POST': @@ -48,7 +46,7 @@ def index(): q = Querying() sources = q.get_sources(date=session['date']) session.pop('asn', None) - ranks = q.asns_global_ranking(limit=-1, **session) + ranks = q.asns_global_ranking(limit=100, **session) descriptions = [q.get_asn_descriptions(int(asn)) for asn, rank in ranks] r = zip(ranks, descriptions) return render_template('index.html', ranks=r, sources=sources, **session) @@ -60,3 +58,12 @@ def asn_details(): q = Querying() ranks = q.asn_details(**session) return render_template('asn.html', ranks=ranks, **session) + + +@app.route('/asn_history', methods=['GET', 'POST']) +def asn_history(): + load_session() + print(session.keys()) + session.pop('date') + q = Querying() + return json.dumps(q.get_asn_history(**session)) diff --git a/website/web/static/linegraph.css b/website/web/static/linegraph.css new file mode 100644 index 0000000..6ea1b2b --- /dev/null +++ b/website/web/static/linegraph.css @@ -0,0 +1,16 @@ + +body { font: 12px Arial;} + +path { + stroke: steelblue; + stroke-width: 2; + fill: none; +} + +.axis path, +.axis line { + fill: none; + stroke: grey; + stroke-width: 1; + shape-rendering: crispEdges; +} diff --git a/website/web/static/linegraph.js b/website/web/static/linegraph.js new file mode 100644 index 0000000..77fe363 --- /dev/null +++ b/website/web/static/linegraph.js @@ -0,0 +1,55 @@ +// set the dimensions and margins of the graph +var margin = {top: 20, right: 20, bottom: 30, left: 50}, + width = 960 - margin.left - margin.right, + height = 500 - margin.top - margin.bottom; + +// parse the date / time +var parseTime = d3.timeParse("%Y-%m-%d"); + +// set the ranges +var x = d3.scaleTime().range([0, width]); +var y = d3.scaleLinear().range([height, 0]); + +// define the line +var valueline = d3.line() + .x(function(d) { return x(d[0]); }) + .y(function(d) { return y(d[1]); }); + +// append the svg obgect to the body of the page +// appends a 'group' element to 'svg' +// moves the 'group' element to the top left margin +var svg = d3.select("body").append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("transform", + "translate(" + margin.left + "," + margin.top + ")"); + +function draw(data) { + + var data = data; + + // Scale the range of the data + x.domain(d3.extent(data, function(d) { return d[0]; })); + y.domain([0, d3.max(data, function(d) { return d[1]; })]); + + // Add the valueline path. + svg.append("path") + .data([data]) + .attr("class", "line") + .attr("d", valueline); + // Add the X Axis + svg.append("g") + .attr("transform", "translate(0," + height + ")") + .call(d3.axisBottom(x)); + + // Add the Y Axis + svg.append("g") + .call(d3.axisLeft(y)); + } + +// Get the data +d3.json("/asn_history", {credentials: 'same-origin'}).then(function(data) { + // trigger render + draw(data); +}); diff --git a/website/web/templates/asn.html b/website/web/templates/asn.html index db84262..9aa9982 100644 --- a/website/web/templates/asn.html +++ b/website/web/templates/asn.html @@ -1,7 +1,18 @@ {% extends "main.html" %} +{% block head %} + {{ super() }} + +{% endblock %} + + {% block title %}Ranking - {{ asn }}{% endblock %} +{% block scripts %} + {{ super() }} + +{% endblock %} + {% block content %}

Ranking - {{asn}}



diff --git a/website/web/templates/main.html b/website/web/templates/main.html index a81793b..a6c603a 100644 --- a/website/web/templates/main.html +++ b/website/web/templates/main.html @@ -2,6 +2,7 @@ {% block scripts %} {{ super() }} + {% endblock %} {% block head %}