Activity/DeploymentLogTable: completely refactored

This commit is contained in:
Thomas Gelf 2017-07-19 18:45:12 +02:00
parent 547deb209c
commit 37b3a8da82
4 changed files with 228 additions and 304 deletions

View File

@ -1,205 +0,0 @@
<?php
namespace Icinga\Module\Director\Tables;
use Icinga\Module\Director\Util;
use Icinga\Module\Director\Web\Table\QuickTable;
class ActivityLogTable extends QuickTable
{
protected $filters = array();
protected $lastDeployedId;
protected $extraParams = array();
protected $lastDay;
protected $columnCount;
protected $isUsEnglish;
protected $searchColumns = array(
//'log_message'
'author',
'object_name',
'object_type',
'action',
);
public function getColumns()
{
return array(
'log_message' => "'[' || l.author || '] ' || l.action_name || ' '"
. " || REPLACE(l.object_type, 'icinga_', '')"
. " || ' \"' || l.object_name || '\"'",
'author' => 'l.author',
'action' => 'l.action_name',
'object_name' => 'l.object_name',
'object_type' => 'l.object_type',
'id' => 'l.id',
'change_time' => 'l.change_time',
'ts_change_time' => 'UNIX_TIMESTAMP(l.change_time)',
);
}
public function setLastDeployedId($id)
{
$this->lastDeployedId = $id;
return $this;
}
protected function listTableClasses()
{
if (Util::hasPermission('director/showconfig')) {
return array_merge(array('activity-log'), parent::listTableClasses());
} else {
return array('simple', 'common-table', 'activity-log');
}
}
public function render()
{
$data = $this->fetchData();
$htm = '<table' . $this->createClassAttribute($this->listTableClasses()) . '>' . "\n"
. $this->renderTitles($this->getTitles());
foreach ($data as $row) {
$htm .= $this->renderRow($row);
}
return $htm . "</tbody>\n</table>\n";
}
protected function renderRow($row)
{
$row->change_time = strftime('%H:%M:%S', $row->ts_change_time);
return $this->renderDayIfNew($row) . parent::renderRow($row);
}
protected function getRowClasses($row)
{
$action = 'action-' . $row->action. ' ';
if ($row->id > $this->lastDeployedId) {
return $action . 'undeployed';
} else {
return $action . 'deployed';
}
}
protected function getActionUrl($row)
{
if (Util::hasPermission('director/showconfig')) {
return $this->url(
'director/show/activitylog',
array_merge(array('id' => $row->id), $this->extraParams)
);
} else {
return false;
}
}
public function getTitles()
{
$view = $this->view();
return array(
// 'author' => $view->translate('Author'),
'log_message' => $view->translate('Action'),
'change_time' => $view->translate('Timestamp'),
);
}
protected function renderTitles($row)
{
return '';
}
protected function isUsEnglish()
{
if ($this->isUsEnglish === null) {
$this->isUsEnglish = in_array(setlocale(LC_ALL, 0), array('en_US.UTF-8', 'C'));
}
return $this->isUsEnglish;
}
/**
* @param object $row
* @return string
*/
protected function renderDayIfNew($row)
{
$view = $this->view();
if ($this->isUsEnglish()) {
$day = date('l, jS F Y', (int) $row->ts_change_time);
} else {
$day = strftime('%A, %e. %B, %Y', (int) $row->ts_change_time);
}
if ($this->lastDay === $day) {
return '';
}
if ($this->lastDay === null) {
$htm = "<thead>\n <tr>\n";
} else {
$htm = "</tbody>\n<thead>\n <tr>\n";
}
if ($this->columnCount === null) {
$this->columnCount = count($this->getTitles());
}
$htm .= '<th colspan="' . $this->columnCount . '">' . $view->escape($day) . '</th>' . "\n";
if ($this->lastDay === null) {
$htm .= " </tr>\n";
} else {
$htm .= " </tr>\n</thead>\n";
}
$this->lastDay = $day;
return $htm . "<tbody>\n";
}
public function filterObject($type, $name)
{
$this->filters[] = array('l.object_type = ?', $type);
$this->filters[] = array('l.object_name = ?', $name);
$this->extraParams = array(
'type' => $type,
'name' => $name,
);
return $this;
}
public function getBaseQuery()
{
$query = $this->db()->select()->from(
array('l' => 'director_activity_log'),
array()
)->order('change_time DESC')->order('id DESC');
foreach ($this->filters as $filter) {
$query->where($filter[0], $filter[1]);
}
return $query;
}
public function count()
{
$db = $this->db();
$sub = clone($this->getBaseQuery());
$sub->reset('order')->columns('l.id')->limit(2501);
$this->applyFiltersToQuery($sub);
$query = $db->select()->from(
array('s' => $sub),
array('c' => 'COUNT(*)')
);
return $db->fetchOne($query);
}
}

