aboutsummaryrefslogtreecommitdiffstats
path: root/interface/js
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2017-01-31 15:48:57 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2017-01-31 15:48:57 +0000
commit977c7309f8438796c3baaf09291cf3ece2916899 (patch)
tree9d5a16b67551d7d2daccbe61f0e2c9a80d88a11d /interface/js
parentc7bfdbfcd187cf08fa1023770a67420a64203391 (diff)
downloadrspamd-977c7309f8438796c3baaf09291cf3ece2916899.tar.gz
rspamd-977c7309f8438796c3baaf09291cf3ece2916899.zip
[WebUI] Add graph tab
Diffstat (limited to 'interface/js')
-rw-r--r--interface/js/app/graph.js195
-rw-r--r--interface/js/app/rspamd.js252
-rw-r--r--interface/js/app/stats.js98
3 files changed, 300 insertions, 245 deletions
diff --git a/interface/js/app/graph.js b/interface/js/app/graph.js
new file mode 100644
index 000000000..2d5341446
--- /dev/null
+++ b/interface/js/app/graph.js
@@ -0,0 +1,195 @@
+/*
+ The MIT License (MIT)
+
+ Copyright (C) 2017 Vsevolod Stakhov <vsevolod@highsecure.ru>
+ Copyright (C) 2017 Alexander Moisseev
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+define(['jquery', 'd3evolution', 'humanize'],
+function($, D3Evolution) {
+ var rrd_pie_config = {
+ header: {},
+ size: {
+ canvasWidth: 400,
+ canvasHeight: 180,
+ pieInnerRadius: "20%",
+ pieOuterRadius: "80%"
+ },
+ labels: {
+ outer: {
+ format: "none"
+ },
+ inner: {
+ hideWhenLessThanPercentage: 8
+ },
+ },
+ misc: {
+ pieCenterOffset: {
+ x: -120,
+ y: 10,
+ },
+ gradient: {
+ enabled: true,
+ },
+ },
+ };
+
+ var graph_options = {
+ title: "Rspamd throughput",
+ width: 1060,
+ height: 370,
+ yAxisLabel: "Message rate, msg/s",
+
+ legend: {
+ space: 140,
+ entries: [{
+ label: "Rejected",
+ color: "#FF0000"
+ }, {
+ label: "Temporary rejected",
+ color: "#BF8040"
+ }, {
+ label: "Subject rewrited",
+ color: "#FF6600"
+ }, {
+ label: "Probable spam",
+ color: "#FFAD00"
+ }, {
+ label: "Greylisted",
+ color: "#436EEE"
+ }, {
+ label: "Clean",
+ color: "#66CC00"
+ }]
+ }
+ };
+
+ function initGraph() {
+ // Get selectors' current state
+ function getSelector(id) {
+ var e = document.getElementById(id);
+ return e.options[e.selectedIndex].value;
+ }
+ var graph = new D3Evolution("graph", $.extend({}, graph_options, {
+ type: getSelector("selType"),
+ interpolate: getSelector("selInterpolate"),
+ convert: getSelector("selConvert"),
+ }));
+ $("#selConvert").change(function () {
+ graph.convert(this.value);
+ });
+ $("#selType").change(function () {
+ graph.type(this.value);
+ });
+ $("#selInterpolate").change(function () {
+ graph.interpolate(this.value);
+ });
+
+ return graph;
+ }
+
+ function getRrdSummary(json) {
+ var xExtents = d3.extent(d3.merge(json), function (d) { return d.x; });
+ var timeInterval = xExtents[1] - xExtents[0];
+
+ return json.map(function (curr, i) {
+ var avg = d3.mean(curr, function (d) { return d.y; });
+ var yExtents = d3.extent(curr, function (d) { return d.y; });
+
+ return {
+ label: graph_options.legend.entries[i].label,
+ value: avg && (avg * timeInterval) ^ 0,
+ min: yExtents[0],
+ avg: avg && avg.toFixed(6),
+ max: yExtents[1],
+ last: curr[curr.length - 1].y,
+ color: graph_options.legend.entries[i].color,
+ };
+ }, []);
+ }
+
+ function drawRrdTable(data) {
+ $('#rrd-table').DataTable({
+ destroy: true,
+ paging: false,
+ searching: false,
+ info: false,
+ data: data,
+ columns: [
+ { data: "label", title: "Action" },
+ { data: "value", title: "Messages", defaultContent: "" },
+ { data: "min", title: "Minimum, msg/s", defaultContent: "" },
+ { data: "avg", title: "Average, msg/s", defaultContent: "" },
+ { data: "max", title: "Maximum, msg/s", defaultContent: "" },
+ { data: "last", title: "Last, msg/s" },
+ ],
+
+ "fnRowCallback": function (nRow, aData) {
+ $(nRow).css("color", aData.color);
+ }
+ });
+ }
+
+ var interface = {};
+
+ interface.draw = function(rspamd, graphs, checked_server, type) {
+ if (graphs.graph === undefined) {
+ graphs.graph = initGraph();
+ }
+
+ if (type === undefined) {
+ function getSelector(id) {
+ var e = document.getElementById(id);
+ return e.options[e.selectedIndex].value;
+ }
+ type = getSelector("selData");
+ }
+
+ $.ajax({
+ dataType: 'json',
+ type: 'GET',
+ url: 'graph',
+ jsonp: false,
+ data: {
+ "type": type
+ },
+ beforeSend: function (xhr) {
+ xhr.setRequestHeader('Password', rspamd.getPassword());
+ },
+ success: function (data) {
+ var rrd_summary = getRrdSummary(data);
+ graphs.graph.data(data);
+ graphs.rrd_pie = rspamd.drawPie(graphs.rrd_pie,
+ "rrd-pie",
+ rrd_summary,
+ rrd_pie_config);
+ drawRrdTable(rrd_summary);
+ },
+ error: function (jqXHR, textStatus, errorThrown) {
+ rspamd.alertMessage('alert-error', 'Cannot receive throughput data: ' +
+ textStatus + ' ' + jqXHR.status + ' ' + errorThrown);
+ }
+ });
+ };
+
+
+ return interface;
+});
diff --git a/interface/js/app/rspamd.js b/interface/js/app/rspamd.js
index 800ad20fe..a7d3f4156 100644
--- a/interface/js/app/rspamd.js
+++ b/interface/js/app/rspamd.js
@@ -22,8 +22,8 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
-define(['jquery', 'visibility', 'bootstrap'],
- function ($, D3Evolution, d3pie, visibility, DataTable) {
+define(['jquery', 'd3pie', 'visibility', 'bootstrap'],
+ function ($, d3pie, visibility, DataTable) {
// begin
var graphs = {};
var tables = {};
@@ -94,13 +94,18 @@ define(['jquery', 'visibility', 'bootstrap'],
});
break;
case "#throughput_nav":
- getGraphData(selData);
+ require(['app/graph'], function(graph) {
+ graph.draw(interface, graphs, checked_server, selData);
+ });
+
var autoRefresh = {
hourly: 60000,
daily: 300000
};
timer_id.throughput = Visibility.every(autoRefresh[selData] || 3600000, function () {
- getGraphData(selData);
+ require(['app/graph'], function(graph) {
+ graph.draw(interface, graphs, checked_server, selData);
+ });
});
break;
case "#configuration_nav":
@@ -172,15 +177,6 @@ define(['jquery', 'visibility', 'bootstrap'],
selData = this.value;
tabClick("#throughput_nav");
});
- $("#selConvert").change(function () {
- graph.convert(this.value);
- });
- $("#selType").change(function () {
- graph.type(this.value);
- });
- $("#selInterpolate").change(function () {
- graph.interpolate(this.value);
- });
$.ajaxSetup({
timeout: 2000,
jsonp: false
@@ -389,6 +385,98 @@ define(['jquery', 'visibility', 'bootstrap'],
});
};
+ interface.drawPie = function(obj, id, data, conf) {
+ if (obj) {
+ obj.updateProp("data.content",
+ data.filter(function (elt) {
+ return elt.value > 0;
+ })
+ );
+ } else {
+ obj = new d3pie(id,
+ $.extend({}, {
+ "header": {
+ "title": {
+ "text": "Rspamd filter stats",
+ "fontSize": 24,
+ "font": "open sans"
+ },
+ "subtitle": {
+ "color": "#999999",
+ "fontSize": 12,
+ "font": "open sans"
+ },
+ "titleSubtitlePadding": 9
+ },
+ "footer": {
+ "color": "#999999",
+ "fontSize": 10,
+ "font": "open sans",
+ "location": "bottom-left"
+ },
+ "size": {
+ "canvasWidth": 600,
+ "canvasHeight": 400,
+ "pieInnerRadius": "20%",
+ "pieOuterRadius": "85%"
+ },
+ "data": {
+ //"sortOrder": "value-desc",
+ "content": data.filter(function (elt) {
+ return elt.value > 0;
+ })
+ },
+ "labels": {
+ "outer": {
+ "hideWhenLessThanPercentage": 1,
+ "pieDistance": 30
+ },
+ "inner": {
+ "hideWhenLessThanPercentage": 4
+ },
+ "mainLabel": {
+ "fontSize": 14
+ },
+ "percentage": {
+ "color": "#eeeeee",
+ "fontSize": 14,
+ "decimalPlaces": 0
+ },
+ "lines": {
+ "enabled": true
+ },
+ "truncation": {
+ "enabled": true
+ }
+ },
+ "tooltips": {
+ "enabled": true,
+ "type": "placeholder",
+ "string": "{label}: {value}, {percentage}%"
+ },
+ "effects": {
+ "pullOutSegmentOnClick": {
+ "effect": "back",
+ "speed": 400,
+ "size": 8
+ },
+ "load": {
+ "effect": "none"
+ }
+ },
+ "misc": {
+ "gradient": {
+ "enabled": true,
+ "percentage": 100
+ }
+ }
+ }, conf));
+ }
+ return obj;
+ };
+
+ interface.getPassword = getPassword;
+
return interface;
// @alert popover
@@ -500,145 +588,7 @@ define(['jquery', 'visibility', 'bootstrap'],
$('#modalBody form').hide();
});
- var rrd_pie_config = {
- header: {},
- size: {
- canvasWidth: 400,
- canvasHeight: 180,
- pieInnerRadius: "20%",
- pieOuterRadius: "80%"
- },
- labels: {
- outer: {
- format: "none"
- },
- inner: {
- hideWhenLessThanPercentage: 8
- },
- },
- misc: {
- pieCenterOffset: {
- x: -120,
- y: 10,
- },
- gradient: {
- enabled: true,
- },
- },
- };
- var graph_options = {
- title: "Rspamd throughput",
- width: 1060,
- height: 370,
- yAxisLabel: "Message rate, msg/s",
-
- legend: {
- space: 140,
- entries: [{
- label: "Rejected",
- color: "#FF0000"
- }, {
- label: "Temporary rejected",
- color: "#BF8040"
- }, {
- label: "Subject rewrited",
- color: "#FF6600"
- }, {
- label: "Probable spam",
- color: "#FFAD00"
- }, {
- label: "Greylisted",
- color: "#436EEE"
- }, {
- label: "Clean",
- color: "#66CC00"
- }]
- }
- };
-
- function initGraph() {
- // Get selectors' current state
- function getSelector(id) {
- var e = document.getElementById(id);
- return e.options[e.selectedIndex].value;
- }
-
- selData = getSelector("selData");
-
- graph = new D3Evolution("graph", $.extend({}, graph_options, {
- type: getSelector("selType"),
- interpolate: getSelector("selInterpolate"),
- convert: getSelector("selConvert"),
- }));
- }
-
- function getRrdSummary(json) {
- var xExtents = d3.extent(d3.merge(json), function (d) { return d.x; });
- var timeInterval = xExtents[1] - xExtents[0];
-
- return json.map(function (curr, i) {
- var avg = d3.mean(curr, function (d) { return d.y; });
- var yExtents = d3.extent(curr, function (d) { return d.y; });
-
- return {
- label: graph_options.legend.entries[i].label,
- value: avg && (avg * timeInterval) ^ 0,
- min: yExtents[0],
- avg: avg && avg.toFixed(6),
- max: yExtents[1],
- last: curr[curr.length - 1].y,
- color: graph_options.legend.entries[i].color,
- };
- }, []);
- }
-
- function drawRrdTable(data) {
- $('#rrd-table').DataTable({
- destroy: true,
- paging: false,
- searching: false,
- info: false,
- data: data,
- columns: [
- { data: "label", title: "Action" },
- { data: "value", title: "Messages", defaultContent: "" },
- { data: "min", title: "Minimum, msg/s", defaultContent: "" },
- { data: "avg", title: "Average, msg/s", defaultContent: "" },
- { data: "max", title: "Maximum, msg/s", defaultContent: "" },
- { data: "last", title: "Last, msg/s" },
- ],
-
- "fnRowCallback": function (nRow, aData) {
- $(nRow).css("color", aData.color);
- }
- });
- }
-
- function getGraphData(type) {
- $.ajax({
- dataType: 'json',
- type: 'GET',
- url: 'graph',
- jsonp: false,
- data: {
- "type": type
- },
- beforeSend: function (xhr) {
- xhr.setRequestHeader('Password', getPassword());
- },
- success: function (data) {
- const rrd_summary = getRrdSummary(data);
- graph.data(data);
- rrd_pie = drawPie(rrd_pie, "rrd-pie", rrd_summary, rrd_pie_config);
- drawRrdTable(rrd_summary);
- },
- error: function (jqXHR, textStatus, errorThrown) {
- alertMessage('alert-error', 'Cannot receive throughput data: ' +
- textStatus + ' ' + jqXHR.status + ' ' + errorThrown);
- }
- });
- }
// @get history log
// function getChart() {
diff --git a/interface/js/app/stats.js b/interface/js/app/stats.js
index 51e13b385..e2ce33d0f 100644
--- a/interface/js/app/stats.js
+++ b/interface/js/app/stats.js
@@ -139,7 +139,7 @@ function($, d3pie, Humanize) {
$(widgets).show();
}
- function getChart(pie, checked_server) {
+ function getChart(rspamd, pie, checked_server) {
var creds = JSON.parse(sessionStorage.getItem('Credentials'));
if (creds && creds[checked_server]) {
var data = creds[checked_server].data;
@@ -169,100 +169,10 @@ function($, d3pie, Humanize) {
"data" : data.reject,
"value" : data.reject
} ];
- return drawPie(pie, "chart", new_data);
- }
- }
- function drawPie(obj, id, data, conf) {
- if (obj) {
- obj.updateProp("data.content",
- data.filter(function (elt) {
- return elt.value > 0;
- })
- );
- } else {
- obj = new d3pie(id,
- $.extend({}, {
- "header": {
- "title": {
- "text": "Rspamd filter stats",
- "fontSize": 24,
- "font": "open sans"
- },
- "subtitle": {
- "color": "#999999",
- "fontSize": 12,
- "font": "open sans"
- },
- "titleSubtitlePadding": 9
- },
- "footer": {
- "color": "#999999",
- "fontSize": 10,
- "font": "open sans",
- "location": "bottom-left"
- },
- "size": {
- "canvasWidth": 600,
- "canvasHeight": 400,
- "pieInnerRadius": "20%",
- "pieOuterRadius": "85%"
- },
- "data": {
- //"sortOrder": "value-desc",
- "content": data.filter(function (elt) {
- return elt.value > 0;
- })
- },
- "labels": {
- "outer": {
- "hideWhenLessThanPercentage": 1,
- "pieDistance": 30
- },
- "inner": {
- "hideWhenLessThanPercentage": 4
- },
- "mainLabel": {
- "fontSize": 14
- },
- "percentage": {
- "color": "#eeeeee",
- "fontSize": 14,
- "decimalPlaces": 0
- },
- "lines": {
- "enabled": true
- },
- "truncation": {
- "enabled": true
- }
- },
- "tooltips": {
- "enabled": true,
- "type": "placeholder",
- "string": "{label}: {value}, {percentage}%"
- },
- "effects": {
- "pullOutSegmentOnClick": {
- "effect": "back",
- "speed": 400,
- "size": 8
- },
- "load": {
- "effect": "none"
- }
- },
- "misc": {
- "gradient": {
- "enabled": true,
- "percentage": 100
- }
- }
- }, conf));
+ return rspamd.drawPie(pie, "chart", new_data);
}
- return obj;
}
-
// Public API
var interface = {
statWidgets: function(rspamd, graphs, checked_server) {
@@ -311,7 +221,7 @@ function($, d3pie, Humanize) {
});
sessionStorage.setItem("Credentials", JSON.stringify(to_Credentials));
displayStatWidgets(checked_server);
- graphs.chart = getChart(graphs.chart, checked_server);
+ graphs.chart = getChart(rspamd, graphs.chart, checked_server);
},
function (serv, jqXHR, textStatus, errorThrown) {
var alert_status = serv.name + '_alerted';
@@ -327,4 +237,4 @@ function($, d3pie, Humanize) {
return interface;
}
-); \ No newline at end of file
+);