diff --git a/aprsd/flask.py b/aprsd/flask.py index b4c15ae..f148134 100644 --- a/aprsd/flask.py +++ b/aprsd/flask.py @@ -121,6 +121,13 @@ class APRSDFlask(flask_classful.FlaskView): } stats_dict["aprsd"]["watch_list"] = new_list + packet_list = packets.PacketList() + rx = packet_list.total_received() + tx = packet_list.total_sent() + stats_dict["packets"] = { + "sent": tx, + "received": rx, + } result = { "time": now.strftime(time_format), diff --git a/aprsd/main.py b/aprsd/main.py index 3c933eb..b24ab2e 100644 --- a/aprsd/main.py +++ b/aprsd/main.py @@ -32,7 +32,18 @@ import time # local imports here import aprsd -from aprsd import client, email, flask, messaging, plugin, stats, threads, trace, utils +from aprsd import ( + client, + email, + flask, + messaging, + packets, + plugin, + stats, + threads, + trace, + utils, +) import aprslib from aprslib.exceptions import LoginError import click @@ -519,6 +530,7 @@ def server( "enabled", True, ): + packets.PacketList(config) notify_thread = threads.APRSDNotifyThread( msg_queues=msg_queues, config=config, diff --git a/aprsd/packets.py b/aprsd/packets.py index a2d19c6..fe7d542 100644 --- a/aprsd/packets.py +++ b/aprsd/packets.py @@ -16,9 +16,13 @@ class PacketList: """Class to track all of the packets rx'd and tx'd by aprsd.""" _instance = None + config = None packet_list = {} + total_recv = 0 + total_tx = 0 + def __new__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super().__new__(cls) @@ -26,6 +30,10 @@ class PacketList: cls._instance.lock = threading.Lock() return cls._instance + def __init__(self, config=None): + if config: + self.config = config + def __iter__(self): with self.lock: return iter(self.packet_list) @@ -33,12 +41,22 @@ class PacketList: def add(self, packet): with self.lock: packet["ts"] = time.time() + if "from" in packet and packet["from"] == self.config["aprs"]["login"]: + self.total_tx += 1 + else: + self.total_recv += 1 self.packet_list.append(packet) def get(self): with self.lock: return self.packet_list.get() + def total_received(self): + return self.total_recv + + def total_sent(self): + return self.total_tx + class WatchList: """Global watch list and info for callsigns.""" diff --git a/aprsd/web/static/css/index.css b/aprsd/web/static/css/index.css index 829b781..0fe80e1 100644 --- a/aprsd/web/static/css/index.css +++ b/aprsd/web/static/css/index.css @@ -38,7 +38,7 @@ footer { #center { height: 300px; } -#messageChart, #emailChart, #memChart { +#packetsChart, #messageChart, #emailChart, #memChart { border: 1px solid #ccc; background: #ddd; } diff --git a/aprsd/web/static/js/charts.js b/aprsd/web/static/js/charts.js index 8490e7d..9b42ffa 100644 --- a/aprsd/web/static/js/charts.js +++ b/aprsd/web/static/js/charts.js @@ -8,7 +8,10 @@ window.chartColors = { blue: 'rgb(54, 162, 235)', purple: 'rgb(153, 102, 255)', grey: 'rgb(201, 203, 207)', - black: 'rgb(0, 0, 0)' + black: 'rgb(0, 0, 0)', + lightcoral: 'rgb(240,128,128)', + darkseagreen: 'rgb(143, 188,143)' + }; function size_dict(d){c=0; for (i in d) ++c; return c} @@ -20,28 +23,28 @@ function start_charts() { } }); - memory_chart = new Chart($("#memChart"), { - label: 'Memory Usage', + packets_chart = new Chart($("#packetsChart"), { + label: 'APRS Packets', type: 'line', data: { labels: [], datasets: [{ - label: 'Peak Ram usage', - borderColor: window.chartColors.red, + label: 'Packets Sent', + borderColor: window.chartColors.lightcoral, data: [], }, { - label: 'Current Ram usage', - borderColor: window.chartColors.blue, + label: 'Packets Recieved', + borderColor: window.chartColors.darkseagreen, data: [], - }], + }] }, options: { responsive: true, maintainAspectRatio: false, title: { display: true, - text: 'Memory Usage', + text: 'APRS Packets', }, scales: { x: { @@ -67,12 +70,12 @@ function start_charts() { labels: [], datasets: [{ label: 'Messages Sent', - borderColor: window.chartColors.green, + borderColor: window.chartColors.lightcoral, data: [], }, { label: 'Messages Recieved', - borderColor: window.chartColors.yellow, + borderColor: window.chartColors.darkseagreen, data: [], }, { @@ -117,12 +120,12 @@ function start_charts() { labels: [], datasets: [{ label: 'Sent', - borderColor: window.chartColors.green, + borderColor: window.chartColors.lightcoral, data: [], }, { label: 'Recieved', - borderColor: window.chartColors.yellow, + borderColor: window.chartColors.darkseagreen, data: [], }], }, @@ -149,6 +152,46 @@ function start_charts() { } } }); + + memory_chart = new Chart($("#memChart"), { + label: 'Memory Usage', + type: 'line', + data: { + labels: [], + datasets: [{ + label: 'Peak Ram usage', + borderColor: window.chartColors.red, + data: [], + }, + { + label: 'Current Ram usage', + borderColor: window.chartColors.blue, + data: [], + }], + }, + options: { + responsive: true, + maintainAspectRatio: false, + title: { + display: true, + text: 'Memory Usage', + }, + scales: { + x: { + type: 'timeseries', + offset: true, + ticks: { + major: { enabled: true }, + fontStyle: context => context.tick.major ? 'bold' : undefined, + source: 'data', + maxRotation: 0, + autoSkip: true, + autoSkipPadding: 75, + } + } + } + } + }); } @@ -182,6 +225,7 @@ function update_stats( data ) { const html_pretty = Prism.highlight(JSON.stringify(data, null, '\t'), Prism.languages.json, 'json'); $("#jsonstats").html(html_pretty); short_time = data["time"].split(/\s(.+)/)[1]; + updateDualData(packets_chart, short_time, data["stats"]["packets"]["sent"], data["stats"]["packets"]["received"]); updateQuadData(message_chart, short_time, data["stats"]["messages"]["sent"], data["stats"]["messages"]["recieved"], data["stats"]["messages"]["ack_sent"], data["stats"]["messages"]["ack_recieved"]); updateDualData(email_chart, short_time, data["stats"]["email"]["sent"], data["stats"]["email"]["recieved"]); updateDualData(memory_chart, short_time, data["stats"]["aprsd"]["memory_peak"], data["stats"]["aprsd"]["memory_current"]); diff --git a/aprsd/web/templates/index.html b/aprsd/web/templates/index.html index 44ce2f6..082f5a6 100644 --- a/aprsd/web/templates/index.html +++ b/aprsd/web/templates/index.html @@ -41,6 +41,7 @@ var cfg_pretty = JSON.stringify(cfg_json, null, '\t'); const html_pretty = Prism.highlight( cfg_pretty, Prism.languages.json, 'json'); $("#configjson").html(html_pretty); + $("#jsonstats").fadeToggle(1000); $('.ui.accordion').accordion({exclusive: false}); $('.menu .item').tab('change tab', 'charts-tab'); @@ -71,22 +72,45 @@
{{ stats }}+
{{ config_json|safe }}
{{ stats|safe }}+