From aca64614686d6338a35a28ff9647e4fe43e8c069 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 18 Dec 2019 13:10:46 +0000 Subject: [PATCH 1/3] Change over-time graphs from line to stacked bar representation. This is much more natural for this kind of data. Also, improve DB graphs to always generate a meaningful display (always generate about 200 bars). This graph was basically unusable when specifying a larger range than, say, one week. Signed-off-by: DL6ER --- api_db.php | 7 --- index.php | 4 +- scripts/pi-hole/js/db_graph.js | 98 +++++++++++++++++++++++++--------- scripts/pi-hole/js/index.js | 87 ++++++------------------------ 4 files changed, 91 insertions(+), 105 deletions(-) diff --git a/api_db.php b/api_db.php index af296ca2..925a2cb5 100644 --- a/api_db.php +++ b/api_db.php @@ -382,13 +382,6 @@ if (isset($_GET['getGraphData']) && $auth) // $data[timestamp] = value_in_this_interval $data[$row[0]] = intval($row[1]); } - - // Fill the missing intervals with zero - // Advance in steps of interval - for($i = $from; $i < $until; $i += $interval) { - if(!array_key_exists($i, $data)) - $data[$i] = 0; - } } return $data; diff --git a/index.php b/index.php index a75e77ab..78c1a464 100644 --- a/index.php +++ b/index.php @@ -82,7 +82,7 @@
-

Queries over last hours

+

Total queries over last hours

@@ -107,7 +107,7 @@
-

Clients (over time)

+

Client activity over last hours

