From bea341f8695a90a353ef7e450758efdbb1485542 Mon Sep 17 00:00:00 2001 From: Luca Haid Date: Tue, 5 Nov 2024 19:12:19 +0100 Subject: [PATCH] added new view for device congestion --- Layout/default/menu.php | 1 + .../DeviceMonitoring/DeviceMonitoring.php | 9 ++ .../DeviceMonitoringController.php | 151 ++++++++++++++++++ lib/Zabbix/Zabbix.php | 97 +++++++++++ .../DeviceMonitoringCongestion.js | 41 +++++ .../run-device-congestion-cache.php | 21 +++ 6 files changed, 320 insertions(+) create mode 100644 application/DeviceMonitoring/DeviceMonitoring.php create mode 100644 application/DeviceMonitoring/DeviceMonitoringController.php create mode 100644 lib/Zabbix/Zabbix.php create mode 100644 public/js/pages/DeviceMonitoringCongestion/DeviceMonitoringCongestion.js create mode 100644 scripts/monitoring/run-device-congestion-cache.php diff --git a/Layout/default/menu.php b/Layout/default/menu.php index 01426c782..89b64c5fe 100644 --- a/Layout/default/menu.php +++ b/Layout/default/menu.php @@ -130,6 +130,7 @@ isAdmin() || $me->can("Cpeshipping")): ?>
  • "> CPE Versand
  • isAdmin()) : ?>
  • "> Domains
  • isAdmin()) : ?>
  • "> IPAM
  • + isAdmin()) : ?>
  • "> Device Congestion
  • diff --git a/application/DeviceMonitoring/DeviceMonitoring.php b/application/DeviceMonitoring/DeviceMonitoring.php new file mode 100644 index 000000000..453aacd12 --- /dev/null +++ b/application/DeviceMonitoring/DeviceMonitoring.php @@ -0,0 +1,9 @@ +loadMe(); + $this->layout()->set("me", $me); + $this->me = $me; + + if (!$this->me->isAdmin()) { + $this->redirect("dashboard"); + } + + $this->zabbix = new Zabbix($this->ZABBIX_API_URL, $this->ZABBIX_API_KEY); + + } + + protected function congestionAction() { + $congestionData = $this->getCongestionData(); + + Helper::renderVue($this, "DeviceMonitoringCongestion", $this->mod, + ["CONGESTION_DATA" => $congestionData]); + } + + public function getCongestionData(): array { + $filename = TEMP_DIR . "/DeviceMonitoring/interfacesWithCongestion.json"; + + // if file is older than 50 minutes, fetch new data + if (file_exists($filename) && (time() - filemtime($filename)) < 3000) { + $interfacesWithCongestion = json_decode(file_get_contents($filename), true); + $fileCreateTime = date("Y-m-d H:i:s", filemtime($filename)); + + return ["interfacesWithCongestion" => $interfacesWithCongestion, "fileCreateTime" => $fileCreateTime]; + } + + $congestionInterfaces = $this->zabbix->getAllCongestionInterfaces(); + + $interfacesWithCongestion = []; + + $fetchedHosts = []; + + foreach ($congestionInterfaces as $interface) { + $itemId = $interface['itemid']; + $name = $interface['name']; + $name = str_replace(": Congestion Packets", "", $name); + $hostId = $interface['hostid']; + + $values = $this->zabbix->getItemValues($itemId); + + $highestValue = 0; + $highestValueTime = 0; + foreach ($values as $value) { + if ($value['value'] > $highestValue) { + $highestValue = $value['value']; + $highestValueTime = $value['clock']; + } + } + + // if highest value is 0, then there is no congestion + if ($highestValue == 0) { + continue; + } + + if (in_array($hostId, $fetchedHosts)) { + $host = $fetchedHosts[$hostId]; + } else { + $host = $this->zabbix->getHostById($hostId); + $fetchedHosts[$hostId] = $host; + } + + $hostname = $host[0]['name']; + $ip = $host[0]['host']; + + + $interfacesWithCongestion[] = [ + "hostname" => $hostname, + "ip" => $ip, + "name" => $name, + "zabbixUrl" => ZABBIX_URL . "/zabbix.php?action=latest.view&hostids%5B%5D=" . $hostId, + "grafanaUrl" => GRAFANA_URL . "/d/Ta3PtRWZk/mikrotik-dashboard?orgId=1&var-host=" . $hostname, + "highestValue" => $highestValue, + "highestValueTime" => $highestValueTime + ]; + } + + if (!file_exists(TEMP_DIR . "/DeviceMonitoring")) { + mkdir(TEMP_DIR . "/DeviceMonitoring"); + } + + file_put_contents($filename, json_encode($interfacesWithCongestion)); + return ["interfacesWithCongestion" => $interfacesWithCongestion, "fileCreateTime" => date("Y-m-d H:i:s")]; + } + + + protected function indexAction(): void { + $JSGlobals = ["BASE_URL" => self::getUrl("VoiceCallActive"), + "DASHBOARD_URL" => self::getUrl("Dashboard"), + "MFAPPNAME" => MFAPPNAME_SLUG, + "PAGE_TITLE" => "Active Voice Calls", + "PATH" => [ + ["text" => MFAPPNAME_SLUG, "href" => self::getUrl("Dashboard")], + ["text" => "Active Voice Calls", "href" => self::getUrl("VoiceCallActive")] + ], + "VOICE_CALL_ACTIVE_API_URL" => self::getUrl("VoiceCallActive/api"), + ]; + + $this->layout()->set("additionalCSS", ["css/views/VoiceCallActive.css"]); + $this->layout()->set("vueViewName", "VoiceCallActive"); + $this->layout()->set("JSGlobals", $JSGlobals); + $this->layout()->setTemplate("VueViews/Vue"); + } + + protected function apiAction() { + $do = $this->request->do; + + if (!$this->me->isAdmin()) { + $this->redirect("dashboard"); + } + + switch ($do) { + case "getActiveCalls": + $return = $this->getActiveCalls(); + break; + default: + $return = false; + break; + } + + if (!$return) { + $return = [ + "status" => "error", + "message" => "Invalid request." + ]; + } + + die(json_encode($return)); + } + + private function getActiveCalls(): array { + $activeCalls = $this->kolmisoftMore->getActiveCalls(); + + return is_null($activeCalls) ? [] : (is_object($activeCalls) ? [$activeCalls] : $activeCalls); + } +} \ No newline at end of file diff --git a/lib/Zabbix/Zabbix.php b/lib/Zabbix/Zabbix.php new file mode 100644 index 000000000..cbe21ddc1 --- /dev/null +++ b/lib/Zabbix/Zabbix.php @@ -0,0 +1,97 @@ +url = $url; + $this->apiKey = $apiKey; + } + + public function zabbixRequest($method, $params) { + $data = array( + 'jsonrpc' => '2.0', + 'method' => $method, + 'params' => $params, + 'id' => 1 + ); + + $options = array( + 'http' => array( + 'header' => "Content-Type: application/json\r\n" . + "Authorization: Bearer " . $this->apiKey . "\r\n", + 'method' => 'POST', + 'content' => json_encode($data) + ) + ); + + $context = stream_context_create($options); + $result = file_get_contents($this->url, false, $context); + + return json_decode($result, true); + } + + public function getAllCongestionInterfaces() { + $response = $this->zabbixRequest('item.get', array( + 'search' => array('name' => array("Congestion")), + )); + return $response['result']; + } + + public function getHostById($hostId) { + $response = $this->zabbixRequest('host.get', array( + 'hostids' => $hostId + )); + return $response['result']; + } + + public function getItemValues($itemIds) { + $response = $this->zabbixRequest('history.get', array( + 'itemids' => $itemIds, + 'output' => 'extend', + 'sortfield' => 'clock', + 'sortorder' => 'DESC', + 'limit' => 15 + )); + return $response['result']; + } + + public function getHosts($hostname) { + $response = $this->zabbixRequest('host.get', array( + 'search' => array('name' => array($hostname)) + )); + return $response['result']; + } + + public function getInterfaceItems($hostId, $interfaceName) { + $response = $this->zabbixRequest('item.get', array( + 'hostids' => $hostId, + 'search' => array('name' => array($interfaceName, "Bits")) + )); + return $response['result']; + } + + public function getUptimeItems($hostId) { + $response = $this->zabbixRequest('item.get', array( + 'hostids' => $hostId, + 'search' => array('name' => array("Uptime")) + )); + return $response['result']; + } + + public function getHostInterfaces($hostIds) { + $response = $this->zabbixRequest('hostinterface.get', array('hostids' => $hostIds)); + return $response['result']; + } + + public function createTask($itemid) { + $response = $this->zabbixRequest('task.create', array( + 'type' => 6, + 'request' => array( + 'itemid' => $itemid + ) + )); + return $response['result']; + } +} diff --git a/public/js/pages/DeviceMonitoringCongestion/DeviceMonitoringCongestion.js b/public/js/pages/DeviceMonitoringCongestion/DeviceMonitoringCongestion.js new file mode 100644 index 000000000..0a2d83b09 --- /dev/null +++ b/public/js/pages/DeviceMonitoringCongestion/DeviceMonitoringCongestion.js @@ -0,0 +1,41 @@ +Vue.component('device-monitoring-congestion', { + //language=Vue + template: ` + + + +
    Letzte Abfragezeit: {{ window.moment.utc(window['TT_CONFIG']['CONGESTION_DATA']['fileCreateTime']).add(1, 'hours').format('DD.MM.YYYY HH:mm:ss') }}
    + + + + + + + + +
    + `, + data() { + return { + window: window, + DeviceTableConfig: { + key: 'DeviceMonitoringCongestion', + tableHeader: 'Device Monitoring - Congestion', + defaultPageSize: 25, + headers: [ + {text: 'Hostname', key: 'hostname', sortable: true, class: 'text-nowrap'}, + {text: 'IP-Adresse', key: 'ip', filter: 'search', class: 'text-center'}, + {text: 'Name', key: 'name', filter: 'search', class: 'text-center'}, + {text: 'Höchster Wert', key: 'highestValue', filter: 'search', class: 'text-center'}, + {text: 'Zeit', key: 'highestValueTime', filter: 'search', class: 'text-center'}, + {text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9}, + ], + }, + } + } +}) \ No newline at end of file diff --git a/scripts/monitoring/run-device-congestion-cache.php b/scripts/monitoring/run-device-congestion-cache.php new file mode 100644 index 000000000..f51c54941 --- /dev/null +++ b/scripts/monitoring/run-device-congestion-cache.php @@ -0,0 +1,21 @@ +#!/usr/bin/php +id); +define("INTERNAL_USER_USERNAME", $me->username); + +$DeviceMonitoringController = new DeviceMonitoringController(false); + +$DeviceMonitoringController->getCongestionData(); \ No newline at end of file