mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Cleanup and optimize the availability widget (#14329)
* Cleanup and optimize the availability widget Default sort is display name Sort applies to services too (services always last) May need to refresh the page to get new css * style * We don't need request (lint fix) * Wrong service field name
This commit is contained in:
@@ -25,11 +25,14 @@
|
||||
|
||||
namespace App\Http\Controllers\Widgets;
|
||||
|
||||
use App\Models\AlertSchedule;
|
||||
use App\Models\Device;
|
||||
use App\Models\DeviceGroup;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Util\Url;
|
||||
|
||||
class AvailabilityMapController extends WidgetController
|
||||
{
|
||||
@@ -44,7 +47,7 @@ class AvailabilityMapController extends WidgetController
|
||||
'color_only_select' => 0,
|
||||
'show_disabled_and_ignored' => 0,
|
||||
'mode_select' => 0,
|
||||
'order_by' => Config::get('webui.availability_map_sort_status') ? 'status' : 'hostname',
|
||||
'order_by' => Config::get('webui.availability_map_sort_status') ? 'status' : 'display-name',
|
||||
'device_group' => null,
|
||||
];
|
||||
}
|
||||
@@ -53,20 +56,8 @@ class AvailabilityMapController extends WidgetController
|
||||
{
|
||||
$data = $this->getSettings();
|
||||
|
||||
$devices = [];
|
||||
$device_totals = [];
|
||||
$services = [];
|
||||
$services_totals = [];
|
||||
|
||||
$mode = $data['mode_select'];
|
||||
if ($mode == 0 || $mode == 2) {
|
||||
[$devices, $device_totals] = $this->getDevices($request);
|
||||
}
|
||||
if ($mode > 0) {
|
||||
[$services, $services_totals] = $this->getServices($request);
|
||||
}
|
||||
|
||||
$data['device'] = Device::first();
|
||||
[$devices, $device_totals] = $this->getDevices();
|
||||
[$services, $services_totals] = $this->getServices();
|
||||
|
||||
$data['devices'] = $devices;
|
||||
$data['device_totals'] = $device_totals;
|
||||
@@ -81,142 +72,206 @@ class AvailabilityMapController extends WidgetController
|
||||
return view('widgets.settings.availability-map', $this->getSettings(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
private function getDevices(Request $request)
|
||||
private function getDevices(): array
|
||||
{
|
||||
$settings = $this->getSettings();
|
||||
|
||||
if ($settings['mode_select'] == 1) { // services only
|
||||
return [[], []];
|
||||
}
|
||||
|
||||
// filter for by device group or show all
|
||||
if ($settings['device_group']) {
|
||||
$device_query = DeviceGroup::find($settings['device_group'])->devices()->hasAccess($request->user());
|
||||
$device_query = DeviceGroup::find($settings['device_group'])->devices()->hasAccess(Auth::user());
|
||||
} else {
|
||||
$device_query = Device::hasAccess($request->user());
|
||||
$device_query = Device::hasAccess(Auth::user());
|
||||
}
|
||||
|
||||
if (! $settings['show_disabled_and_ignored']) {
|
||||
$device_query->isNotDisabled();
|
||||
}
|
||||
$devices = $device_query->select(['devices.device_id', 'hostname', 'sysName', 'display', 'status', 'uptime', 'last_polled', 'disabled', 'disable_notify', 'location_id'])->get();
|
||||
$devices = $device_query->select(['devices.device_id', 'hostname', 'sysName', 'display', 'status', 'uptime', 'last_polled', 'disabled', 'ignore'])->get();
|
||||
|
||||
// process status
|
||||
$uptime_warn = Config::get('uptime_warning', 86400);
|
||||
$uptime_warn = (int) Config::get('uptime_warning', 86400);
|
||||
$check_maintenance = AlertSchedule::isActive()->exists(); // check if any maintenance schedule is active
|
||||
$totals = ['warn' => 0, 'up' => 0, 'down' => 0, 'maintenance' => 0, 'ignored' => 0, 'disabled' => 0];
|
||||
$data = [];
|
||||
|
||||
// add another field for the selected device label
|
||||
$label_type = $settings['color_only_select'];
|
||||
|
||||
foreach ($devices as $device) {
|
||||
$row = ['device' => $device];
|
||||
if ($device->disabled) {
|
||||
$totals['disabled']++;
|
||||
$row['stateName'] = 'disabled';
|
||||
$row['labelClass'] = 'blackbg';
|
||||
} elseif ($device->disable_notify) {
|
||||
$totals['ignored']++;
|
||||
$row['stateName'] = 'alert-dis';
|
||||
$row['labelClass'] = 'label-default';
|
||||
} elseif ($device->status == 1) {
|
||||
if (($device->uptime < $uptime_warn) && ($device->uptime != 0)) {
|
||||
$totals['warn']++;
|
||||
$row['stateName'] = 'warn';
|
||||
$row['labelClass'] = 'label-warning';
|
||||
} else {
|
||||
$totals['up']++;
|
||||
$row['stateName'] = 'up';
|
||||
$row['labelClass'] = 'label-success';
|
||||
}
|
||||
} else {
|
||||
$totals['down']++;
|
||||
$row['stateName'] = 'down';
|
||||
$row['labelClass'] = 'label-danger';
|
||||
}
|
||||
// parse state and count
|
||||
[$state_name, $class] = $this->parseDeviceState($device, $uptime_warn);
|
||||
$totals[$state_name]++;
|
||||
|
||||
if ($device->isUnderMaintenance()) {
|
||||
$row['labelClass'] = 'label-default';
|
||||
if ($check_maintenance && $device->isUnderMaintenance()) {
|
||||
$class = 'label-default';
|
||||
$totals['maintenance']++;
|
||||
}
|
||||
|
||||
if ($label_type == 1) {
|
||||
$row['label'] = null;
|
||||
} elseif ($label_type == 4) {
|
||||
$row['label'] = strtolower($device->shortDisplayName());
|
||||
} elseif ($label_type == 2) {
|
||||
$row['label'] = strtolower($device->hostname);
|
||||
} elseif ($label_type == 3) {
|
||||
$row['label'] = strtolower($device->sysName);
|
||||
} else {
|
||||
$row['label'] = $device->status;
|
||||
if ($settings['type'] == 1) {
|
||||
$class = "availability-map-oldview-box-$state_name";
|
||||
}
|
||||
|
||||
$data[] = $row;
|
||||
$data[] = [
|
||||
'status' => $device->status,
|
||||
'link' => Url::deviceUrl($device),
|
||||
'tooltip' => $this->getDeviceTooltip($device, $state_name),
|
||||
'label' => $this->getDeviceLabel($device, $state_name), // add another field for the selected label
|
||||
'labelClass' => $class,
|
||||
];
|
||||
}
|
||||
|
||||
// now apply sorting, depending on the selected device label
|
||||
$order_by = $settings['order_by'];
|
||||
|
||||
if ($order_by == 'status') {
|
||||
usort($data, function ($l, $r) {
|
||||
$retval = $l['device']->status <=> $r['device']->status;
|
||||
if ($retval == 0) {
|
||||
$retval = $l['label'] <=> $r['label'];
|
||||
}
|
||||
|
||||
return $retval;
|
||||
});
|
||||
} elseif ($order_by == 'label') {
|
||||
usort($data, function ($l, $r) {
|
||||
return $l['label'] <=> $r['label'];
|
||||
});
|
||||
}
|
||||
$this->sort($data);
|
||||
|
||||
return [$data, $totals];
|
||||
}
|
||||
|
||||
private function getServices($request)
|
||||
private function getServices(): array
|
||||
{
|
||||
$settings = $this->getSettings();
|
||||
|
||||
// filter for by device group or show all
|
||||
if ($settings['device_group']) {
|
||||
$services_query = DeviceGroup::find($settings['device_group'])->services()->hasAccess($request->user());
|
||||
} else {
|
||||
$services_query = Service::hasAccess($request->user());
|
||||
if ($settings['mode_select'] == 0) { // devices only
|
||||
return [[], []];
|
||||
}
|
||||
|
||||
if ($settings['order_by'] == 'status') {
|
||||
$services_query->orderBy('service_status', 'DESC')->orderBy('service_type');
|
||||
} elseif ($settings['order_by'] == 'hostname') {
|
||||
$services_query->leftJoin('devices', 'services.device_id', 'devices.device_id')->orderBy('hostname')->orderBy('service_type');
|
||||
// filter for by device group or show all
|
||||
if ($settings['device_group']) {
|
||||
$services_query = DeviceGroup::find($settings['device_group'])->services()->hasAccess(Auth::user());
|
||||
} else {
|
||||
$services_query = Service::hasAccess(Auth::user());
|
||||
}
|
||||
$services = $services_query->with(['device' => function ($query) {
|
||||
$query->select(['devices.device_id', 'hostname', 'sysName']);
|
||||
}])->select(['service_id', 'services.device_id', 'service_type', 'service_desc', 'service_status'])->get();
|
||||
|
||||
$services = $services_query->with([
|
||||
'device' => function ($query) {
|
||||
$query->select(['devices.device_id', 'hostname', 'sysName', 'display']);
|
||||
},
|
||||
])->select(['service_id', 'services.device_id', 'service_type', 'service_name', 'service_desc', 'service_status'])->get();
|
||||
|
||||
// process status
|
||||
$totals = ['warn' => 0, 'up' => 0, 'down' => 0];
|
||||
$data = [];
|
||||
foreach ($services as $service) {
|
||||
$row = ['service' => $service];
|
||||
if ($service->service_status == 0) {
|
||||
$row['labelClass'] = 'label-success';
|
||||
$row['stateName'] = 'up';
|
||||
$totals['up']++;
|
||||
} elseif ($service->service_status == 1) {
|
||||
$row['labelClass'] = 'label-warning';
|
||||
$row['stateName'] = 'warn';
|
||||
$totals['warn']++;
|
||||
} else {
|
||||
$row['labelClass'] = 'label-danger';
|
||||
$row['stateName'] = 'down';
|
||||
$totals['down']++;
|
||||
[$state_name, $class] = $this->parseServiceState($service);
|
||||
$totals[$state_name]++;
|
||||
|
||||
if ($settings['type'] == 1) {
|
||||
$class = "availability-map-oldview-box-$state_name";
|
||||
}
|
||||
$data[] = $row;
|
||||
|
||||
$data[] = [
|
||||
'status' => $service->service_status,
|
||||
'link' => Url::deviceUrl($service->device),
|
||||
'tooltip' => $this->getServiceTooltip($service),
|
||||
'label' => $this->getServiceLabel($service, $state_name),
|
||||
'labelClass' => $class,
|
||||
];
|
||||
}
|
||||
|
||||
$this->sort($data);
|
||||
|
||||
return [$data, $totals];
|
||||
}
|
||||
|
||||
private function sort(array &$data): void
|
||||
{
|
||||
switch ($this->getSettings()['order_by']) {
|
||||
case 'status':
|
||||
usort($data, function ($l, $r) {
|
||||
return ($l['status'] <=> $r['status']) ?: strcasecmp($l['label'], $r['label']);
|
||||
});
|
||||
break;
|
||||
case 'label':
|
||||
usort($data, function ($l, $r) {
|
||||
return strcasecmp($l['label'], $r['label']);
|
||||
});
|
||||
break;
|
||||
default: // device display name (tooltip starts with the display name)
|
||||
usort($data, function ($l, $r) {
|
||||
return strcasecmp($l['tooltip'], $r['tooltip']) ?: strcasecmp($l['label'], $r['label']);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private function getDeviceLabel(Device $device, string $state_name): string
|
||||
{
|
||||
switch ($this->getSettings()['color_only_select']) {
|
||||
case 1:
|
||||
return '';
|
||||
case 4:
|
||||
return $device->shortDisplayName();
|
||||
case 2:
|
||||
return strtolower($device->hostname);
|
||||
case 3:
|
||||
return strtolower($device->sysName);
|
||||
default:
|
||||
return __($state_name);
|
||||
}
|
||||
}
|
||||
|
||||
private function getServiceLabel(Service $service, string $state_name): string
|
||||
{
|
||||
if ($this->getSettings()['color_only_select'] == 1) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $service->service_type . ' - ' . __($state_name);
|
||||
}
|
||||
|
||||
private function getDeviceTooltip(Device $device, string $state_name): string
|
||||
{
|
||||
$tooltip = $device->displayName();
|
||||
$time = $device->formatDownUptime(true);
|
||||
|
||||
if ($time) {
|
||||
$tooltip .= ' - ' . ($state_name == 'down' ? 'downtime ' : '') . $time;
|
||||
}
|
||||
|
||||
return $tooltip;
|
||||
}
|
||||
|
||||
private function getServiceTooltip(Service $service): string
|
||||
{
|
||||
$tooltip = $service->device->displayName() . ' [' . $service->service_type . ']';
|
||||
|
||||
$description = $service->service_name ?: $service->service_desc;
|
||||
if ($description) {
|
||||
$tooltip .= ' ' . $description;
|
||||
}
|
||||
|
||||
return $tooltip;
|
||||
}
|
||||
|
||||
private function parseDeviceState(Device $device, int $uptime_warn): array
|
||||
{
|
||||
if ($device->disabled) {
|
||||
return ['disabled', 'blackbg'];
|
||||
}
|
||||
|
||||
if ($device->ignore) {
|
||||
return ['ignored', 'label-default'];
|
||||
}
|
||||
|
||||
if ($device->status == 1) {
|
||||
if (($device->uptime < $uptime_warn) && ($device->uptime != 0)) {
|
||||
return ['warn', 'label-warning'];
|
||||
}
|
||||
|
||||
return ['up', 'label-success'];
|
||||
}
|
||||
|
||||
return ['down', 'label-danger'];
|
||||
}
|
||||
|
||||
private function parseServiceState(Service $service): array
|
||||
{
|
||||
if ($service->service_status == 0) {
|
||||
return ['up', 'label-success'];
|
||||
}
|
||||
|
||||
if ($service->service_status == 1) {
|
||||
return ['warn', 'label-warning'];
|
||||
}
|
||||
|
||||
return ['down', 'label-danger'];
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user