diff --git a/root/app/www/public/ajax/logs.php b/root/app/www/public/ajax/logs.php index 949ebb2..3a27f4a 100644 --- a/root/app/www/public/ajax/logs.php +++ b/root/app/www/public/ajax/logs.php @@ -20,7 +20,7 @@ require '../loader.php'; if ($_POST['m'] == 'viewAppLog') { - getLog($_POST['log'], 1, true); + getLog($_POST['log'], 1, true, $_POST['activeTab'] ?: '#access'); } if ($_POST['m'] == 'viewLog') { @@ -30,3 +30,7 @@ if ($_POST['m'] == 'deleteLog') { unlink($_POST['log']); } + +if ($_POST['m'] == 'refreshLogList') { + renderLogList(); +} diff --git a/root/app/www/public/functions/logger.php b/root/app/www/public/functions/logger.php index a08eccb..0714258 100644 --- a/root/app/www/public/functions/logger.php +++ b/root/app/www/public/functions/logger.php @@ -119,7 +119,51 @@ function getLogs() return $list; } -function getLog($logfile, $page = 1, $app = false) +function renderLogList() +{ + $logList = getLogs(); + $index = 0; + + foreach ($logList['system'] as $group => $groupLogs) { + ?> +

+ + $logs) { + if ($app == 'system') { + continue; + } + + ?> +

+ + exec('wc -l "' . $logfile . '"')); $logLines = intval(trim($logLines)); @@ -141,11 +188,11 @@ function getLog($logfile, $page = 1, $app = false) ?>
-
+
getStarrInterfaceNameFromId($proxiedApp['starrAppDetails']['starr']); ?> -
+

Endpoint usage ( endpoint)

$methods) { diff --git a/root/app/www/public/js/logs.js b/root/app/www/public/js/logs.js index 30464b3..f4e5f5a 100644 --- a/root/app/www/public/js/logs.js +++ b/root/app/www/public/js/logs.js @@ -1,3 +1,98 @@ +const LOG_REFRESH_INTERVAL = 3000; +const LOG_LIST_REFRESH_INTERVAL = 10000; + +let currentLog = null; + +//-- Polls tick() every interval ms, waits for the previous request to finish and pauses while the browser tab is hidden +function createPoller(interval, tick) +{ + let timer = null; + let running = false; + + function schedule() + { + clearTimeout(timer); + timer = running && !document.hidden ? setTimeout(run, interval) : null; + } + + function run() + { + $.when(tick()).always(schedule); + } + + document.addEventListener('visibilitychange', schedule); + + return { + start: function () { + running = true; + schedule(); + }, + stop: function () { + running = false; + schedule(); + }, + toggle: function () { + running ? this.stop() : this.start(); + return running; + } + }; +} +// ------------------------------------------------------------------------------------------- +function setRefreshButton(button, enabled) +{ + $(button).find('i').toggleClass('fa-sync', enabled).toggleClass('fa-pause', !enabled); + $(button).attr('title', enabled ? 'Pause auto-refresh' : 'Resume auto-refresh'); +} +// ------------------------------------------------------------------------------------------- +function keepScroll(container, update) +{ + const containerScroll = $(container).scrollTop(); + const windowScroll = window.scrollY; + + update(); + + $(container).scrollTop(containerScroll); + window.scrollTo(0, windowScroll); +} +// ------------------------------------------------------------------------------------------- +const logPoller = createPoller(LOG_REFRESH_INTERVAL, function () { + if (!currentLog) { + return; + } + + return $.post('ajax/logs.php', { m: 'viewLog', log: currentLog.log, page: currentLog.page, index: currentLog.index }, function (resultData) { + keepScroll('#log-viewer', function () { + $('#log-viewer').html(resultData); + }); + }); +}); +// ------------------------------------------------------------------------------------------- +const logListPoller = createPoller(LOG_LIST_REFRESH_INTERVAL, function () { + return $.post('ajax/logs.php', { m: 'refreshLogList' }, function (resultData) { + $('#log-sidebar').html(resultData); + + if (currentLog) { + $('#app-log-' + currentLog.index).addClass('text-info'); + } + }); +}); +// ------------------------------------------------------------------------------------------- +let appLog = null; + +const appLogPoller = createPoller(LOG_REFRESH_INTERVAL, function () { + if (!appLog || !$('#viewAppLog').is(':visible')) { + return; + } + + const activeTab = $('#viewAppLog .nav-link.active').attr('href') || '#access'; + + return $.post('ajax/logs.php', { m: 'viewAppLog', key: appLog.key, log: appLog.log, activeTab: activeTab }, function (resultData) { + keepScroll('#viewAppLog .modal-body', function () { + $('#viewAppLog .modal-body').html(resultData); + }); + }); +}); +// ------------------------------------------------------------------------------------------- function viewLog(log, index, page = 1) { loadingStart(); @@ -6,42 +101,59 @@ function viewLog(log, index, page = 1) $('[id^=app-log-]').removeClass('text-info'); $('#app-log-' + index).addClass('text-info'); - $.ajax({ - type: 'POST', - url: 'ajax/logs.php', - data: '&m=viewLog&log=' + log + '&page=' + page + '&index=' + index, - success: function (resultData) { - $('#log-viewer').html(resultData); - loadingStop(); - } + currentLog = { log: log, index: index, page: page }; + + $.post('ajax/logs.php', { m: 'viewLog', log: log, page: page, index: index }, function (resultData) { + $('#log-viewer').html(resultData); + loadingStop(); }); } // ------------------------------------------------------------------------------------------- +function toggleLogAutoRefresh() +{ + const enabled = logPoller.toggle(); + + enabled ? logListPoller.start() : logListPoller.stop(); + setRefreshButton('#auto-refresh-toggle', enabled); + $('#auto-refresh-status').text(enabled ? LOG_REFRESH_INTERVAL / 1000 + 's' : 'off'); +} +// ------------------------------------------------------------------------------------------- function viewAppLog(log, key, appName) { loadingStart(); - $.ajax({ - type: 'POST', - url: 'ajax/logs.php', - data: '&m=viewAppLog&key=' + key + '&log=' + log, - success: function (resultData) { - dialogOpen({ - id: 'viewAppLog', - title: 'Access log viewer: ' + appName + ' (filter: ' + key + ')', - size: 'xxl', - body: resultData, - onOpen: function() { - loadingStop(); - } - }); - } + appLog = { log: log, key: key }; + + $.post('ajax/logs.php', { m: 'viewAppLog', key: key, log: log }, function (resultData) { + dialogOpen({ + id: 'viewAppLog', + title: 'Access log viewer: ' + appName + ' (filter: ' + key + ')' + + ' ', + size: 'xxl', + body: resultData, + onOpen: function () { + loadingStop(); + appLogPoller.start(); + }, + onClose: function () { + appLogPoller.stop(); + appLog = null; + } + }); }); } // ------------------------------------------------------------------------------------------- +function toggleAppLogAutoRefresh() +{ + setRefreshButton('#app-log-refresh-toggle', appLogPoller.toggle()); +} +// ------------------------------------------------------------------------------------------- function deleteLog(log) { if (confirm('Are you sure you want to delete the log: ' + log + '?')) { + logPoller.stop(); + $.ajax({ type: 'POST', url: 'ajax/logs.php', @@ -53,3 +165,9 @@ function deleteLog(log) } } // ------------------------------------------------------------------------------------------- +$(document).ready(function () { + if ($('#log-sidebar').length) { + logPoller.start(); + logListPoller.start(); + } +}); diff --git a/root/app/www/public/pages/logs.php b/root/app/www/public/pages/logs.php index 700de32..2018e90 100644 --- a/root/app/www/public/pages/logs.php +++ b/root/app/www/public/pages/logs.php @@ -15,51 +15,19 @@ exit('Invalid session, refresh the page'); } -$logList = getLogs(); ?>
- $groupLogs) { - ?> -

-
    -
  • - - () -
    -
  • -
- $logs) { - if ($app == 'system') { - continue; - } - - ?> -

-
    -
  • - - () -
    -
  • -
- +
+ Auto-refresh: 3s + +
+
+ +