Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SLA #710

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open

SLA #710

Prev Previous commit
Next Next commit
SLA: Use sla models for generating host/service reports
yhabteab committed Feb 22, 2023
commit c393637c1ceea0beff40087bdfb3da80225f3125
28 changes: 1 addition & 27 deletions library/Icingadb/ProvidedHook/Reporting/HostSlaReport.php
Original file line number Diff line number Diff line change
@@ -5,12 +5,8 @@
namespace Icinga\Module\Icingadb\ProvidedHook\Reporting;

use Icinga\Application\Icinga;
use Icinga\Module\Icingadb\Model\Host;
use Icinga\Module\Reporting\ReportData;
use Icinga\Module\Icingadb\ProvidedHook\Reporting\Common\ReportData;
use Icinga\Module\Reporting\ReportRow;
use Icinga\Module\Reporting\Timerange;
use ipl\Sql\Expression;
use ipl\Stdlib\Filter\Rule;

use function ipl\I18n\t;

@@ -43,26 +39,4 @@ protected function createReportRow($row)
->setDimensions([$row->display_name])
->setValues([(float) $row->sla]);
}

protected function fetchSla(Timerange $timerange, Rule $filter = null)
{
$sla = Host::on($this->getDb())
->columns([
'display_name',
'sla' => new Expression(sprintf(
"get_sla_ok_percent(%s, NULL, '%s', '%s')",
'host.id',
$timerange->getStart()->format('Uv'),
$timerange->getEnd()->format('Uv')
))
]);

$this->applyRestrictions($sla);

if ($filter !== null) {
$sla->filter($filter);
}

return $sla;
}
}
38 changes: 2 additions & 36 deletions library/Icingadb/ProvidedHook/Reporting/ServiceSlaReport.php
Original file line number Diff line number Diff line change
@@ -5,12 +5,8 @@
namespace Icinga\Module\Icingadb\ProvidedHook\Reporting;

use Icinga\Application\Icinga;
use Icinga\Module\Icingadb\Model\Service;
use Icinga\Module\Reporting\ReportData;
use Icinga\Module\Icingadb\ProvidedHook\Reporting\Common\ReportData;
use Icinga\Module\Reporting\ReportRow;
use Icinga\Module\Reporting\Timerange;
use ipl\Sql\Expression;
use ipl\Stdlib\Filter\Rule;

use function ipl\I18n\t;

@@ -35,38 +31,8 @@ protected function createReportData()

protected function createReportRow($row)
{
if ($row->sla === null) {
return null;
}

return (new ReportRow())
->setDimensions([$row->host->display_name, $row->display_name])
->setDimensions([$row->host_display_name, $row->display_name])
->setValues([(float) $row->sla]);
}

protected function fetchSla(Timerange $timerange, Rule $filter = null)
{
$sla = Service::on($this->getDb())
->columns([
'host.display_name',
'display_name',
'sla' => new Expression(sprintf(
"get_sla_ok_percent(%s, %s, '%s', '%s')",
'service.host_id',
'service.id',
$timerange->getStart()->format('Uv'),
$timerange->getEnd()->format('Uv')
))
]);

$sla->resetOrderBy()->orderBy('host.display_name')->orderBy('display_name');

$this->applyRestrictions($sla);

if ($filter !== null) {
$sla->filter($filter);
}

return $sla;
}
}
123 changes: 7 additions & 116 deletions library/Icingadb/ProvidedHook/Reporting/SlaReport.php
Original file line number Diff line number Diff line change
@@ -4,19 +4,16 @@

namespace Icinga\Module\Icingadb\ProvidedHook\Reporting;

use DateInterval;
use DatePeriod;
use Icinga\Module\Icingadb\Common\Auth;
use Icinga\Module\Icingadb\Common\Database;
use Icinga\Module\Icingadb\ProvidedHook\Reporting\Common\ReportData;
use Icinga\Module\Icingadb\ProvidedHook\Reporting\Common\SlaReportUtils;
use Icinga\Module\Icingadb\Widget\EmptyState;
use Icinga\Module\Reporting\Hook\ReportHook;
use Icinga\Module\Reporting\ReportData;
use Icinga\Module\Reporting\ReportRow;
use Icinga\Module\Reporting\Timerange;
use ipl\Html\Form;
use ipl\Html\Html;
use ipl\Stdlib\Filter\Rule;
use ipl\Web\Filter\QueryString;

