Gunnar Beutner a66a1a4729 Refactor the timeSincePrefix and timeUntilPrefix functions
Instead of having two separate functions to get the prefix
and the formatted time interval the new functions return
both the prefix and the time interval.

refs #5981
2014-05-29 13:03:10 +02:00

335 lines
10 KiB
PHP

<?php
namespace Icinga\Module\Monitoring\Clicommands;
use Icinga\Module\Monitoring\Backend;
use Icinga\Module\Monitoring\Cli\CliUtils;
use Icinga\Util\Format;
use Icinga\Cli\Command;
use Icinga\File\Csv;
use Icinga\Module\Monitoring\Plugin\PerfdataSet;
use Exception;
/**
* Icinga monitoring objects
*
* This module is your interface to the Icinga monitoring application.
*/
class ListCommand extends Command
{
protected $backend;
protected $dumpSql;
protected $defaultActionName = 'status';
public function init()
{
$this->backend = Backend::createBackend($this->params->shift('backend'));
$this->dumpSql = $this->params->shift('showsql');
}
protected function getQuery($table, $columns)
{
$limit = $this->params->shift('limit');
$format = $this->params->shift('format');
if ($format !== null) {
if ($this->params->has('columns')) {
$columnParams = preg_split(
'/,/',
$this->params->shift('columns')
);
$columns = array();
foreach ($columnParams as $col) {
if (false !== ($pos = strpos($col, '='))) {
$columns[substr($col, 0, $pos)] = substr($col, $pos + 1);
} else {
$columns[] = $col;
}
}
}
}
$query = $this->backend->select()->from($table, $columns);
if ($limit) {
$query->limit($limit, $this->params->shift('offset'));
}
foreach ($this->params->getParams() as $col => $filter) {
$query->where($col, $filter);
}
// $query->applyFilters($this->params->getParams());
if ($this->dumpSql) {
echo wordwrap($query->dump(), 72);
exit;
}
if ($format !== null) {
$this->showFormatted($query, $format, $columns);
}
return $query;
}
protected function showFormatted($query, $format, $columns)
{
switch($format) {
case 'json':
echo json_encode($query->fetchAll());
break;
case 'csv':
Csv::fromQuery($query)->dump();
break;
default:
preg_match_all('~\$([a-z0-9_-]+)\$~', $format, $m);
$words = array();
foreach ($columns as $key => $col) {
if (is_numeric($key)) {
if (in_array($col, $m[1])) {
$words[] = $col;
}
} else {
if (in_array($key, $m[1])) {
$words[] = $key;
}
}
}
foreach ($query->fetchAll() as $row) {
$output = $format;
foreach ($words as $word) {
$output = preg_replace(
'~\$' . $word . '\$~',
$row->{$word},
$output
);
}
echo $output . "\n";
}
}
exit;
}
/**
* List and filter monitored objects
*
* This command allows you to search and visualize your monitored objects in
* different ways.
*
* USAGE
*
* icingacli monitoring list [<type>] [options]
*
* OPTIONS
*
* --verbose Show detailled output
* --showsql Dump generated SQL query (DB backend only)
*
* --format <csv|json|<custom>>
* Dump columns in the given format. <custom> format allows $column$
* placeholders, e.g. --format '$host$: $service$'
*
* --<column> [filter]
* Filter given column by optional filter. Boolean (1/0) columns are
* true if no filter value is given.
*
* EXAMPLES
*
* icingacli monitoring list --unhandled
* icingacli monitoring list --host local* --service *disk*
* icingacli monitoring list --format '$host$: $service$'
*/
public function statusAction()
{
$columns = array(
'host_name',
'host_state',
'host_output',
'host_handled',
'host_acknowledged',
'host_in_downtime',
'service_description',
'service_state',
'service_acknowledged',
'service_in_downtime',
'service_handled',
'service_output',
'service_perfdata',
'service_last_state_change'
);
$query = $this->getQuery('status', $columns)
->order('host_name');
echo $this->renderStatusQuery($query);
}
protected function renderStatusQuery($query)
{
$out = '';
$last_host = null;
$screen = $this->screen;
$utils = new CliUtils($screen);
$maxCols = $screen->getColumns();
$rows = $query->fetchAll();
$count = $query->count();
$count = count($rows);
for ($i = 0; $i < $count; $i++) {
$row = & $rows[$i];
$utils->setHostState($row->host_state);
if (! array_key_exists($i + 1, $rows)
|| $row->host_name !== $rows[$i + 1]->host_name
) {
$lastService = true;
} else {
$lastService = false;
}
$hostUnhandled = ! ($row->host_state == 0 || $row->host_handled);
if ($row->host_name !== $last_host) {
if (isset($row->service_description)) {
$out .= "\n";
}
$hostTxt = $utils->shortHostState();
if ($hostUnhandled) {
$out .= $utils->hostStateBackground(
sprintf(' %s ', $utils->shortHostState())
);
} else {
$out .= sprintf(
'%s %s ',
$utils->hostStateBackground(' '),
$utils->shortHostState()
);
}
$out .= sprintf(
" %s%s: %s\n",
$screen->underline($row->host_name),
$screen->colorize($utils->objectStateFlags('host', $row), 'lightblue'),
$row->host_output
);
if (isset($row->services_ok)) {
$out .= sprintf(
"%d services, %d problems (%d unhandled), %d OK\n",
$row->services_cnt,
$row->services_problem,
$row->services_problem_unhandled,
$row->services_ok
);
}
}
$last_host = $row->host_name;
if (! isset($row->service_description)) {
continue;
}
$utils->setServiceState($row->service_state);
$serviceUnhandled = ! (
$row->service_state == 0 || $row->service_handled
);
if ($lastService) {
$straight = ' ';
$leaf = '└';
} else {
$straight = '│';
$leaf = '├';
}
$out .= $utils->hostStateBackground(' ');
if ($serviceUnhandled) {
$out .= $utils->serviceStateBackground(
sprintf(' %s ', $utils->shortServiceState())
);
$emptyBg = ' ';
$emptySpace = '';
} else {
$out .= sprintf(
'%s %s ',
$utils->serviceStateBackground(' '),
$utils->shortServiceState()
);
$emptyBg = ' ';
$emptySpace = ' ';
}
$emptyLine = "\n"
. $utils->hostStateBackground(' ')
. $utils->serviceStateBackground($emptyBg)
. $emptySpace
. ' ' . $straight . ' ';
$perf = '';
try {
$pset = PerfdataSet::fromString($row->service_perfdata);
$perfs = array();
foreach ($pset as $perfName => $p) {
if ($percent = $p->getPercentage()) {
if ($percent < 0 || $percent > 100) {
continue;
}
$perfs[] = ' '
. $perfName
. ': '
. $this->getPercentageSign($percent)
. ' '
. number_format($percent, 2, ',', '.')
. '%';
}
}
if (! empty($perfs)) {
$perf = ', ' . implode($perfs);
}
// TODO: fix wordwarp, then remove this line:
$perf = '';
} catch (Exception $e) {
// Ignoring perfdata errors right now, we could show some hint
}
$wrappedOutput = wordwrap(
preg_replace('~\@{3,}~', '@@@', $row->service_output),
$maxCols - 13
) . "\n";
$out .= sprintf(
" %1s─ %s%s (%s %s)",
$leaf,
$screen->underline($row->service_description),
$screen->colorize($utils->objectStateFlags('service', $row) . $perf, 'lightblue'),
Format::prefixedTimeSince($row->service_last_state_change, true)
);
if ($this->isVerbose) {
$out .= $emptyLine . preg_replace(
'/\n/',
$emptyLine,
$wrappedOutput
) . "\n";
} else {
$out .= "\n";
}
}
$out .= "\n";
return $out;
}
protected function getPercentageSign($percent)
{
$circles = array(
0 => '○',
15 => '◔',
40 => '◑',
65 => '◕',
90 => '●',
);
$last = $circles[0];
foreach ($circles as $cur => $circle) {
if ($percent < $cur) {
return $last;
}
$last = $circle;
}
}
}