View File

@ -1,99 +0,0 @@
<?php
namespace Icinga\Module\Director\Tables;
use Icinga\Module\Director\Web\Table\QuickTable;
class DeploymentLogTable extends QuickTable
{
protected $activeStageName;
public function setActiveStageName($name)
{
$this->activeStageName = $name;
return $this;
}
protected function listTableClasses()
{
return array_merge(array('deployment-log'), parent::listTableClasses());
}
protected function getRowClasses($row)
{
if ($row->startup_succeeded === 'y') {
$classes = array('succeeded');
} elseif ($row->startup_succeeded === 'n') {
$classes = array('failed');
} elseif ($row->stage_collected === null) {
$classes = array('pending');
} elseif ($row->dump_succeeded === 'y') {
$classes = array('sent');
} else {
// TODO: does this ever be stored?
$classes = array('notsent');
}
if ($this->activeStageName !== null
&& $row->stage_name === $this->activeStageName
) {
$classes[] = 'running';
}
return $classes;
}
public function getColumns()
{
$db = $this->connection();
$columns = array(
'id' => 'l.id',
'peer_identity' => 'l.peer_identity',
'identifier' => "l.peer_identity || ' (' || SUBSTRING(",
'start_time' => 'l.start_time',
'stage_collected' => 'l.stage_collected',
'dump_succeeded' => 'l.dump_succeeded',
'stage_name' => 'l.stage_name',
'startup_succeeded' => 'l.startup_succeeded',
'checksum' => $db->dbHexFunc('c.checksum'),
'duration' => "l.duration_dump || 'ms'",
);
if ($this->connection->isPgsql()) {
$columns['identifier'] .= $columns['checksum'] . ' FROM 1 FOR 7)';
} else {
$columns['identifier'] .= $columns['checksum'] . ', 1, 7)';
}
$columns['identifier'] .= " || ')'";
return $columns;
}
protected function getActionUrl($row)
{
return $this->url('director/deployment', array('id' => $row->id));
}
public function getTitles()
{
$view = $this->view();
return array(
'identifier' => $view->translate('Icinga Node'),
'start_time' => $view->translate('Time'),
);
}
public function getBaseQuery()
{
return $this->db()->select()->from(
array('l' => 'director_deployment_log'),
array()
)->joinLeft(
array('c' => 'director_generated_config'),
'c.checksum = l.config_checksum',
array()
)->order('l.start_time DESC');
}
}

View File