diff --git a/scripts/pi-hole/js/db_graph.js b/scripts/pi-hole/js/db_graph.js index 422179e8..74c5a6b3 100644 --- a/scripts/pi-hole/js/db_graph.js +++ b/scripts/pi-hole/js/db_graph.js @@ -11,6 +11,7 @@ var start__ = moment().subtract(6, "days"); var from = moment(start__).utc().valueOf()/1000; var end__ = moment(); var until = moment(end__).utc().valueOf()/1000; +var interval = 0; var timeoutWarning = $("#timeoutWarning"); @@ -71,7 +72,35 @@ function compareNumbers(a, b) { function updateQueriesOverTime() { $("#queries-over-time .overlay").show(); timeoutWarning.show(); - $.getJSON("api_db.php?getGraphData&from="+from+"&until="+until, function(data) { + + // Compute interval to obtain about 200 values + var num = 200; + interval = (until-from)/num; + // Default displaying axis scaling + timeLineChart.options.scales.xAxes[0].time.unit="hour" + + if(num*interval >= 6*29*24*60*60) + { + // If the requested data is more than 3 months, set ticks interval to quarterly + timeLineChart.options.scales.xAxes[0].time.unit="quarter" + } + else if(num*interval >= 3*29*24*60*60) + { + // If the requested data is more than 3 months, set ticks interval to months + timeLineChart.options.scales.xAxes[0].time.unit="month" + } + if(num*interval >= 29*24*60*60) + { + // If the requested data is more than 1 month, set ticks interval to weeks + timeLineChart.options.scales.xAxes[0].time.unit="week" + } + else if(num*interval >= 6*24*60*60) + { + // If the requested data is more than 1 week, set ticks interval to days + timeLineChart.options.scales.xAxes[0].time.unit="day" + } + + $.getJSON("api_db.php?getGraphData&from="+from+"&until="+until+"&interval="+interval, function(data) { // convert received objects to arrays data.domains_over_time = objectToArray(data.domains_over_time); @@ -119,7 +148,7 @@ function updateQueriesOverTime() { } timeLineChart.data.labels.push(d); - timeLineChart.data.datasets[0].data.push(dom); + timeLineChart.data.datasets[0].data.push(dom - ads); timeLineChart.data.datasets[1].data.push(ads); } } @@ -131,54 +160,73 @@ function updateQueriesOverTime() { }); } +Date.prototype.AddInterval = function () { + return new Date(this.valueOf() + 1000 * interval); +} + $(document).ready(function() { var ctx = document.getElementById("queryOverTimeChart").getContext("2d"); timeLineChart = new Chart(ctx, { - type: "line", + type: "bar", data: { - labels: [ 0 ], + labels: [ ], datasets: [ { - label: "Total DNS Queries", + label: "Permitted DNS Queries", fill: true, - backgroundColor: "rgba(220,220,220,0.5)", + backgroundColor: "rgba(0, 166, 90,.8)", borderColor: "rgba(0, 166, 90,.8)", pointBorderColor: "rgba(0, 166, 90,.8)", pointRadius: 1, pointHoverRadius: 5, data: [], - pointHitRadius: 5, - cubicInterpolationMode: "monotone" + pointHitRadius: 5 }, { label: "Blocked DNS Queries", fill: true, - backgroundColor: "rgba(0,192,239,0.5)", + backgroundColor: "rgba(0,192,239,1)", borderColor: "rgba(0,192,239,1)", pointBorderColor: "rgba(0,192,239,1)", pointRadius: 1, pointHoverRadius: 5, data: [], - pointHitRadius: 5, - cubicInterpolationMode: "monotone" + pointHitRadius: 5 } ] }, options: { tooltips: { enabled: true, - responsive: true, mode: "x-axis", callbacks: { title: function(tooltipItem) { var label = tooltipItem[0].xLabel; var time = new Date(label); - var date = time.getFullYear()+"-"+padNumber(time.getMonth()+1)+"-"+padNumber(time.getDate()); - var h = time.getHours(); - var m = time.getMinutes(); - var from = padNumber(h)+":"+padNumber(m)+":00"; - var to = padNumber(h)+":"+padNumber(m+9)+":59"; - return "Queries from "+from+" to "+to+" on "+date; + var from_date = time.getFullYear() + + "-" + + padNumber(time.getMonth()+1) + + "-" + + padNumber(time.getDate()) + + " " + + padNumber(time.getHours()) + + ":" + + padNumber(time.getMinutes()) + + ":" + + padNumber(time.getSeconds()); + time = time.AddInterval(); + var until_date = time.getFullYear() + + "-" + + padNumber(time.getMonth()+1) + + "-" + + padNumber(time.getDate()) + + " " + + padNumber(time.getHours()) + + ":" + + padNumber(time.getMinutes()) + + ":" + + padNumber(time.getSeconds()); + return "Queries from " + from_date + " to " + until_date; }, label: function(tooltipItems, data) { if(tooltipItems.datasetIndex === 1) @@ -203,20 +251,22 @@ $(document).ready(function() { scales: { xAxes: [{ type: "time", - display: false, + stacked: true, time: { + unit: "hour", displayFormats: { "minute": "HH:mm", "hour": "HH:mm", - "day": "HH:mm", - "week": "MMM DD HH:mm", - "month": "MMM DD", - "quarter": "MMM DD", - "year": "MMM DD" + "day": "MMM DD", + "week": "MMM DD", + "month": "MMM", + "quarter": "MMM", + "year": "YYYY MMM" } } }], yAxes: [{ + stacked: true, ticks: { beginAtZero: true } diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js index 18b1773b..a65953fa 100644 --- a/scripts/pi-hole/js/index.js +++ b/scripts/pi-hole/js/index.js @@ -166,8 +166,10 @@ function updateQueriesOverTime() { } timeLineChart.data.labels.push(d); - timeLineChart.data.datasets[0].data.push(data.domains_over_time[1][hour]); - timeLineChart.data.datasets[1].data.push(data.ads_over_time[1][hour]); + var blocked = data.ads_over_time[1][hour]; + var permitted = data.domains_over_time[1][hour] - blocked; + timeLineChart.data.datasets[0].data.push(permitted); + timeLineChart.data.datasets[1].data.push(blocked); } } $("#queries-over-time .overlay").hide(); @@ -718,33 +720,31 @@ $(document).ready(function() { var ctx = document.getElementById("queryOverTimeChart").getContext("2d"); timeLineChart = new Chart(ctx, { - type: "line", + type: "bar", data: { - labels: [], + labels: [ ], datasets: [ { - label: "Total DNS Queries", + label: "Permitted DNS Queries", fill: true, - backgroundColor: "rgba(220,220,220,0.5)", + backgroundColor: "rgba(0, 166, 90,.8)", borderColor: "rgba(0, 166, 90,.8)", pointBorderColor: "rgba(0, 166, 90,.8)", pointRadius: 1, pointHoverRadius: 5, data: [], - pointHitRadius: 5, - cubicInterpolationMode: "monotone" + pointHitRadius: 5 }, { label: "Blocked DNS Queries", fill: true, - backgroundColor: "rgba(0,192,239,0.5)", + backgroundColor: "rgba(0,192,239,1)", borderColor: "rgba(0,192,239,1)", pointBorderColor: "rgba(0,192,239,1)", pointRadius: 1, pointHoverRadius: 5, data: [], - pointHitRadius: 5, - cubicInterpolationMode: "monotone" + pointHitRadius: 5 } ] }, @@ -785,6 +785,7 @@ $(document).ready(function() { scales: { xAxes: [{ type: "time", + stacked: true, time: { unit: "hour", displayFormats: { @@ -794,6 +795,7 @@ $(document).ready(function() { } }], yAxes: [{ + stacked: true, ticks: { beginAtZero: true } @@ -807,73 +809,13 @@ $(document).ready(function() { updateQueriesOverTime(); - // Create / load "Forward Destinations over Time" only if authorized - if(document.getElementById("forwardDestinationChart")) - { - ctx = document.getElementById("forwardDestinationChart").getContext("2d"); - forwardDestinationChart = new Chart(ctx, { - type: "line", - data: { - labels: [], - datasets: [{ data: [] }] - }, - options: { - tooltips: { - enabled: true, - mode: "x-axis", - callbacks: { - title: function(tooltipItem) { - var label = tooltipItem[0].xLabel; - var time = label.match(/(\d?\d):?(\d?\d?)/); - var h = parseInt(time[1], 10); - var m = parseInt(time[2], 10) || 0; - var from = padNumber(h)+":"+padNumber(m-5)+":00"; - var to = padNumber(h)+":"+padNumber(m+4)+":59"; - return "Forward destinations from "+from+" to "+to; - }, - label: function(tooltipItems, data) { - return data.datasets[tooltipItems.datasetIndex].label + ": " + (100.0*tooltipItems.yLabel).toFixed(1) + "%"; - } - } - }, - legend: { - display: false - }, - scales: { - xAxes: [{ - type: "time", - time: { - unit: "hour", - displayFormats: { - hour: "HH:mm" - }, - tooltipFormat: "HH:mm" - } - }], - yAxes: [{ - ticks: { - mix: 0.0, - max: 1.0, - beginAtZero: true, - callback: function(value) { - return Math.round(value*100) + " %"; - } - }, - stacked: true - }] - }, - maintainAspectRatio: true - } - }); - } - // Create / load "Top Clients over Time" only if authorized var clientsChartEl = document.getElementById("clientsChart"); if(clientsChartEl) { ctx = clientsChartEl.getContext("2d"); clientsChart = new Chart(ctx, { - type: "line", + type: "bar", data: { labels: [], datasets: [{ data: [] }] @@ -907,6 +849,7 @@ $(document).ready(function() { scales: { xAxes: [{ type: "time", + stacked: true, time: { unit: "hour", displayFormats: { From 4f42ebcbcafebe390beec829a964ac704441b133 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Thu, 19 Dec 2019 08:54:24 +0000 Subject: [PATCH 2/3] Add interval directly without extending the prototype. Signed-off-by: DL6ER --- scripts/pi-hole/js/db_graph.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/scripts/pi-hole/js/db_graph.js b/scripts/pi-hole/js/db_graph.js index 74c5a6b3..0ce616d6 100644 --- a/scripts/pi-hole/js/db_graph.js +++ b/scripts/pi-hole/js/db_graph.js @@ -132,8 +132,8 @@ function updateQueriesOverTime() { // Add data for each hour that is available for (hour in dates) { if (Object.prototype.hasOwnProperty.call(dates, hour)) { - var d, dom = 0, ads = 0; - d = new Date(1000*dates[hour]); + var date, dom = 0, ads = 0; + date = new Date(1000*dates[hour]); var idx = data.domains_over_time[0].indexOf(dates[hour].toString()); if (idx > -1) @@ -147,7 +147,7 @@ function updateQueriesOverTime() { ads = data.ads_over_time[1][idx]; } - timeLineChart.data.labels.push(d); + timeLineChart.data.labels.push(date); timeLineChart.data.datasets[0].data.push(dom - ads); timeLineChart.data.datasets[1].data.push(ads); } @@ -160,10 +160,6 @@ function updateQueriesOverTime() { }); } -Date.prototype.AddInterval = function () { - return new Date(this.valueOf() + 1000 * interval); -} - $(document).ready(function() { var ctx = document.getElementById("queryOverTimeChart").getContext("2d"); timeLineChart = new Chart(ctx, { @@ -214,7 +210,7 @@ $(document).ready(function() { padNumber(time.getMinutes()) + ":" + padNumber(time.getSeconds()); - time = time.AddInterval(); + time = new Date(time.valueOf() + 1000 * interval); var until_date = time.getFullYear() + "-" + padNumber(time.getMonth()+1) + From 1849e8a9c68e4d708cb30053db86ee0f32128c8f Mon Sep 17 00:00:00 2001 From: DL6ER Date: Thu, 19 Dec 2019 15:45:37 +0000 Subject: [PATCH 3/3] Remove unused variable. Signed-off-by: DL6ER --- scripts/pi-hole/js/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js index a65953fa..969e6cdc 100644 --- a/scripts/pi-hole/js/index.js +++ b/scripts/pi-hole/js/index.js @@ -7,8 +7,8 @@ // Define global variables /* global Chart:false, updateSessionTimer:false */ -var timeLineChart, forwardDestinationChart; -var queryTypePieChart, forwardDestinationPieChart, clientsChart; +var timeLineChart, clientsChart; +var queryTypePieChart, forwardDestinationPieChart; function padNumber(num) { return ("00" + num).substr(-2,2);