statistics.html: Show aggregated traffic for hoods and total

This patch aims at showing the client-caused traffic. We use
bat0 for this, at this seems to be the easiest way which does not
require router-specific ifs etc.

This patch distinguishes between routers and gateways:

- For routers, we just use the bat0 data
- For gateways, we aggregate eth0.1, eth1.1, w2ap and w5ap

This requires changes to the MySQL database!

Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
This commit is contained in:
Adrian Schmutzler 2018-04-18 12:11:40 +02:00
parent b21b6c9201
commit aa99035e23
6 changed files with 100 additions and 21 deletions

View File

@ -15,7 +15,9 @@ mysql.execute("""
`online` smallint(6) NOT NULL,
`offline` smallint(6) NOT NULL,
`unknown` smallint(6) NOT NULL,
`orphaned` smallint(6) NOT NULL
`orphaned` smallint(6) NOT NULL,
`rx` int(10) UNSIGNED DEFAULT NULL,
`tx` int(10) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
""")
@ -50,7 +52,9 @@ mysql.execute("""
`online` smallint(6) NOT NULL,
`offline` smallint(6) NOT NULL,
`unknown` smallint(6) NOT NULL,
`orphaned` smallint(6) NOT NULL
`orphaned` smallint(6) NOT NULL,
`rx` int(10) UNSIGNED DEFAULT NULL,
`tx` int(10) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
""")

View File

