Add delete from logs ajax capability. Make the clear button use it. Fixes #2620

pull/2715/head
Isaac Connor 2019-10-02 15:39:04 -04:00
parent e37870d983
commit e4b5052fb4
3 changed files with 124 additions and 76 deletions

View File

@ -4,6 +4,61 @@
# These are the valid columns that you can filter on.
$filterFields = array( 'Component', 'ServerId', 'Pid', 'Level', 'File', 'Line' );
function buildLogQuery($action) {
$minTime = isset($_REQUEST['minTime'])?$_REQUEST['minTime']:NULL;
$maxTime = isset($_REQUEST['maxTime'])?$_REQUEST['maxTime']:NULL;
$limit = 100;
if ( isset($_REQUEST['limit']) ) {
if ( ( !is_integer($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) {
ZM\Error('Invalid value for limit ' . $_REQUEST['limit']);
} else {
$limit = $_REQUEST['limit'];
}
}
$sortField = 'TimeKey';
if ( isset($_REQUEST['sortField']) ) {
if ( !in_array($_REQUEST['sortField'], $filterFields) and ( $_REQUEST['sortField'] != 'TimeKey' ) ) {
ZM\Error('Invalid sort field ' . $_REQUEST['sortField']);
} else {
$sortField = $_REQUEST['sortField'];
}
}
$sortOrder = (isset($_REQUEST['sortOrder']) and ($_REQUEST['sortOrder'] == 'asc')) ? 'asc' : 'desc';
$filter = isset($_REQUEST['filter']) ? $_REQUEST['filter'] : array();
$sql = $action.' FROM Logs';
$where = array();
$values = array();
if ( $minTime ) {
$where[] = 'TimeKey > ?';
$values[] = $minTime;
} elseif ( $maxTime ) {
$where[] = 'TimeKey < ?';
$values[] = $maxTime;
}
foreach ( $filter as $field=>$value ) {
if ( ! in_array($field, $filterFields) ) {
ZM\Error("$field is not in valid filter fields");
continue;
}
if ( $field == 'Level' ){
$where[] = $field.' <= ?';
$values[] = $value;
} else {
$where[] = $field.' = ?';
$values[] = $value;
}
}
if ( count($where) )
$sql.= ' WHERE '.join(' AND ', $where);
$sql .= ' ORDER BY '.$sortField.' '.$sortOrder.' LIMIT '.$limit;
return array('sql'=>$sql, 'values'=>$values);
}
switch ( $_REQUEST['task'] ) {
case 'create' :
{
@ -21,17 +76,33 @@ switch ( $_REQUEST['task'] ) {
$levels = array_flip(ZM\Logger::$codes);
if ( !isset($levels[$_POST['level']]) )
ZM\Panic("Unexpected logger level '".$_POST['level']."'");
ZM\Panic('Unexpected logger level '.$_POST['level']);
$level = $levels[$_POST['level']];
ZM\Logger::fetch()->logPrint($level, $string, $file, $line);
}
ajaxResponse();
break;
}
case 'delete' :
{
if ( !canEdit('System') )
ajaxError('Insufficient permissions to delete log entries');
$query = buildLogQuery('DELETE');
$result = dbQuery($query['sql'], $query['values']);
ajaxResponse( array(
'result'=>'Ok',
'deleted'=>$result->rowCount(),
) );
}
case 'query' :
{
if ( !canView('System') )
ajaxError('Insufficient permissions to view log entries');
$total = dbFetchOne('SELECT count(*) AS Total FROM Logs', 'Total');
$query = buildLogQuery('SELECT *');
$servers = ZM\Server::find();
$servers_by_Id = array();
@ -40,59 +111,10 @@ switch ( $_REQUEST['task'] ) {
$servers_by_Id[$server->Id()] = $server;
}
$minTime = isset($_REQUEST['minTime'])?$_REQUEST['minTime']:NULL;
$maxTime = isset($_REQUEST['maxTime'])?$_REQUEST['maxTime']:NULL;
$limit = 100;
if ( isset($_REQUEST['limit']) ) {
if ( ( !is_integer($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) {
ZM\Error('Invalid value for limit ' . $_REQUEST['limit']);
} else {
$limit = $_REQUEST['limit'];
}
}
$sortField = 'TimeKey';
if ( isset($_REQUEST['sortField']) ) {
if ( !in_array($_REQUEST['sortField'], $filterFields) and ( $_REQUEST['sortField'] != 'TimeKey' ) ) {
ZM\Error("Invalid sort field " . $_REQUEST['sortField']);
} else {
$sortField = $_REQUEST['sortField'];
}
}
$sortOrder = (isset($_REQUEST['sortOrder']) and ($_REQUEST['sortOrder'] == 'asc')) ? 'asc' : 'desc';
$filter = isset($_REQUEST['filter']) ? $_REQUEST['filter'] : array();
$total = dbFetchOne('SELECT count(*) AS Total FROM Logs', 'Total');
$sql = 'SELECT * FROM Logs';
$where = array();
$values = array();
if ( $minTime ) {
$where[] = 'TimeKey > ?';
$values[] = $minTime;
} elseif ( $maxTime ) {
$where[] = 'TimeKey < ?';
$values[] = $maxTime;
}
foreach ( $filter as $field=>$value ) {
if ( ! in_array($field, $filterFields) ) {
ZM\Error("$field is not in valid filter fields");
continue;
}
if ( $field == 'Level' ){
$where[] = $field.' <= ?';
$values[] = $value;
} else {
$where[] = $field.' = ?';
$values[] = $value;
}
}
$options = array();
if ( count($where) )
$sql.= ' WHERE '.join(' AND ', $where);
$sql .= ' ORDER BY '.$sortField.' '.$sortOrder.' LIMIT '.$limit;
$logs = array();
foreach ( dbFetchAll($sql, NULL, $values) as $log ) {
$options = array();
foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $log ) {
$log['DateTime'] = strftime('%Y-%m-%d %H:%M:%S', intval($log['TimeKey']));
#Warning("TimeKey: " . $log['TimeKey'] . 'Intval:'.intval($log['TimeKey']).' DateTime:'.$log['DateTime']);

View File

@ -1,4 +1,4 @@
var logParms = "view=request&request=log&task=query";
var logParms = 'view=request&request=log&task=query';
var logReq = new Request.JSON( {url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: logResponse} );
var logTimer = undefined;
var logTable = undefined;
@ -148,7 +148,7 @@ function logResponse( respObj ) {
function refreshLog() {
options = {};
logTable.empty();
$j('#logTable tbody').empty();
firstLoad = true;
maxLogTime = 0;
minLogTime = 0;
@ -163,15 +163,41 @@ function expandLog() {
fetchPrevLogs();
}
function clearResponse() {
refreshLog();
}
function clearError() {
}
function clearLog() {
logReq.cancel();
var clearParms = 'view=request&request=log&task=delete';
var clearReq = new Request.JSON( {url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: clearResponse} );
var tbody = $(logTable).getElement( 'tbody' );
var rows = tbody.getElements( 'tr' );
if ( rows ) {
var minTime = rows[0].getElement('td').get('text');
clearParms += "&minTime="+encodeURIComponent(minTime);
var maxTime = rows[rows.length-1].getElement('td').get('text');
clearParms += "&maxTime="+encodeURIComponent(maxTime);
}
var form = $('logForm');
if ( ! form ) {
console.log("Nothing found for #logForm?");
} else {
clearReq.send(clearParms+"&"+form.toQueryString());
}
if ( 0 ) {
minLogTime = 0;
logCount = 0;
logTimeout = maxSampleTime;
displayLimit = initialDisplayLimit;
$('displayLogs').set('text', logCount);
options = {};
logTable.empty();
$j('#logTable tbody').empty();
}
}
function filterLog() {
@ -181,7 +207,7 @@ function filterLog() {
var selector = $('filter['+field+']');
if ( ! selector ) {
if ( window.console && window.console.log ) {
window.console.log("No selector found for " + field );
window.console.log('No selector found for ' + field);
}
return;
}
@ -215,14 +241,14 @@ function exportResponse( response ) {
function exportFail( request ) {
$('exportLog').unspin();
$('exportErrorText').set('text', request.status+" / "+request.statusText );
$('exportErrorText').set('text', request.status+' / '+request.statusText );
$('exportError').show();
Error( "Export request failed: "+request.status+" / "+request.statusText );
Error('Export request failed: '+request.status+' / '+request.statusText );
}
function exportRequest() {
var form = $('exportForm');
$('exportErrorText').set('text', "" );
$('exportErrorText').set('text', '');
$('exportError').hide();
if ( form.validate() ) {
var exportParms = "view=request&request=log&task=export";
@ -256,7 +282,7 @@ function updateFilterSelectors() {
var selector = $('filter['+key+']');
if ( ! selector ) {
if ( window.console && window.console.log ) {
window.console.log("No selector found for " + key );
window.console.log('No selector found for ' + key);
}
return;
}
@ -300,12 +326,12 @@ function initPage() {
}
);
logTable.addEvent( 'sort', function( tbody, index ) {
var header = tbody.getParent( 'table' ).getElement( 'thead' );
var columns = header.getElement( 'tr' ).getElements( 'th' );
var header = tbody.getParent('table').getElement('thead');
var columns = header.getElement('tr').getElements('th');
var column = columns[index];
sortReversed = column.hasClass( 'table-th-sort-rev' );
sortReversed = column.hasClass('table-th-sort-rev');
if ( logCount > displayLimit ) {
var rows = tbody.getElements( 'tr' );
var rows = tbody.getElements('tr');
var startIndex;
if ( sortReversed ) {
startIndex = displayLimit;
@ -322,12 +348,12 @@ function initPage() {
);
exportFormValidator = new Form.Validator.Inline($('exportForm'), {
useTitles: true,
warningPrefix: "",
errorPrefix: ""
warningPrefix: '',
errorPrefix: ''
});
new Asset.css( "css/spinner.css" );
new Asset.css('css/spinner.css');
fetchNextLogs();
}
// Kick everything off
window.addEventListener( 'DOMContentLoaded', initPage );
window.addEventListener('DOMContentLoaded', initPage);

View File

@ -56,41 +56,41 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
</table>
</div> <!--header-->
<div id="content">
<form id="logForm" name="logForm" method="post" action="?">
<div id="filters">
<table class="table-condensed">
<tr class="row">
<td class="col">
<?php echo translate('Component') ?>
<label><?php echo translate('Component') ?></label>
<select class="form-control chosen" id="filter[Component]" data-on-change="filterLog"><option value="">-----</option></select>
</td>
<td class="col">
<?php echo translate('Server') ?>
<label><?php echo translate('Server') ?></label>
<select class="form-control chosen" id="filter[ServerId]" data-on-change="filterLog"><option value="">-----</option></select>
</td>
<td class="col">
<?php echo translate('Pid') ?>
<label><?php echo translate('Pid') ?></label>
<select class="form-control chosen" id="filter[Pid]" data-on-change="filterLog"><option value="">-----</option></select>
</td>
</tr>
<tr class="row">
<td class="col">
<?php echo translate('Level') ?>
<label><?php echo translate('Level') ?></label>
<select class="form-control chosen" id="filter[Level]" data-on-change="filterLog"><option value="">---</option></select>
</td>
<td class="col">
<?php echo translate('File') ?>
<label><?php echo translate('File') ?></label>
<select class="form-control chosen" id="filter[File]" data-on-change="filterLog"><option value="">------</option></select>
</td>
<td class="col">
<?php echo translate('Line') ?>
<label><?php echo translate('Line') ?></label>
<select class="form-control chosen" id="filter[Line]" data-on-change="filterLog"><option value="">----</option></select>
</td>
</tr>
</table>
<button type="reset" data-on-click="resetLog"><?php echo translate('Reset') ?></button>
</div>
<form name="logForm" method="post" action="?">
<input type="hidden" name="view" value="<?php echo $view ?>"/>
<table id="logTable" class="major">
<thead class="thead-highlight">