Compare commits

...

4 Commits

Author SHA1 Message Date
Hemna f2d39e5fd2 Added threads chart to admin ui graphs 2024-04-12 17:43:11 -04:00
Hemna 3bd7adda44 set packetlist max back to 100 2024-04-12 17:17:53 -04:00
Hemna 91ba6d10ce ensure thread count is updated 2024-04-12 17:03:10 -04:00
Hemna c6079f897d Added threads table in the admin web ui 2024-04-12 16:33:52 -04:00
5 changed files with 127 additions and 11 deletions

View File

@ -22,7 +22,7 @@ class PacketList(objectstore.ObjectStoreMixin):
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._maxlen = 50
cls._maxlen = 100
cls.data = {
"types": {},
"packets": OrderedDict(),

View File

@ -8,6 +8,8 @@ var packet_types_data = {};
var mem_current = []
var mem_peak = []
var thread_current = []
function start_charts() {
console.log("start_charts() called");
@ -17,6 +19,7 @@ function start_charts() {
create_messages_chart();
create_ack_chart();
create_memory_chart();
create_thread_chart();
}
@ -258,6 +261,49 @@ function create_memory_chart() {
memory_chart.setOption(option);
}
function create_thread_chart() {
thread_canvas = document.getElementById('threadChart');
thread_chart = echarts.init(thread_canvas);
// Specify the configuration items and data for the chart
var option = {
title: {
text: 'Active Threads'
},
legend: {},
tooltip: {
trigger: 'axis'
},
toolbox: {
show: true,
feature: {
mark : {show: true},
dataView : {show: true, readOnly: false},
magicType : {show: true, type: ['line', 'bar']},
restore : {show: true},
saveAsImage : {show: true}
}
},
calculable: true,
xAxis: { type: 'time' },
yAxis: { },
series: [
{
name: 'current',
type: 'line',
smooth: true,
color: 'red',
encode: {
x: 'timestamp',
y: 'current' // refer sensor 1 value
}
}
]
};
thread_chart.setOption(option);
}
@ -371,6 +417,21 @@ function updateMemChart(time, current, peak) {
memory_chart.setOption(option);
}
function updateThreadChart(time, threads) {
keys = Object.keys(threads);
thread_count = keys.length;
thread_current.push([time, thread_count]);
option = {
series: [
{
name: 'current',
data: thread_current,
}
]
}
thread_chart.setOption(option);
}
function updateMessagesChart() {
updateTypeChart(message_chart, "MessagePacket")
}
@ -397,6 +458,7 @@ function update_stats( data ) {
updateMessagesChart();
updateAcksChart();
updateMemChart(ts, stats["APRSDStats"]["memory_current"], stats["APRSDStats"]["memory_peak"]);
updateThreadChart(ts, stats["APRSDThreadList"]);
//updateQuadData(message_chart, short_time, data["stats"]["messages"]["sent"], data["stats"]["messages"]["received"], 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"]);

View File

@ -113,6 +113,34 @@ function update_plugins( data ) {
plugindiv.append(html_str);
}
function update_threads( data ) {
stats = data["stats"];
if (stats.hasOwnProperty("APRSDThreadList") == false) {
return
}
var threadsdiv = $("#threadsDiv");
var countdiv = $("#thread_count");
var html_str = '<table class="ui celled striped table"><thead><tr>'
html_str += '<th>Thread Name</th><th>Alive?</th>'
html_str += '<th>Age</th><th>Loop Count</th>'
html_str += '</tr></thead><tbody>'
threadsdiv.html('')
var threads = stats["APRSDThreadList"];
var keys = Object.keys(threads);
countdiv.html(keys.length);
keys.sort();
for (var i=0; i<keys.length; i++) { // now lets iterate in sort order
var key = keys[i];
var val = threads[key];
html_str += '<tr><td class="collapsing">' + key + '</td>';
html_str += '<td>' + val["alive"] + '</td><td>' + val["age"] + '</td>';
html_str += '<td>' + val["loop_count"] + '</td></tr>';
}
html_str += "</tbody></table>";
threadsdiv.append(html_str);
}
function update_packets( data ) {
var packetsdiv = $("#packetsDiv");
//nuke the contents first, then add to it.
@ -179,6 +207,7 @@ function start_update() {
update_watchlist(data);
update_seenlist(data);
update_plugins(data);
update_threads(data);
},
complete: function() {
setTimeout(statsworker, 10000);

View File

@ -81,6 +81,7 @@
<div class="item" data-tab="seen-tab">Seen List</div>
<div class="item" data-tab="watch-tab">Watch List</div>
<div class="item" data-tab="plugin-tab">Plugins</div>
<div class="item" data-tab="threads-tab">Threads</div>
<div class="item" data-tab="config-tab">Config</div>
<div class="item" data-tab="log-tab">LogFile</div>
<!-- <div class="item" data-tab="oslo-tab">OSLO CONFIG</div> //-->
@ -96,11 +97,6 @@
<div class="ui segment" style="height: 300px" id="packetsChart"></div>
</div>
</div>
<div class="row">
<div class="column">
<div class="ui segment" style="height: 300px" id="packetTypesChart"></div>
</div>
</div>
<div class="row">
<div class="column">
<div class="ui segment" style="height: 300px" id="messagesChart"></div>
@ -111,8 +107,17 @@
</div>
<div class="row">
<div class="column">
<div class="ui segment" style="height: 300px" id="memChart">
</div>
<div class="ui segment" style="height: 300px" id="packetTypesChart"></div>
</div>
</div>
<div class="row">
<div class="column">
<div class="ui segment" style="height: 300px" id="threadChart"></div>
</div>
</div>
<div class="row">
<div class="column">
<div class="ui segment" style="height: 300px" id="memChart"></div>
</div>
</div>
<!-- <div class="row">
@ -155,6 +160,13 @@
<div id="pluginDiv" class="ui mini text">Loading</div>
</div>
<div class="ui bottom attached tab segment" data-tab="threads-tab">
<h3 class="ui dividing header">
Threads Loaded (<span id="thread_count">{{ thread_count }}</span>)
</h3>
<div id="threadsDiv" class="ui mini text">Loading</div>
</div>
<div class="ui bottom attached tab segment" data-tab="config-tab">
<h3 class="ui dividing header">Config</h3>
<pre id="configjson" class="language-json">{{ config_json|safe }}</pre>

View File

@ -70,12 +70,17 @@ def index():
pm = plugin.PluginManager()
plugins = pm.get_plugins()
plugin_count = len(plugins)
client_stats = stats["stats"].get("APRSClientStats", {})
if CONF.aprs_network.enabled:
transport = "aprs-is"
if client_stats:
aprs_connection = client_stats.get("server_string", "")
else:
aprs_connection = "APRS-IS"
aprs_connection = (
"APRS-IS Server: <a href='http://status.aprs2.net' >"
"{}</a>".format(stats["stats"]["APRSClientStats"]["server_string"])
"{}</a>".format(aprs_connection)
)
else:
# We might be connected to a KISS socket?
@ -96,10 +101,17 @@ def index():
)
)
stats["stats"]["APRSClientStats"]["transport"] = transport
stats["stats"]["APRSClientStats"]["aprs_connection"] = aprs_connection
if client_stats:
stats["stats"]["APRSClientStats"]["transport"] = transport
stats["stats"]["APRSClientStats"]["aprs_connection"] = aprs_connection
entries = conf.conf_to_dict()
thread_info = stats["stats"].get("APRSDThreadList", {})
if thread_info:
thread_count = len(thread_info)
else:
thread_count = "unknown"
return flask.render_template(
"index.html",
initial_stats=json.dumps(stats, cls=aprsd_json.SimpleJSONEncoder),
@ -111,6 +123,7 @@ def index():
sort_keys=True, default=str,
),
plugin_count=plugin_count,
thread_count=thread_count,
# oslo_out=generate_oslo()
)