Unify time interval formatting (#14733)

* Unify time interval formatting
Use carbon for formatting, it supports locales.

* fix style

* remove baseline exceptions

* fixes found by lint
This commit is contained in:
Tony Murray
2022-12-15 15:52:53 -06:00
committed by GitHub
parent d091788f28
commit 1d3440b943
10 changed files with 39 additions and 155 deletions

View File

@@ -38,7 +38,6 @@ use LibreNMS\Enum\AlertState;
use LibreNMS\Exceptions\AlertTransportDeliveryException;
use LibreNMS\Polling\ConnectivityHelper;
use LibreNMS\Util\Time;
use Log;
class RunAlerts
{
@@ -104,7 +103,7 @@ class RunAlerts
$obj['features'] = $device->features;
$obj['location'] = (string) $device->location;
$obj['uptime'] = $device->uptime;
$obj['uptime_short'] = Time::formatInterval($device->uptime, 'short');
$obj['uptime_short'] = Time::formatInterval($device->uptime, true);
$obj['uptime_long'] = Time::formatInterval($device->uptime);
$obj['description'] = $device->purpose;
$obj['notes'] = $device->notes;
@@ -149,7 +148,7 @@ class RunAlerts
}
}
}
$obj['elapsed'] = $this->timeFormat(time() - strtotime($alert['time_logged']));
$obj['elapsed'] = Time::formatInterval(time() - strtotime($alert['time_logged']), true) ?: 'none';
if (! empty($extra['diff'])) {
$obj['diff'] = $extra['diff'];
}
@@ -170,7 +169,7 @@ class RunAlerts
dbUpdate(['details' => gzcompress(json_encode($id['details']), 9)], 'alert_log', 'id = ?', [$alert['id']]);
$obj['title'] = $template->title_rec ?: 'Device ' . $obj['display'] . ' recovered from ' . ($alert['name'] ?: $alert['rule']);
$obj['elapsed'] = $this->timeFormat(strtotime($alert['time_logged']) - strtotime($id['time_logged']));
$obj['elapsed'] = Time::formatInterval(strtotime($alert['time_logged']) - strtotime($id['time_logged']), true) ?: 'none';
$obj['id'] = $id['id'];
foreach ($extra['rule'] as $incident) {
$i++;
@@ -200,36 +199,6 @@ class RunAlerts
return $obj;
}
/**
* Format Elapsed Time
*
* @param int $secs Seconds elapsed
* @return string
*/
public function timeFormat($secs)
{
$bit = [
'y' => round($secs / 31556926) % 12,
'w' => round($secs / 604800) % 52,
'd' => round($secs / 86400) % 7,
'h' => round($secs / 3600) % 24,
'm' => round($secs / 60) % 60,
's' => $secs % 60,
];
$ret = [];
foreach ($bit as $k => $v) {
if ($v > 0) {
$ret[] = $v . $k;
}
}
if (empty($ret)) {
return 'none';
}
return join(' ', $ret);
}
public function clearStaleAlerts()
{
$sql = 'SELECT `alerts`.`id` AS `alert_id`, `devices`.`hostname` AS `hostname` FROM `alerts` LEFT JOIN `devices` ON `alerts`.`device_id`=`devices`.`device_id` RIGHT JOIN `alert_rules` ON `alerts`.`rule_id`=`alert_rules`.`id` WHERE `alerts`.`state`!=' . AlertState::CLEAR . ' AND `devices`.`hostname` IS NULL';

View File

@@ -25,9 +25,12 @@
namespace LibreNMS\Util;
use Carbon\CarbonInterface;
use Carbon\CarbonInterval;
class Time
{
public static function legacyTimeSpecToSecs($description)
public static function legacyTimeSpecToSecs(string $description): int
{
$conversion = [
'now' => 0,
@@ -46,91 +49,38 @@ class Time
'twoyear' => 63072000,
];
return isset($conversion[$description]) ? $conversion[$description] : 0;
return $conversion[$description] ?? 0;
}
public static function formatInterval($interval, $format = 'long')
{
$result = '';
$data = [
'years' => 31536000,
'days' => 86400,
'hours' => 3600,
'minutes' => 60,
'seconds' => 1,
];
foreach ($data as $k => $v) {
if ($interval >= $v) {
$diff = floor($interval / $v);
$result .= " $diff";
if ($format == 'short') {
$result .= substr($k, 0, 1);
}
if ($format != 'short' && $diff > 1) {
$result .= ' ' . $k;
}
if ($format != 'short' && $diff < 2) {
$result .= ' ' . substr($k, 0, -1);
}
$interval -= $v * $diff;
}
}
return $result;
}
/*
* @param integer seconds of a time period
* @return string human readably time period
/**
* Format seconds as a human readable interval. Negative seconds will say "ago".
*/
public static function humanTime($s)
public static function formatInterval(?int $seconds, bool $short = false, ?int $parts = null): string
{
$ret = [];
if ($s >= 86400) {
$d = floor($s / 86400);
$s -= $d * 86400;
if ($d == 1) {
$ret[] = $d . ' day';
} else {
$ret[] = $d . ' days';
}
if ($seconds == 0) {
return '';
}
if ($s >= 3600) {
$h = floor($s / 3600);
$s -= $h * 3600;
if ($h == 1) {
$ret[] = $h . ' hour';
} else {
$ret[] = $h . ' hours';
}
}
$parts = $parts ?? ($short ? 3 : -1);
if ($s >= 60) {
$m = floor($s / 60);
$s -= $m * 60;
if ($m == 1) {
$ret[] = $m . ' minute';
} else {
$ret[] = $m . ' minutes';
try {
// handle negative seconds correctly
if ($seconds < 0) {
return CarbonInterval::seconds($seconds)->invert()->cascade()->forHumans([
'syntax' => CarbonInterface::DIFF_RELATIVE_TO_NOW,
'parts' => $parts,
'short' => $short,
]);
}
}
if ($s > 0) {
if ($s == 1) {
$ret[] = $s . ' second';
} else {
$ret[] = $s . ' seconds';
}
return CarbonInterval::seconds($seconds)->cascade()->forHumans([
'syntax' => CarbonInterface::DIFF_ABSOLUTE,
'parts' => $parts,
'short' => $short,
]);
} catch (\Exception) {
return '';
}
return implode(' ,', $ret);
}
/**

View File

@@ -155,7 +155,7 @@ class DeviceController extends TableController
'metrics' => $this->getMetrics($device),
'hardware' => Rewrite::ciscoHardware($device),
'os' => $this->getOsText($device),
'uptime' => (! $device->status && ! $device->last_polled) ? __('Never polled') : Time::formatInterval($device->status ? $device->uptime : $device->last_polled->diffInSeconds(), 'short'),
'uptime' => (! $device->status && ! $device->last_polled) ? __('Never polled') : Time::formatInterval($device->status ? $device->uptime : $device->last_polled->diffInSeconds(), true),
'location' => $this->getLocation($device),
'actions' => view('device.actions', ['actions' => $this->getActions($device)])->__toString(),
'device_id' => $device->device_id,

View File

@@ -223,7 +223,7 @@ class GraphController extends WidgetController
$data = $settings;
$data['params'] = $params;
$data['dimensions'] = $request->get('dimensions');
$data['from'] = Carbon::now()->subSeconds(Time::legacyTimeSpecToSecs($settings['graph_range']))->timestamp;
$data['from'] = Carbon::now()->subSeconds(Time::legacyTimeSpecToSecs($settings['graph_range'] ?? ''))->timestamp;
$data['to'] = Carbon::now()->timestamp;
return view('widgets.graph', $data);

View File

@@ -4,6 +4,7 @@ namespace App\Observers;
use App\Models\Eventlog;
use App\Models\Stp;
use LibreNMS\Util\Time;
class StpObserver
{
@@ -24,7 +25,7 @@ class StpObserver
}
if ($stp->isDirty('rootPort')) {
$time = \LibreNMS\Util\Time::formatInterval($stp->timeSinceTopologyChange);
$time = Time::formatInterval((int) $stp->timeSinceTopologyChange);
Eventlog::log('STP topology changed after: ' . $time, $stp->device_id, 'stp', 4);
}
}

View File

@@ -5,7 +5,6 @@ use LibreNMS\Config;
use LibreNMS\Exceptions\InvalidIpException;
use LibreNMS\Util\Clean;
use LibreNMS\Util\IP;
use LibreNMS\Util\Time;
echo "<div class='row'>
<div class='col-md-12'>
@@ -104,17 +103,17 @@ if ($device['sysContact']) {
if (! empty($device['inserted']) && preg_match('/^0/', $device['inserted']) == 0) {
$inserted_text = 'Device Added';
$inserted = (Time::formatInterval(time() - strtotime($device['inserted'])) . ' ago');
$inserted = (\LibreNMS\Util\Time::formatInterval(-(time() - strtotime($device['inserted']))));
echo "<div class='row'><div class='col-sm-4'>$inserted_text</div><div class='col-sm-8' title='$inserted_text on " . $device['inserted'] . "'>$inserted</div></div>";
}
if (! empty($device['last_discovered'])) {
$last_discovered_text = 'Last Discovered';
$last_discovered = (empty($device['last_discovered']) ? 'Never' : Time::formatInterval(time() - strtotime($device['last_discovered'])) . ' ago');
$last_discovered = (empty($device['last_discovered']) ? 'Never' : \LibreNMS\Util\Time::formatInterval(-(time() - strtotime($device['last_discovered']))));
echo "<div class='row'><div class='col-sm-4'>$last_discovered_text</div><div class='col-sm-8' title='$last_discovered_text at " . $device['last_discovered'] . "'>$last_discovered</div></div>";
}
$uptime = (Time::formatInterval($device['status'] ? $device['uptime'] : time() - strtotime($device['last_polled'])));
$uptime = (\LibreNMS\Util\Time::formatInterval($device['status'] ? $device['uptime'] : time() - strtotime($device['last_polled'])));
$uptime_text = ($device['status'] ? 'Uptime' : 'Downtime');
if ($uptime) {

View File

@@ -13,7 +13,7 @@ $colour_area = '8B8BEB44';
$colour_area_max = 'cc9999';
$line_text = \LibreNMS\Util\Time::humanTime($vars['duration']);
$line_text = \LibreNMS\Util\Time::formatInterval($vars['duration'], parts: 1);
$graph_title .= '::' . $line_text;

View File

@@ -16,7 +16,7 @@ foreach ($duration_list as $duration) {
$graph_array['type'] = 'device_' . $graph_type;
$graph_array['duration'] = $duration['duration'];
$human_duration = \LibreNMS\Util\Time::humanTime($duration['duration']);
$human_duration = \LibreNMS\Util\Time::formatInterval($duration['duration'], parts: 1);
$graph_title = DeviceCache::get($device['device_id'])->displayName() . ' - ' . $human_duration;
echo "<div class='panel panel-default'>

View File

@@ -24,7 +24,7 @@ foreach (dbFetchRows('SELECT * FROM availability WHERE device_id = ?', [$device[
}
$avail = \LibreNMS\Device\Availability::availability($device, $row['duration']);
$human_time = \LibreNMS\Util\Time::humanTime($row['duration']);
$human_time = \LibreNMS\Util\Time::formatInterval($row['duration'], parts: 1);
$rrd_name = ['availability', $row['duration']];
$rrd_def = RrdDefinition::make()

View File

@@ -5630,41 +5630,6 @@ parameters:
count: 1
path: LibreNMS/Util/StringHelpers.php
-
message: "#^Method LibreNMS\\\\Util\\\\Time\\:\\:formatInterval\\(\\) has no return type specified\\.$#"
count: 1
path: LibreNMS/Util/Time.php
-
message: "#^Method LibreNMS\\\\Util\\\\Time\\:\\:formatInterval\\(\\) has parameter \\$format with no type specified\\.$#"
count: 1
path: LibreNMS/Util/Time.php
-
message: "#^Method LibreNMS\\\\Util\\\\Time\\:\\:formatInterval\\(\\) has parameter \\$interval with no type specified\\.$#"
count: 1
path: LibreNMS/Util/Time.php
-
message: "#^Method LibreNMS\\\\Util\\\\Time\\:\\:humanTime\\(\\) has no return type specified\\.$#"
count: 1
path: LibreNMS/Util/Time.php
-
message: "#^Method LibreNMS\\\\Util\\\\Time\\:\\:humanTime\\(\\) has parameter \\$s with no type specified\\.$#"
count: 1
path: LibreNMS/Util/Time.php
-
message: "#^Method LibreNMS\\\\Util\\\\Time\\:\\:legacyTimeSpecToSecs\\(\\) has no return type specified\\.$#"
count: 1
path: LibreNMS/Util/Time.php
-
message: "#^Method LibreNMS\\\\Util\\\\Time\\:\\:legacyTimeSpecToSecs\\(\\) has parameter \\$description with no type specified\\.$#"
count: 1
path: LibreNMS/Util/Time.php
-
message: "#^Method LibreNMS\\\\Util\\\\Url\\:\\:escapeBothQuotes\\(\\) has no return type specified\\.$#"
count: 1