mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-13 08:09:41 +00:00
Reporting / Insight - cleanup frontend code and move some processing to the backend for easier handling.
Eventually we want to replace the d3 graphs, but before doing that, it's likely a good idea to cleanup the code for readability.
This commit is contained in:
parent
de5dd5f527
commit
e4203d81eb
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2016 Deciso B.V.
|
||||
* Copyright (C) 2016-2025 Deciso B.V.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -70,6 +70,7 @@ class NetworkinsightController extends ApiControllerBase
|
||||
$to_date = $filter->sanitize($to_date, "int");
|
||||
$resolution = $filter->sanitize($resolution, "int");
|
||||
$field = $filter->sanitize($field, "string");
|
||||
$interfaces = $this->getInterfacesAction();
|
||||
|
||||
$result = array();
|
||||
if ($this->request->isGet()) {
|
||||
@ -78,11 +79,6 @@ class NetworkinsightController extends ApiControllerBase
|
||||
$response = $backend->configdRun(
|
||||
"netflow aggregate fetch {$provider} {$from_date} {$to_date} {$resolution} {$field}"
|
||||
);
|
||||
// for test, request random data
|
||||
//$response = $backend->configdRun(
|
||||
// "netflow aggregate fetch {$provider} {$from_date} {$to_date} {$resolution} {$field} " .
|
||||
// "em0,in~em0,out~em1,in~em1,out~em2,in~em2,out~em3,in~em3,out"
|
||||
//);
|
||||
$graph_data = json_decode($response, true);
|
||||
if ($graph_data != null) {
|
||||
ksort($graph_data);
|
||||
@ -124,7 +120,19 @@ class NetworkinsightController extends ApiControllerBase
|
||||
}
|
||||
}
|
||||
foreach ($timeseries as $timeserie_key => $data) {
|
||||
$result[] = array("key" => $timeserie_key, "values" => $data);
|
||||
$record = [
|
||||
"key" => $timeserie_key,
|
||||
"values" => $data
|
||||
];
|
||||
if (in_array($provider, ['FlowInterfaceTotals'])) {
|
||||
$tmp = explode(',', $timeserie_key);
|
||||
if (!empty($interfaces[$tmp[0]])) {
|
||||
$record['interface'] = $interfaces[$tmp[0]];
|
||||
}
|
||||
$record['direction'] = $tmp[1] ?? '';
|
||||
}
|
||||
|
||||
$result[] = $record;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,6 +167,8 @@ class NetworkinsightController extends ApiControllerBase
|
||||
$max_hits = $filter->sanitize($max_hits, "int");
|
||||
|
||||
if ($this->request->isGet()) {
|
||||
$protocols = $this->getProtocolsAction();
|
||||
$services = $this->getServicesAction();
|
||||
if ($this->request->get("filter_field") != null && $this->request->get("filter_value") != null) {
|
||||
$filter_fields = explode(',', $this->request->get("filter_field"));
|
||||
$filter_values = explode(',', $this->request->get("filter_value"));
|
||||
@ -181,7 +191,26 @@ class NetworkinsightController extends ApiControllerBase
|
||||
$configd_cmd .= " {$measure} {$data_filter} {$max_hits}";
|
||||
$response = $backend->configdRun($configd_cmd);
|
||||
$graph_data = json_decode($response, true);
|
||||
if ($graph_data != null) {
|
||||
if (is_array($graph_data)) {
|
||||
foreach ($graph_data as &$record) {
|
||||
if (isset($record['dst_port']) || isset($record['service_port'])) {
|
||||
$portnum = $record['dst_port'] ?? $record['service_port'];
|
||||
$label = $portnum;
|
||||
$protocol = '';
|
||||
if (isset($record['protocol']) && isset($protocols[$record['protocol']])) {
|
||||
$protocol = sprintf(" (%s)", $protocols[$record['protocol']]);
|
||||
}
|
||||
if (isset($services[$portnum])) {
|
||||
$label = $services[$portnum];
|
||||
}
|
||||
$record['last_seen_str'] = '';
|
||||
if (!empty($record['last_seen'])) {
|
||||
$record['last_seen_str'] = date('Y-m-d H:i:s', $record['last_seen']);
|
||||
}
|
||||
|
||||
$record['label'] = $label . $protocol;
|
||||
}
|
||||
}
|
||||
return $graph_data;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{#
|
||||
|
||||
OPNsense® is Copyright © 2016 by Deciso B.V.
|
||||
OPNsense® is Copyright © 2016-2025 by Deciso B.V.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -27,7 +27,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#}
|
||||
|
||||
<style type="text/css">
|
||||
.panel-heading-sm{
|
||||
.panel-heading-sm {
|
||||
height: 28px;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
@ -55,15 +55,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
// collect all chars for resize update
|
||||
var pageCharts = {};
|
||||
|
||||
// form metadata definitions
|
||||
var interface_names = [];
|
||||
var service_names = [];
|
||||
var protocol_names = [];
|
||||
|
||||
/**
|
||||
* load shared metadata (interfaces, protocols, )
|
||||
*/
|
||||
function get_metadata()
|
||||
function do_startup()
|
||||
{
|
||||
var dfObj = new $.Deferred();
|
||||
ajaxGet('/api/diagnostics/netflow/isEnabled', {}, function(is_enabled, status){
|
||||
@ -73,33 +66,30 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
}
|
||||
// fetch interface names
|
||||
ajaxGet('/api/diagnostics/networkinsight/getInterfaces',{}, function(intf_names, status){
|
||||
interface_names = intf_names;
|
||||
// fetch protocol names
|
||||
ajaxGet('/api/diagnostics/networkinsight/getProtocols',{}, function(protocols, status) {
|
||||
protocol_names = protocols;
|
||||
// fetch service names
|
||||
ajaxGet('/api/diagnostics/networkinsight/getServices',{}, function(services, status) {
|
||||
service_names = services;
|
||||
// return promise, no need to wait for getMetadata
|
||||
dfObj.resolve();
|
||||
// fetch aggregators
|
||||
ajaxGet('/api/diagnostics/networkinsight/getMetadata',{}, function(metadata, status) {
|
||||
Object.keys(metadata['aggregators']).forEach(function (agg_name) {
|
||||
var res = metadata['aggregators'][agg_name]['resolutions'].join(',');
|
||||
$("#export_collection").append($("<option data-resolutions='"+res+"'/>").val(agg_name).text(agg_name));
|
||||
});
|
||||
$("#export_collection").change(function(){
|
||||
$("#export_resolution").html("");
|
||||
var resolutions = String($(this).find('option:selected').data('resolutions'));
|
||||
resolutions.split(',').map(function(item) {
|
||||
$("#export_resolution").append($("<option/>").val(item).text(item));
|
||||
});
|
||||
$("#export_resolution").selectpicker('refresh');
|
||||
});
|
||||
$("#export_collection").change();
|
||||
$("#export_collection").selectpicker('refresh');
|
||||
});
|
||||
for (var key in intf_names) {
|
||||
$('#interface_select').append($("<option></option>").attr("value",key).text(intf_names[key]));
|
||||
$('#interface_select_detail').append($("<option></option>").attr("value",key).text(intf_names[key]));
|
||||
}
|
||||
$('#interface_select').selectpicker('refresh');
|
||||
$('#interface_select_detail').selectpicker('refresh');
|
||||
// return promise, no need to wait for getMetadata
|
||||
dfObj.resolve();
|
||||
// fetch aggregators
|
||||
ajaxGet('/api/diagnostics/networkinsight/getMetadata',{}, function(metadata, status) {
|
||||
Object.keys(metadata['aggregators']).forEach(function (agg_name) {
|
||||
var res = metadata['aggregators'][agg_name]['resolutions'].join(',');
|
||||
$("#export_collection").append($("<option data-resolutions='"+res+"'/>").val(agg_name).text(agg_name));
|
||||
});
|
||||
$("#export_collection").change(function(){
|
||||
$("#export_resolution").html("");
|
||||
var resolutions = String($(this).find('option:selected').data('resolutions'));
|
||||
resolutions.split(',').map(function(item) {
|
||||
$("#export_resolution").append($("<option/>").val(item).text(item));
|
||||
});
|
||||
$("#export_resolution").selectpicker('refresh');
|
||||
});
|
||||
$("#export_collection").change();
|
||||
$("#export_collection").selectpicker('refresh');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -123,51 +113,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
function get_time_select()
|
||||
{
|
||||
// current time stamp
|
||||
var timestamp_now = Math.round((new Date()).getTime() / 1000);
|
||||
var duration = 0;
|
||||
var resolution = 0;
|
||||
switch ($("#total_time_select").val()) {
|
||||
case "2h":
|
||||
duration = 60*60*2;
|
||||
resolution = 30;
|
||||
break;
|
||||
case "8h":
|
||||
duration = 60*60*8;
|
||||
resolution = 300;
|
||||
break;
|
||||
case "24h":
|
||||
duration = 60*60*24;
|
||||
resolution = 300;
|
||||
break;
|
||||
case "7d":
|
||||
duration = 60*60*24*7;
|
||||
resolution = 3600;
|
||||
break;
|
||||
case "14d":
|
||||
duration = 60*60*24*14;
|
||||
resolution = 3600;
|
||||
break;
|
||||
case "30d":
|
||||
duration = 60*60*24*30;
|
||||
resolution = 86400;
|
||||
break;
|
||||
case "60d":
|
||||
duration = 60*60*24*60;
|
||||
resolution = 86400;
|
||||
break;
|
||||
case "90d":
|
||||
duration = 60*60*24*90;
|
||||
resolution = 86400;
|
||||
break;
|
||||
case "182d":
|
||||
duration = 60*60*24*182;
|
||||
resolution = 86400;
|
||||
break;
|
||||
case "1y":
|
||||
duration = 60*60*24*365;
|
||||
resolution = 86400;
|
||||
break;
|
||||
}
|
||||
let timestamp_now = Math.round((new Date()).getTime() / 1000);
|
||||
let duration = parseInt($("#total_time_select > option:selected").data('duration'));
|
||||
let resolution = parseInt($("#total_time_select > option:selected").data('resolution'));
|
||||
// always round from timestamp to nearest hour
|
||||
const from_timestamp = Math.floor((timestamp_now -duration) / 3600 ) * 3600;
|
||||
return {resolution: resolution, from: from_timestamp, to: timestamp_now};
|
||||
@ -217,17 +165,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
let chart_data = [];
|
||||
data.map(function(item){
|
||||
let item_dir = item.key.split(',').pop();
|
||||
let item_intf = item.key.split(',')[0];
|
||||
if (item_intf != '0' && item_intf != 'lo0' ) {
|
||||
if (direction == item_dir) {
|
||||
if (interface_names[item_intf] != undefined) {
|
||||
item.key = interface_names[item_intf];
|
||||
} else {
|
||||
item.key = item_intf;
|
||||
}
|
||||
chart_data.push(item);
|
||||
}
|
||||
if (direction == item.direction) {
|
||||
item.key = item.interface ?? '-';
|
||||
chart_data.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
@ -273,19 +213,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
let chart_data = [];
|
||||
data.map(function(item){
|
||||
var label = "(other)";
|
||||
var proto = "";
|
||||
if (item.protocol != "") {
|
||||
if (item.protocol in protocol_names) {
|
||||
proto = ' (' + protocol_names[item.protocol] + ')';
|
||||
}
|
||||
if (item.dst_port in service_names) {
|
||||
label = service_names[item.dst_port];
|
||||
} else {
|
||||
label = item.dst_port
|
||||
}
|
||||
}
|
||||
chart_data.push({'label': label + proto, 'value': item.total});
|
||||
chart_data.push({'label': item.label, 'value': item.total});
|
||||
});
|
||||
|
||||
var diag = d3.select("#chart_top_ports svg")
|
||||
@ -486,51 +414,24 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
});
|
||||
// dump rows
|
||||
data.map(function(item){
|
||||
let proto = '';
|
||||
if (item.protocol in protocol_names) {
|
||||
proto = ' (' + protocol_names[item.protocol] + ')';
|
||||
}
|
||||
let service_port;
|
||||
if (item.service_port in service_names) {
|
||||
service_port = service_names[item.service_port];
|
||||
} else {
|
||||
service_port = item.service_port
|
||||
}
|
||||
let tr_str = '<tr>';
|
||||
if (service_port != "") {
|
||||
tr_str += '<td> <span data-toggle="tooltip" title="'+proto+'/'+item.service_port+'">'+service_port+' </span> '+proto+'</td>';
|
||||
} else {
|
||||
tr_str += "<td>{{ lang._('(other)') }}</td>";
|
||||
}
|
||||
tr_str += '<td>' + item['src_addr'] + '</td>';
|
||||
tr_str += '<td>' + item['dst_addr'] + '</td>';
|
||||
tr_str += '<td>' + byteFormat(item['total']) + ' ' + '</td>';
|
||||
if (item['last_seen'] != "") {
|
||||
tr_str += '<td>' + d3.time.format('%b %e %H:%M:%S')(new Date(item['last_seen']*1000)) + '</td>';
|
||||
} else {
|
||||
tr_str += '<td></td>'
|
||||
}
|
||||
|
||||
|
||||
let percentage = parseInt((item['total'] /grand_total) * 100);
|
||||
let perc_text = ((item['total'] /grand_total) * 100).toFixed(2);
|
||||
tr_str += '<td>';
|
||||
tr_str += '<div class="progress-bar progress-bar-warning progress-bar-striped" role="progressbar" ';
|
||||
tr_str += 'aria-valuenow="'+percentage+'" aria-valuemin="0" aria-valuemax="100" style="color: black; min-width: 2em; width:' ;
|
||||
tr_str += percentage+'%;">'+perc_text+' %</div>';
|
||||
tr_str += '</td>';
|
||||
tr_str += '</tr>';
|
||||
html.push(tr_str);
|
||||
let percentage = parseInt((item.total /grand_total) * 100);
|
||||
let perc_text = ((item.total /grand_total) * 100).toFixed(2);
|
||||
html.push($("<tr/>").append([
|
||||
$("<td/>").text(item.label),
|
||||
$("<td/>").text(item.src_addr),
|
||||
$("<td/>").text(item.dst_addr),
|
||||
$("<td/>").text(byteFormat(item.total)),
|
||||
$("<td/>").text(item.last_seen_str),
|
||||
$("<td>").html(
|
||||
'<div class="progress-bar progress-bar-warning progress-bar-striped" role="progressbar" aria-valuenow="'+
|
||||
percentage+
|
||||
'" aria-valuemin="0" aria-valuemax="100" style="color: black; min-width: 2em; width:'+
|
||||
percentage+'%;">'+perc_text+' %'
|
||||
)
|
||||
]));
|
||||
});
|
||||
$("#netflow_details > tbody").html(html.join(''));
|
||||
if (grand_total > 0) {
|
||||
$("#netflow_details_total").html(byteFormat(grand_total));
|
||||
} else {
|
||||
$("#netflow_details_total").html("");
|
||||
}
|
||||
|
||||
// link tooltips
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
$("#netflow_details > tbody").empty().append(html);
|
||||
$("#netflow_details_total").html(byteFormat(grand_total));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -596,15 +497,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// trigger initial tab load
|
||||
get_metadata().done(function(){
|
||||
// known interfaces
|
||||
for (var key in interface_names) {
|
||||
$('#interface_select').append($("<option></option>").attr("value",key).text(interface_names[key]));
|
||||
$('#interface_select_detail').append($("<option></option>").attr("value",key).text(interface_names[key]));
|
||||
}
|
||||
$('#interface_select').selectpicker('refresh');
|
||||
$('#interface_select_detail').selectpicker('refresh');
|
||||
|
||||
do_startup().done(function(){
|
||||
// generate date selection (utc start, end times)
|
||||
var now = new Date;
|
||||
var date_begin = Date.UTC(now.getUTCFullYear(),now.getUTCMonth(), now.getUTCDate(), 0, 0, 0, 0);
|
||||
@ -670,16 +563,16 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<div id="totals" class="tab-pane fade in active">
|
||||
<div class="pull-right">
|
||||
<select class="selectpicker" id="total_time_select">
|
||||
<option value="2h">{{ lang._('Last 2 hours, 30 second average') }}</option>
|
||||
<option value="8h">{{ lang._('Last 8 hours, 5 minute average') }}</option>
|
||||
<option value="24h">{{ lang._('Last 24 hours, 5 minute average') }}</option>
|
||||
<option value="7d">{{ lang._('7 days, 1 hour average') }}</option>
|
||||
<option value="14d">{{ lang._('14 days, 1 hour average') }}</option>
|
||||
<option value="30d">{{ lang._('30 days, 24 hour average') }}</option>
|
||||
<option value="60d">{{ lang._('60 days, 24 hour average') }}</option>
|
||||
<option value="90d">{{ lang._('90 days, 24 hour average') }}</option>
|
||||
<option value="182d">{{ lang._('182 days, 24 hour average') }}</option>
|
||||
<option value="1y">{{ lang._('Last year, 24 hour average') }}</option>
|
||||
<option data-duration="7200" data-resolution="30" value="2h">{{ lang._('Last 2 hours, 30 second average') }}</option>
|
||||
<option data-duration="28800" data-resolution="300" value="8h">{{ lang._('Last 8 hours, 5 minute average') }}</option>
|
||||
<option data-duration="86400" data-resolution="300" value="24h">{{ lang._('Last 24 hours, 5 minute average') }}</option>
|
||||
<option data-duration="604800" data-resolution="3600" value="7d">{{ lang._('7 days, 1 hour average') }}</option>
|
||||
<option data-duration="1209600" data-resolution="3600" value="14d">{{ lang._('14 days, 1 hour average') }}</option>
|
||||
<option data-duration="2592000" data-resolution="86400" value="30d">{{ lang._('30 days, 24 hour average') }}</option>
|
||||
<option data-duration="5184000" data-resolution="86400" value="60d">{{ lang._('60 days, 24 hour average') }}</option>
|
||||
<option data-duration="7776000" data-resolution="86400" value="90d">{{ lang._('90 days, 24 hour average') }}</option>
|
||||
<option data-duration="15724800" data-resolution="86400" value="182d">{{ lang._('182 days, 24 hour average') }}</option>
|
||||
<option data-duration="31536000" data-resolution="86400" value="1y">{{ lang._('Last year, 24 hour average') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user