diff --git a/application/Graphing/Graphing.php b/application/Graphing/Graphing.php
new file mode 100644
index 000000000..845b3ea26
--- /dev/null
+++ b/application/Graphing/Graphing.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 indexAction() {
+ $this->layout()->set('additionalJS', ["plugins/chart.js/chart.4.4.6.js", "plugins/chart.js/chartjs-adapter-moment.min.js"]);
+ Helper::renderVue($this, "DeviceGraphing", $this->mod, []);
+ }
+
+
+ protected function dataAction() {
+ header('Content-Type: application/json');
+ $hostId = $this->request->hostId;
+ $hostInterfaceItems = $this->zabbix->getHostInterfaceItems($hostId, '');
+ // limit to 25 items
+ $hostInterfaceItems = array_slice($hostInterfaceItems, 0, 25);
+
+ $itemIds = array_map(function($item) {
+ return $item['itemid'];
+ }, $hostInterfaceItems);
+
+
+ $itemValues = $this->zabbix->getItemValues($itemIds, 1000);
+
+ $out = [];
+ foreach ($hostInterfaceItems as $item) {
+ $out[$item['itemid']] = [
+ 'name' => str_replace('Bits', 'Mbps', $item['name']),
+ 'units' => $item['units'],
+ 'values' => []
+ ];
+ }
+
+ foreach ($itemValues as $itemValue) {
+ $out[$itemValue['itemid']]['values'][] = [
+ 'clock' => $itemValue['clock'],
+ 'value' => $itemValue['value'] / 1000000
+ ];
+ }
+
+ // sort by name
+ uasort($out, function($a, $b) {
+ return strcmp($a['name'], $b['name']);
+ });
+
+
+ die(json_encode($out));
+ }
+}
\ No newline at end of file
diff --git a/lib/Zabbix/Zabbix.php b/lib/Zabbix/Zabbix.php
index 536519551..4578d60d3 100644
--- a/lib/Zabbix/Zabbix.php
+++ b/lib/Zabbix/Zabbix.php
@@ -46,13 +46,13 @@ class Zabbix {
return $response['result'];
}
- public function getItemValues($itemIds) {
+ public function getItemValues($itemIds, $limit = 15) {
$response = $this->zabbixRequest('history.get', array(
'itemids' => $itemIds,
'output' => 'extend',
'sortfield' => 'clock',
'sortorder' => 'DESC',
- 'limit' => 15
+ 'limit' => $limit
));
return $response['result'];
}
@@ -64,10 +64,13 @@ class Zabbix {
return $response['result'];
}
- public function getInterfaceItems($hostId, $interfaceName) {
+ public function getHostInterfaceItems($hostId) {
$response = $this->zabbixRequest('item.get', array(
'hostids' => $hostId,
- 'search' => array('name' => array($interfaceName, "Bits"))
+ 'output' => ['itemid','name_resolved', 'key_', 'units'],
+ 'search' => ['name' => ["Bits received", "Bits sent"]],
+ 'searchByAny' => true,
+ 'sortfield' => 'name'
));
return $response['result'];
}
diff --git a/public/js/pages/Device/Device.js b/public/js/pages/Device/Device.js
index a98023951..796b8c51e 100644
--- a/public/js/pages/Device/Device.js
+++ b/public/js/pages/Device/Device.js
@@ -77,7 +77,7 @@ Vue.component('DeviceTable', {
-
+
diff --git a/public/js/pages/DeviceGraphing/DeviceGraphing.js b/public/js/pages/DeviceGraphing/DeviceGraphing.js
new file mode 100644
index 000000000..9ce5dc5c5
--- /dev/null
+++ b/public/js/pages/DeviceGraphing/DeviceGraphing.js
@@ -0,0 +1,133 @@
+Vue.component('tt-graph', {
+ template: `
+
+{{ header }}
+
+
+