@ -0,0 +1,140 @@
<?php
namespace Icinga\Module\Director\Web\Table;
use Icinga\Module\Director\Util;
use ipl\Html\BaseElement;
use ipl\Html\Link;
use ipl\Web\Table\ZfQueryBasedTable;
class ActivityLogTable extends ZfQueryBasedTable
{
protected $filters = [];
protected $lastDeployedId;
protected $extraParams = [];
protected $columnCount;
/** @var BaseElement */
protected $currentHead;
/** @var BaseElement */
protected $currentBody;
protected $searchColumns = array(
'l.author',
'l.object_name',
'l.object_type',
'l.action_name',
);
public function assemble()
{
$this->attributes()->add('class', 'activity-log');
$this->fetchRows();
}
public function setLastDeployedId($id)
{
$this->lastDeployedId = $id;
return $this;
}
public function renderRow($row)
{
$this->splitByDay($row->ts_change_time);
$action = 'action-' . $row->action. ' ';
if ($row->id > $this->lastDeployedId) {
$action .= 'undeployed';
} else {
$action .= 'deployed';
}
return $this::tr([
$this::td($this->makeLink($row))->setSeparator(' '),
$this::td(strftime('%H:%M:%S', $row->ts_change_time))
])->addAttributes(['class' => $action]);
}
protected function makeLink($row)
{
if (Util::hasPermission('director/showconfig')) {
// Later on replacing, service_set -> serviceset
$type = $row->object_type;
$name = $row->object_name;
if (substr($type, 0, 7) === 'icinga_') {
$type = substr($type, 7);
}
// multi column key :(
if ($type === 'service') {
$object = "\"$name\"";
} else {
$object = Link::create(
"\"$name\"",
'director/' . str_replace('_', '', $type),
['name' => $name],
['title' => $this->translate('Jump to this object')]
);
}
return [
'[' . $row->author . ']',
Link::create(
$row->action,
'director/show/activitylog',
array_merge(['id' => $row->id], $this->extraParams),
['title' => $this->translate('Show details related to this change')]
),
str_replace('_', ' ', $type),
$object
];
} else {
return $row->log_message;
}
}
public function filterObject($type, $name)
{
$this->filters[] = ['l.object_type = ?', $type];
$this->filters[] = ['l.object_name = ?', $name];
$this->extraParams = [
'type' => $type,
'name' => $name,
];
return $this;
}
public function getColumns()
{
return [
'log_message' => "'[' || l.author || '] ' || l.action_name || ' '"
. " || REPLACE(l.object_type, 'icinga_', '')"
. " || ' \"' || l.object_name || '\"'",
'author' => 'l.author',
'action' => 'l.action_name',
'object_name' => 'l.object_name',
'object_type' => 'l.object_type',
'id' => 'l.id',
'change_time' => 'l.change_time',
'ts_change_time' => 'UNIX_TIMESTAMP(l.change_time)',
];
}
public function prepareQuery()
{
$query = $this->db()->select()->from(
['l' => 'director_activity_log'],
$this->getColumns()
)->order('change_time DESC')->order('id DESC')->limit(100);
foreach ($this->filters as $filter) {
$query->where($filter[0], $filter[1]);
}
return $query;
}
}

View File

@ -0,0 +1,88 @@
<?php
namespace Icinga\Module\Director\Web\Table;
use ipl\Html\Link;
use ipl\Web\Table\ZfQueryBasedTable;
class DeploymentLogTable extends ZfQueryBasedTable
{
protected $activeStageName;
public function setActiveStageName($name)
{
$this->activeStageName = $name;
return $this;
}
public function assemble()
{
$this->attributes()->add('class', 'deployment-log');
parent::assemble();
}
public function renderRow($row)
{
$this->splitByDay($row->start_time);
$shortSum = substr(bin2hex($row->config_checksum), 0, 7);
$tr = $this::tr([
$this::td(Link::create(
[$row->peer_identity, " ($shortSum)"],
'director/deployment',
['id' => $row->id]
)),
$this::td(strftime('%H:%M:%S', $row->start_time))
])->addAttributes(['class' => $this->getMyRowClasses($row)]);
return $tr;
}
protected function getMyRowClasses($row)
{
if ($row->startup_succeeded === 'y') {
$classes = ['succeeded'];
} elseif ($row->startup_succeeded === 'n') {
$classes = ['failed'];
} elseif ($row->stage_collected === null) {
$classes = ['pending'];
} elseif ($row->dump_succeeded === 'y') {
$classes = ['sent'];
} else {
// TODO: does this ever be stored?
$classes = ['notsent'];
}
if ($this->activeStageName !== null
&& $row->stage_name === $this->activeStageName
) {
$classes[] = 'running';
}
return $classes;
}
public function getColumns()
{
$columns = [
'id' => 'l.id',
'peer_identity' => 'l.peer_identity',
'start_time' => 'UNIX_TIMESTAMP(l.start_time)',
'stage_collected' => 'l.stage_collected',
'dump_succeeded' => 'l.dump_succeeded',
'stage_name' => 'l.stage_name',
'startup_succeeded' => 'l.startup_succeeded',
'config_checksum' => 'l.config_checksum',
];
return $columns;
}
public function prepareQuery()
{
return $this->db()->select()->from(
array('l' => 'director_deployment_log'),
$this->getColumns()
)->order('l.start_time DESC')->limit(100);
}
}