Просмотр исходного кода

Feature/2859 Replace RRD image with chartjs (#3045)

* Add support for rrd-tool export

* Include chartjs

* Fix include path chartjs

* Fix behaviour mysql, postgresql and ethernet ports behaviour

* Disable timer 

We should be able rewrite / remove parts of it when done...

* Replace RRD images with chartjs

* Use day / week / year instead daily weekly and yearly

* Disable linting for 3rd part libary

* Move libraries to /js/vendor/

Some as still hard code in init.js and app.js

* Update .eslintignore
Jaap Marcus 3 лет назад
Родитель
Сommit
49d3f61b3e

+ 196 - 0
bin/v-export-rrd

@@ -0,0 +1,196 @@
+#!/bin/bash
+# info: export rrd charts as json
+# options: [CHART] [TIMESPAN]
+#
+# example: v-export-rrd chart format
+
+#----------------------------------------------------------#
+#                Variables & Functions                     #
+#----------------------------------------------------------#
+
+chart=$1
+timespan=${2-hour}
+
+# Includes
+# shellcheck source=/etc/hestiacp/hestia.conf
+source /etc/hestiacp/hestia.conf
+# shellcheck source=/usr/local/hestia/func/main.sh
+source $HESTIA/func/main.sh
+# load config file
+source_conf "$HESTIA/conf/hestia.conf"
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+check_args '1' "$#" 'chart'
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+function generate_load_table () {
+        rrdtool xport --json -s $start -e $end --step $step \
+        DEF:la=$RRD/la/la.rrd:LA:AVERAGE \
+        DEF:pr=$RRD/la/la.rrd:PR:AVERAGE \
+        XPORT:la:load \
+        XPORT:pr:Proccess
+}
+
+function generate_mem_table () {
+        rrdtool xport --json -s $start -e $end --step $step \
+        DEF:used=$RRD/mem/mem.rrd:RAM:AVERAGE \
+        DEF:swap=$RRD/mem/mem.rrd:SWAP:AVERAGE \
+        DEF:free=$RRD/mem/mem.rrd:FREE:AVERAGE \
+        XPORT:used:Used \
+        XPORT:swap:Swap \
+        XPORT:free:Free
+}
+
+function generate_apache2_table () {
+        rrdtool xport --json -s $start -e $end --step $step \
+        DEF:a=$RRD/web/apache2.rrd:A:AVERAGE \
+        XPORT:a:Connections
+}
+
+function generate_httpd_table () {
+        rrdtool xport --json -s $start -e $end --step $step \
+        DEF:a=$RRD/web/httpd.rrd:A:AVERAGE \
+        XPORT:a:Connections
+}
+
+function generate_nginx_table () {
+        rrdtool xport --json -s $start -e $end --step $step \
+        DEF:a=$RRD/web/nginx.rrd:A:AVERAGE \
+        XPORT:a:Connections
+}
+
+function generate_ftp_table () {
+        rrdtool xport --json -s $start -e $end --step $step \
+        DEF:a=$RRD/ftp/ftp.rrd:A:AVERAGE \
+        XPORT:a:Connections
+}
+
+function generate_ssh_table () {
+        rrdtool xport --json -s $start -e $end --step $step \
+        DEF:a=$RRD/ssh/ssh.rrd:A:AVERAGE \
+        XPORT:a:Connections
+}
+
+function generate_mysql_table () {
+        if [ -f "$RRD/db/mysql_$host.rrd" ]; then
+            rrdtool xport --json -s $start -e $end --step $step \
+            DEF:a=$RRD/db/mysql_$host.rrd:A:AVERAGE \
+            DEF:s=$RRD/db/mysql_$host.rrd:S:AVERAGE \
+            XPORT:a:Queries \
+            XPORT:s:Slow
+        else
+            echo "Does not exists";
+            exit 1;
+        fi
+}
+
+function generate_pgsql_table () {
+        if [ -f "$RRD/db/pgsql_$host.rrd" ]; then
+            rrdtool xport --json -s $start -e $end --step $step \
+            DEF:a=$RRD/db/pgsql_$host.rrd:A:AVERAGE \
+            DEF:t=$RRD/db/pgsql_$host.rrd:T:AVERAGE \
+            XPORT:a:Queries \
+            XPORT:t:Transactions
+        else
+            echo "Does not exists";
+            exit 1;
+        fi
+}
+
+function generate_mail_table () {
+        rrdtool xport --json -s $start -e $end --step $step \
+        DEF:a=$RRD/mail/mail.rrd:A:AVERAGE \
+        XPORT:a:Emails
+}
+
+function generate_net_table () {
+        if [ -f "$RRD/net/$host.rrd" ]; then
+            rrdtool xport --json -s $start -e $end --step $step \
+            DEF:inoctets=$RRD/net/$host.rrd:RX:AVERAGE \
+            DEF:outoctets=$RRD/net/$host.rrd:TX:AVERAGE \
+            XPORT:inoctets:"Input (rx)" \
+            XPORT:outoctets:"Output (rx)"
+        else
+            echo "Does not exists";
+            exit 1;
+        fi
+}
+
+
+
+if [ "$timespan" = "week" ]; then
+    start=$(date -d "7 days ago" +%s);
+    # every 30 min
+    step=3600
+elif [ "$timespan" = "month" ]; then
+    start=$(date -d "1 month ago" +%s);
+    step=21600
+elif [ "$timespan" = "year" ]; then
+    start=$(date -d "1 year ago" +%s);
+    step=172800
+else
+    start=$(date -d "1 day ago" +%s);
+    # every 5min
+    step=300
+fi
+end=$(date +%s)
+
+host=$(echo $chart | cut -d'_' -f2 );
+chart=$(echo $chart | cut -d'_' -f1 );
+
+case $chart in
+    "la")
+    generate_load_table
+    ;;
+
+    "mem")
+    generate_mem_table
+    ;;
+
+    "apache2")
+    generate_apache2_table
+    ;;
+
+    "httpd")
+    generate_httpd_table
+    ;;
+
+    "nginx")
+    generate_nginx_table
+    ;;
+
+    "ftp")
+    generate_ftp_table
+    ;;
+
+    "ssh")
+    generate_ssh_table
+    ;;
+
+    "mysql")
+    generate_mysql_table
+    ;;
+
+    "pgsql")
+    generate_pgsql_table
+    ;;
+
+    "mail")
+    generate_mail_table
+    ;;
+
+    "net")
+    generate_net_table
+    ;;
+
+
+    *)
+    echo "Does not exists";
+    exit 1;
+esac

