new: Add historical graph in ASN view

pull/12/head
Raphaël Vinot 2018-05-31 15:48:11 +02:00
parent fbc5a6a1bb
commit 2d9667e25b
7 changed files with 107 additions and 9 deletions

View File

@ -3,6 +3,7 @@
from typing import TypeVar from typing import TypeVar
import datetime import datetime
from datetime import timedelta
from dateutil.parser import parse from dateutil.parser import parse
import logging import logging
@ -55,7 +56,7 @@ class Querying():
key = f'{d}|{asn}|{ipversion}' key = f'{d}|{asn}|{ipversion}'
return self.ranking.zrevrange(key, start=0, end=-1, withscores=True) 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.''' '''Get the rank of a single ASN, weighted by source.'''
d = self.__normalize_date(date) d = self.__normalize_date(date)
if source: if source:
@ -64,7 +65,7 @@ class Querying():
key = f'{d}|asns|{ipversion}' key = f'{d}|asns|{ipversion}'
return self.ranking.zscore(key, asn) 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).''' '''Get the sources availables for a specific day (default: today).'''
d = self.__normalize_date(date) d = self.__normalize_date(date)
key = f'{d}|sources' key = f'{d}|sources'
@ -75,3 +76,11 @@ class Querying():
if all_descriptions or not descriptions: if all_descriptions or not descriptions:
return descriptions return descriptions
return descriptions[sorted(descriptions.keys(), reverse=True)[0]] 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

View File

@ -5,5 +5,4 @@ set -x
mkdir -p web/static/ mkdir -p web/static/
wget https://code.jquery.com/ui/1.12.1/jquery-ui.js -O web/static/jquery-ui.js wget https://d3js.org/d3.v5.js -O web/static/d3.v5.js
wget https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css -O web/static/jquery-ui.css

View File

@ -1,11 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import json
from flask import Flask, render_template, request, session from flask import Flask, render_template, request, session
from flask_bootstrap import Bootstrap from flask_bootstrap import Bootstrap
from bgpranking.querying import Querying from bgpranking.querying import Querying
from pathlib import Path
from datetime import date, timedelta 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) Bootstrap(app)
app.config['BOOTSTRAP_SERVE_LOCAL'] = True app.config['BOOTSTRAP_SERVE_LOCAL'] = True
jquery_js = Path('static', 'jquery-ui.js')
jquery_css = Path('static', 'jquery-ui.css')
def load_session(): def load_session():
if request.method == 'POST': if request.method == 'POST':
@ -48,7 +46,7 @@ def index():
q = Querying() q = Querying()
sources = q.get_sources(date=session['date']) sources = q.get_sources(date=session['date'])
session.pop('asn', None) 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] descriptions = [q.get_asn_descriptions(int(asn)) for asn, rank in ranks]
r = zip(ranks, descriptions) r = zip(ranks, descriptions)
return render_template('index.html', ranks=r, sources=sources, **session) return render_template('index.html', ranks=r, sources=sources, **session)
@ -60,3 +58,12 @@ def asn_details():
q = Querying() q = Querying()
ranks = q.asn_details(**session) ranks = q.asn_details(**session)
return render_template('asn.html', ranks=ranks, **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))

View File

@ -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;
}

View File

@ -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);
});

View File

@ -1,7 +1,18 @@
{% extends "main.html" %} {% extends "main.html" %}
{% block head %}
{{ super() }}
<link rel="stylesheet" href="{{ url_for('static', filename='linegraph.css') }}">
{% endblock %}
{% block title %}Ranking - {{ asn }}{% endblock %} {% block title %}Ranking - {{ asn }}{% endblock %}
{% block scripts %}
{{ super() }}
<script src='{{ url_for('static', filename='linegraph.js') }}'></script>
{% endblock %}
{% block content %} {% block content %}
<center> <center>
<h1>Ranking - {{asn}}</h1></br></br> <h1>Ranking - {{asn}}</h1></br></br>

View File

@ -2,6 +2,7 @@
{% block scripts %} {% block scripts %}
{{ super() }} {{ super() }}
<script src='{{ url_for('static', filename='d3.v5.js') }}'></script>
{% endblock %} {% endblock %}
{% block head %} {% block head %}