new: Add historical graph in ASN view
parent
fbc5a6a1bb
commit
2d9667e25b
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
});
|
|
@ -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>
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
Loading…
Reference in New Issue