@ -41,6 +41,36 @@ def router_status(mysql,selecthood=None):
tmp["sum"] = sum(tmp.values())
return tmp
def router_traffic(mysql,selecthood=None):
# rx and tx are exchanged for bat0, since we want to get client traffic, which is the mirror of bat0 traffic
if selecthood:
tmp = mysql.findone("""
SELECT SUM(rx) AS tx, SUM(tx) AS rx FROM router_netif
INNER JOIN router ON router_netif.router = router.id
WHERE hood = %s AND gateway = FALSE AND netif = 'bat0'
""",(selecthood,))
gw = mysql.findone("""
SELECT SUM(rx) AS rx, SUM(tx) AS tx FROM router_netif
INNER JOIN router ON router_netif.router = router.id
WHERE hood = %s AND gateway = TRUE AND netif IN ('eth0.1','eth1.1','w2ap','w5ap')
""",(selecthood,))
else:
tmp = mysql.findone("""
SELECT SUM(rx) AS tx, SUM(tx) AS rx FROM router_netif
INNER JOIN router ON router_netif.router = router.id
WHERE gateway = FALSE AND netif = 'bat0'
""",())
gw = mysql.findone("""
SELECT SUM(rx) AS rx, SUM(tx) AS tx FROM router_netif
INNER JOIN router ON router_netif.router = router.id
WHERE gateway = TRUE AND netif IN ('eth0.1','eth1.1','w2ap','w5ap')
""",())
if "rx" in gw and gw["rx"]:
tmp["rx"] += gw["rx"]
if "tx" in gw and gw["tx"]:
tmp["tx"] += gw["tx"]
return tmp
def total_clients_hood(mysql):
return mysql.fetchdict("""
SELECT hood, SUM(clients) AS clients
@ -61,6 +91,36 @@ def router_status_hood(mysql):
dict[d["hood"]][d["status"]] = d["count"]
return dict
def router_traffic_hood(mysql):
# rx and tx are exchanged for bat0, since we want to get client traffic, which is the mirror of bat0 traffic
dict = mysql.fetchdict("""
SELECT hood, SUM(rx) AS tx, SUM(tx) AS rx FROM router_netif
INNER JOIN router ON router_netif.router = router.id
WHERE gateway = FALSE AND netif = 'bat0'
GROUP BY hood
""",(),"hood")
gw = mysql.fetchall("""
SELECT hood, SUM(rx) AS rx, SUM(tx) AS tx FROM router_netif
INNER JOIN router ON router_netif.router = router.id
WHERE gateway = TRUE AND netif IN ('eth0.1','eth1.1','w2ap','w5ap')
GROUP BY hood
""")
allhoods = mysql.fetchall("""
SELECT hood
FROM router
GROUP BY hood
""")
for d in gw:
if not d["hood"] in dict:
dict[d["hood"]] = d
else:
dict[d["hood"]]["rx"] += d["rx"]
dict[d["hood"]]["tx"] += d["tx"]
for h in allhoods:
if not h["hood"] in dict:
dict[h["hood"]] = {"hood": h["hood"], "rx": 0, "tx": 0}
return dict
def total_clients_gw(mysql):
return mysql.fetchdict("""
SELECT router_gw.mac, SUM(clients) AS clients
@ -289,18 +349,21 @@ def record_global_stats(mysql):
threshold=(utcnow() - datetime.timedelta(days=CONFIG["global_stat_days"])).timestamp()
time = mysql.utctimestamp()
status = router_status(mysql)
traffic = router_traffic(mysql)
mysql.execute("""
INSERT INTO stats_global (time, clients, online, offline, unknown, orphaned)
VALUES (%s, %s, %s, %s, %s, %s)
INSERT INTO stats_global (time, clients, online, offline, unknown, orphaned, rx, tx)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
clients=VALUES(clients),
online=VALUES(online),
offline=VALUES(offline),
unknown=VALUES(unknown),
orphaned=VALUES(orphaned)
""",(time,total_clients(mysql),status.get("online",0),status.get("offline",0),status.get("unknown",0),status.get("orphaned",0),))
orphaned=VALUES(orphaned),
rx=VALUES(rx),
tx=VALUES(tx)
""",(time,total_clients(mysql),status.get("online",0),status.get("offline",0),status.get("unknown",0),status.get("orphaned",0),traffic["rx"],traffic["tx"],))
mysql.execute("""
DELETE FROM stats_global
WHERE time < %s
@ -313,24 +376,27 @@ def record_hood_stats(mysql):
time = mysql.utctimestamp()
status = router_status_hood(mysql)
clients = total_clients_hood(mysql)
traffic = router_traffic_hood(mysql)
hdata = []
for hood in clients.keys():
if not hood:
hood = "Default"
hdata.append((time,hood,clients[hood],status[hood].get("online",0),status[hood].get("offline",0),status[hood].get("unknown",0),status[hood].get("orphaned",0),))
hdata.append((time,hood,clients[hood],status[hood].get("online",0),status[hood].get("offline",0),status[hood].get("unknown",0),status[hood].get("orphaned",0),traffic[hood]["rx"],traffic[hood]["tx"],))
mysql.executemany("""
INSERT INTO stats_hood (time, hood, clients, online, offline, unknown, orphaned)
VALUES (%s, %s, %s, %s, %s, %s, %s)
INSERT INTO stats_hood (time, hood, clients, online, offline, unknown, orphaned, rx, tx)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
clients=VALUES(clients),
online=VALUES(online),
offline=VALUES(offline),
unknown=VALUES(unknown),
orphaned=VALUES(orphaned)
orphaned=VALUES(orphaned),
rx=VALUES(rx),
tx=VALUES(tx)
""",hdata)
mysql.execute("""
DELETE FROM stats_hood
WHERE time < %s

View File

@ -503,7 +503,7 @@ def helper_statistics(mysql,stats,selecthood,selectgw):
stats = mysql.utcawaretupleint(stats,"time")
numnew = len(hoods)-18
numnew = len(hoods)-27
if numnew < 1:
numnew = 1

View File

@ -66,12 +66,11 @@ function setup_plot_zoom(plot, pdata, num_data_points) {
// Per router statistics
function network_graph(netif) {
function network_graph(netif_stats, tx_label, rx_label) {
var netstat = $("#netstat");
var tx = [], rx = [];
var len, i;
for (len=netif_stats.length, i=0; i<len; i++) {
//if (netif_stats[i].netif != netif) { continue; }
try {
var tx_value = netif_stats[i].tx;
var rx_value = netif_stats[i].rx;
@ -86,8 +85,8 @@ function network_graph(netif) {
}
}
var pdata = [
{"label": "tx", "data": tx, "color": "#CB4B4B"},
{"label": "rx", "data": rx, "color": "#8CACC6"}
{"label": tx_label, "data": tx, "color": "#CB4B4B"},
{"label": rx_label, "data": rx, "color": "#8CACC6"}
]
var plot = $.plot(netstat, pdata, {
xaxis: {mode: "time", timezone: "browser"},

View File

@ -468,8 +468,7 @@
function load_netif_stats(netif) {
var starttimenetif = performance.now();
ajax_get_request(url_load_netif_stats + "?netif=" + netif, function(netifstats) {
netif_stats = netifstats;
network_graph(netif);
network_graph(netifstats,"tx","rx");
console.debug("Loaded netif stats for "+netif+" in "+((performance.now() - starttimenetif)/1000).toFixed(3)+" seconds.");
});
}

View File

@ -113,6 +113,14 @@
<div id="globclientstat" class="graph"></div>
</div>
</div>
{%- if not selectgw %}
<div class="panel panel-default">
<div class="panel-heading">Traffic{%- if selecthood %} @ {{ selecthood }}{%- endif -%}</div>
<div class="panel-body">
<div id="netstat" class="graph"></div>
</div>
</div>
{%- endif -%}
<div class="panel panel-default">
<div class="panel-heading">Newest Routers{%- if selecthood %} @ {{ selecthood }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }}{%- endif -%}</div>
<div class="panel-body" style="padding-bottom:34px">
@ -233,6 +241,9 @@
global_router_firmwares_graph();
global_router_models_graph("globroutermodelsstat","count");
global_router_models_graph("globroutermodelsperclient","clients");
{%- if not selectgw %}
network_graph(global_stats,"sent to clients","received from clients");
{%- endif -%}
$("#hoodlist").DataTable({
"order": [],