+ 1 - 1
web/.eslintignore

@@ -1 +1 @@
-js/jquery/*.js
+js/vendor/

+ 1 - 1
web/js/events.js

@@ -208,7 +208,7 @@ VE.helpers.toggleHiddenPasswordText = function(ref, triggering_elm) {
 var reloadTimer = 150;
 var reloadFunction = '';
 
-$(document).ready(startTime);
+//$(document).ready(startTime);
 function startTime(){
     if ($(".spinner")[0]){
     reloadFunction = setInterval(updateInterval, 100);

+ 43 - 0
web/js/pages/list_rrd.js

@@ -0,0 +1,43 @@
+// Default max of 3 lines are drawn for memory. Colors need to be update to work better
+colors=['rgba(255,52,120,0.5)','rgba(255,52,0,0.5)','rgba(255,255,120,0.5)'];
+// Other markups are working see https://www.chartjs.org/docs/latest/
+
+//todo make charts reponsive
+$(document).ready( function(){
+    $('canvas').each(function(){
+
+        $.post('/list/rrd/ajax.php',{service:$(this).attr('id'),period:$(this).attr('period')}, function(response){
+            labels=[];
+            //data is stored as start, end time and step between each step
+            for(i = response.meta.start; i < response.meta.end; i=i + response.meta.step){
+                labels.push(new Date(i * 1000).toLocaleString());
+            }
+            datasets = [];
+            //response.data stores data as i[x,y] useless for chartjs split in separate datasets
+            for(i = 0; i < response.meta.legend.length; i++){
+                data=[];
+                for( b of response.data){
+                    data.push(b[i]);
+                }
+                dataset={label: response.meta.legend[i], data: data, borderColor: colors[i]};
+                datasets.push(dataset);
+            }
+            //draw chart
+            const ctx = document.getElementById(response.service).getContext('2d');
+            const myChart = new Chart(ctx, {
+                type: 'line',
+                data: {
+                    labels: labels,
+                    datasets: datasets
+                },
+                options: {
+                    scales: {
+                        y: {
+                            beginAtZero: true
+                        }
+                    }
+                }
+            });
+        },'json');
+    });
+})

Разница между файлами не показана из-за своего большого размера
+ 6 - 0
web/js/vendor/chart.min.js


+ 0 - 0
web/inc/jquery/jquery-3.6.1.min.js → web/js/vendor/jquery/jquery-3.6.1.min.js


+ 0 - 0
web/js/jquery/jquery-ui.min.js → web/js/vendor/jquery/jquery-ui.min.js


+ 0 - 0
web/js/jquery/jquery.cookie.js → web/js/vendor/jquery/jquery.cookie.js


+ 0 - 0
web/js/jquery/jquery.finder.js → web/js/vendor/jquery/jquery.finder.js


+ 32 - 0
web/list/rrd/ajax.php

@@ -0,0 +1,32 @@
+<?php
+use function Hestiacp\quoteshellarg\quoteshellarg;
+// Main include
+include($_SERVER['DOCUMENT_ROOT']."/inc/main.php");
+
+// Check user
+if ($_SESSION['userContext'] != 'admin') {
+    header('Location: /list/user');
+    exit;
+}
+
+if (empty($_POST['period'])) {
+    $period = "daily";
+} else {
+    if (in_array($_POST['period'] ,array('day', 'week','month','year'))) {
+        $period=$_POST['period'];
+    } else {
+        $period = "daily";
+    }
+}
+
+if (empty($_POST['service'])) {
+    $service = "la";
+} else {
+    $service = $_POST['service'];
+}
+
+// Data
+exec(HESTIA_CMD."v-export-rrd ".quoteshellarg($service)." ".quoteshellarg($period), $output, $return_var);
+$data = json_decode(implode('', $output), true);
+$data['service'] = $service;
+echo json_encode($data);

+ 3 - 3
web/list/rrd/index.php

@@ -17,9 +17,9 @@ $data = json_decode(implode('', $output), true);
 unset($output);
 
 if (empty($_GET['period'])) {
-    $period = 'daily';
-} elseif (!in_array($_GET['period'], array('daily', 'weekly', 'monthly', 'yearly'))) {
-    $period = 'daily';
+    $period = 'day';
+} elseif (!in_array($_GET['period'], array('day', 'week', 'month', 'year'))) {
+    $period = 'day';
 } else {
     $period = $_GET['period'];
 }

+ 4 - 3
web/templates/includes/end_js.html

@@ -1,6 +1,7 @@
-<script src="/js/jquery/jquery.cookie.js?<?=JS_LATEST_UPDATE?>"></script>
-<script src="/js/jquery/jquery-ui.min.js?<?=JS_LATEST_UPDATE?>"></script>
-<script src="/js/jquery/jquery.finder.js?<?=JS_LATEST_UPDATE?>"></script>
+<script src="/js/vendor/chart.min.js?<?=JS_LATEST_UPDATE?>"></script>
+<script src="/js/vendor/jquery/jquery.cookie.js?<?=JS_LATEST_UPDATE?>"></script>
+<script src="/js/vendor/jquery/jquery-ui.min.js?<?=JS_LATEST_UPDATE?>"></script>
+<script src="/js/vendor/jquery/jquery.finder.js?<?=JS_LATEST_UPDATE?>"></script>
 <script src="/js/hotkeys.js?<?=JS_LATEST_UPDATE?>"></script>
 <script src="/js/events.js?<?=JS_LATEST_UPDATE?>"></script>
 <script src="/js/app.js?<?=JS_LATEST_UPDATE?>"></script>

+ 1 - 1
web/templates/includes/top_js.html

@@ -1 +1 @@
-<script src="/inc/jquery/jquery-3.6.1.min.js"></script>
+<script src="/js/vendor/jquery/jquery-3.6.1.min.js"></script>

+ 9 - 18
web/templates/pages/list_rrd.html

@@ -7,18 +7,10 @@
     </div>
     <div class="l-sort-toolbar">
       <div>
-        <a class="vst<?php if ((empty($period)) || ($period == 'daily')) echo " selected" ?>" href="?period=daily"><?=_('Daily');?></a>
-        <a class="vst<?php if ((!empty($period)) && ($period == 'weekly')) echo " selected" ?>" href="?period=weekly"><?=_('Weekly');?></a>
-        <a class="vst<?php if ((!empty($period)) && ($period == 'monthly')) echo " selected" ?>" href="?period=monthly"><?=_('Monthly');?></a>
-        <a class="vst<?php if ((!empty($period)) && ($period == 'yearly')) echo " selected" ?>" href="?period=yearly"><?=_('Yearly');?></a>
-      </div>
-      <div class="timer-container" style="float:right;">
-        <span class="timer-button pause-stop" onclick="stopTimer()"><i class="fas fa-pause"></i></span>
-        <div class="timer-button spinner">
-          <div class="spinner-inner"></div>
-          <div class="spinner-mask"></div>
-          <div class="spinner-mask-two"></div>
-        </div>
+        <a class="vst<?php if ((empty($period)) || ($period == 'day')) echo " selected" ?>" href="?period=day"><?=_('Daily');?></a>
+        <a class="vst<?php if ((!empty($period)) && ($period == 'week')) echo " selected" ?>" href="?period=week"><?=_('Weekly');?></a>
+        <a class="vst<?php if ((!empty($period)) && ($period == 'month')) echo " selected" ?>" href="?period=month"><?=_('Monthly');?></a>
+        <a class="vst<?php if ((!empty($period)) && ($period == 'year')) echo " selected" ?>" href="?period=year"><?=_('Yearly');?></a>
       </div>
     </div>
   </div>
@@ -26,7 +18,6 @@
 <!-- End toolbar -->
 
 <div class="l-separator"></div>
-
 <div class="l-center units animated fadeIn">
   <!-- Begin graph list item loop -->
   <?php foreach ($data as $key => $value) { ?>
@@ -35,11 +26,11 @@
         <div class="l-unit__name separate">
           <?= _($data[$key]['TITLE'])?>
         </div>
-        <div>
-          <a href="/list/rrd/image.php?/rrd/<?=$data[$key]['TYPE']."/".$period."-".$data[$key]['RRD'].".png"?>" class="u-block" target="_blank">
-            <img class="graph-rounded" src="/list/rrd/image.php?/rrd/<?=$data[$key]['TYPE']."/".$period."-".$data[$key]['RRD'].".png"?>" alt="">
-          </a>
-        </div>
+        <?php if($data[$key]['TYPE'] != 'net'){?>
+        <canvas id="<?=$data[$key]['RRD'];?>" class="js-chart" width="800" height="200" period="<?php echo htmlentities($period);?>"></canvas>
+        <?php }else{?>
+        <canvas id="net_<?=$data[$key]['RRD'];?>" class="js-chart" width="800" height="200" period="<?php echo htmlentities($period);?>"></canvas>
+        <?php } ?>
       </div>
     </div>
   <?php } ?>

+ 3 - 3
web/templates/pages/list_server_info.html

@@ -6,9 +6,9 @@
   <?php require ''.$_SERVER['HESTIA'].'/web/templates/includes/title.html'; ?>
   <?php require ''.$_SERVER['HESTIA'].'/web/templates/includes/css.html'; ?>
   <?php require ''.$_SERVER['HESTIA'].'/web/templates/includes/top_js.html'; ?>
-  <script src="/js/jquery/jquery.cookie.js?<?=JS_LATEST_UPDATE?>"></script>
-  <script src="/js/jquery/jquery-ui.min.js?<?=JS_LATEST_UPDATE?>"></script>
-  <script src="/js/jquery/jquery.finder.js?<?=JS_LATEST_UPDATE?>"></script>
+  <script src="/js/vendor/jquery/jquery.cookie.js?<?=JS_LATEST_UPDATE?>"></script>
+  <script src="/js/vendor/jquery/jquery-ui.min.js?<?=JS_LATEST_UPDATE?>"></script>
+  <script src="/js/vendor/jquery/jquery.finder.js?<?=JS_LATEST_UPDATE?>"></script>
   <script src="/js/hotkeys.js?<?=JS_LATEST_UPDATE?>"></script>
   <script src="/js/events.js?<?=JS_LATEST_UPDATE?>"></script>
   <script src="/js/app.js?<?=JS_LATEST_UPDATE?>"></script>

+ 3 - 3
web/templates/pages/list_weblog.html

@@ -6,9 +6,9 @@
   <?php require ''.$_SERVER['HESTIA'].'/web/templates/includes/title.html'; ?>
   <?php require ''.$_SERVER['HESTIA'].'/web/templates/includes/css.html'; ?>
   <?php require ''.$_SERVER['HESTIA'].'/web/templates/includes/top_js.html'; ?>
-  <script src="/js/jquery/jquery.cookie.js?<?=JS_LATEST_UPDATE?>"></script>
-  <script src="/js/jquery/jquery-ui.min.js?<?=JS_LATEST_UPDATE?>"></script>
-  <script src="/js/jquery/jquery.finder.js?<?=JS_LATEST_UPDATE?>"></script>
+  <script src="/js/vendor/jquery/jquery.cookie.js?<?=JS_LATEST_UPDATE?>"></script>
+  <script src="/js/vendor/jquery/jquery-ui.min.js?<?=JS_LATEST_UPDATE?>"></script>
+  <script src="/js/vendor/jquery/jquery.finder.js?<?=JS_LATEST_UPDATE?>"></script>
   <script src="/js/hotkeys.js?<?=JS_LATEST_UPDATE?>"></script>
   <script src="/js/events.js?<?=JS_LATEST_UPDATE?>"></script>
   <script src="/js/app.js?<?=JS_LATEST_UPDATE?>"></script>

Некоторые файлы не были показаны из-за большого количества измененных файлов