use function ipl\I18n\t;

@@ -27,12 +24,13 @@ abstract class SlaReport extends ReportHook
{
use Auth;
use Database;
use SlaReportUtils;

/** @var float If an SLA value is lower than the threshold, it is considered not ok */
const DEFAULT_THRESHOLD = 99.5;
protected const DEFAULT_THRESHOLD = 99.5;

/** @var int The amount of decimal places for the report result */
const DEFAULT_REPORT_PRECISION = 2;
protected const DEFAULT_REPORT_PRECISION = 2;

/**
* Create and return a {@link ReportData} container
@@ -51,113 +49,6 @@ abstract protected function createReportData();
*/
abstract protected function createReportRow($row);

/**
* Fetch SLA according to specified time range and filter
*
* @param Timerange $timerange
* @param Rule|null $filter
*
* @return iterable
*/
abstract protected function fetchSla(Timerange $timerange, Rule $filter = null);

protected function fetchReportData(Timerange $timerange, array $config = null)
{
$rd = $this->createReportData();
$rows = [];

$filter = trim((string) $config['filter']) ?: '*';
$filter = $filter !== '*' ? QueryString::parse($filter) : null;

if (isset($config['breakdown']) && $config['breakdown'] !== 'none') {
switch ($config['breakdown']) {
case 'day':
$interval = new DateInterval('P1D');
$format = 'Y-m-d';
$boundary = 'tomorrow midnight';

break;
case 'week':
$interval = new DateInterval('P1W');
$format = 'Y-\WW';
$boundary = 'monday next week midnight';

break;
case 'month':
$interval = new DateInterval('P1M');
$format = 'Y-m';
$boundary = 'first day of next month midnight';

break;
}

$dimensions = $rd->getDimensions();
$dimensions[] = ucfirst($config['breakdown']);
$rd->setDimensions($dimensions);

foreach ($this->yieldTimerange($timerange, $interval, $boundary) as list($start, $end)) {
foreach ($this->fetchSla(new Timerange($start, $end), $filter) as $row) {
$row = $this->createReportRow($row);

if ($row === null) {
continue;
}

$dimensions = $row->getDimensions();
$dimensions[] = $start->format($format);
$row->setDimensions($dimensions);

$rows[] = $row;
}
}
} else {
foreach ($this->fetchSla($timerange, $filter) as $row) {
$rows[] = $this->createReportRow($row);
}
}

$rd->setRows($rows);

return $rd;
}

/**
* Yield start and end times that recur at the specified interval over the given time range
*
* @param Timerange $timerange
* @param DateInterval $interval
* @param string|null $boundary English text datetime description for calculating bounds to get
* calendar days, weeks or months instead of relative times according to interval
*
* @return \Generator
*/
protected function yieldTimerange(Timerange $timerange, DateInterval $interval, $boundary = null)
{
$start = clone $timerange->getStart();
$end = clone $timerange->getEnd();
$oneSecond = new DateInterval('PT1S');

if ($boundary !== null) {
$intermediate = (clone $start)->modify($boundary);
if ($intermediate < $end) {
yield [clone $start, $intermediate->sub($oneSecond)];

$start->modify($boundary);
}
}

$period = new DatePeriod($start, $interval, $end, DatePeriod::EXCLUDE_START_DATE);

foreach ($period as $date) {
/** @var \DateTime $date */
yield [$start, (clone $date)->sub($oneSecond)];

$start = $date;
}

yield [$start, $end];
}

public function initConfigForm(Form $form)
{
$form->addElement('text', 'filter', [
@@ -192,7 +83,7 @@ public function initConfigForm(Form $form)

public function getData(Timerange $timerange, array $config = null)
{
return $this->fetchReportData($timerange, $config);
return $this->fetchReportData($timerange->getStart(), $timerange->getEnd(), $config);
}

public function getHtml(Timerange $timerange, array $config = null)
@@ -241,7 +132,6 @@ public function getHtml(Timerange $timerange, array $config = null)

// We only have one average
$average = $data->getAverages()[0];

if ($average < $threshold) {
$slaClass = 'nok';
} else {
@@ -274,6 +164,7 @@ public function getHtml(Timerange $timerange, array $config = null)
]
);

// echo '<pre>' . nl2br($data->getTimelineString()) . '</pre>';
return $table;
}
}