mirror of
https://github.com/gSpotx2f/ruantiblock_openwrt.git
synced 2026-05-13 22:20:59 +00:00
Minor improvements. luci-app-ruantiblock: updated log.
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
#
|
||||
# (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
|
||||
# (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-ruantiblock
|
||||
PKG_VERSION:=2.1.4
|
||||
PKG_VERSION:=2.1.5
|
||||
PKG_RELEASE:=1
|
||||
LUCI_TITLE:=LuCI support for ruantiblock
|
||||
LUCI_DEPENDS:=+ruantiblock
|
||||
|
||||
@@ -10,6 +10,7 @@ document.head.append(E('style', {'type': 'text/css'},
|
||||
--app-log-dark-font-color: #2e2e2e;
|
||||
--app-log-light-font-color: #fff;
|
||||
--app-log-debug-font-color: #737373;
|
||||
--app-log-raw-font-color: #737373;
|
||||
--app-log-emerg-color: #a93734;
|
||||
--app-log-alert: #ff7968;
|
||||
--app-log-crit: #fcc3bf;
|
||||
@@ -18,12 +19,14 @@ document.head.append(E('style', {'type': 'text/css'},
|
||||
--app-log-notice: #e3ffec;
|
||||
--app-log-info: rgba(0,0,0,0);
|
||||
--app-log-debug: #ebf6ff;
|
||||
--app-log-raw: #eee;
|
||||
--app-log-entries-count-border: #ccc;
|
||||
}
|
||||
:root[data-darkmode="true"] {
|
||||
--app-log-dark-font-color: #fff;
|
||||
--app-log-light-font-color: #fff;
|
||||
--app-log-debug-font-color: #e7e7e7;
|
||||
--app-log-raw-font-color: #aaa;
|
||||
--app-log-emerg-color: #960909;
|
||||
--app-log-alert: #eb5050;
|
||||
--app-log-crit: #dc7f79;
|
||||
@@ -32,6 +35,7 @@ document.head.append(E('style', {'type': 'text/css'},
|
||||
--app-log-notice: #007627;
|
||||
--app-log-info: rgba(0,0,0,0);
|
||||
--app-log-debug: #5986b1;
|
||||
--app-log-raw: #353535;
|
||||
--app-log-entries-count-border: #555;
|
||||
}
|
||||
#logWrapper {
|
||||
@@ -114,6 +118,16 @@ log-emerg td {
|
||||
.log-debug td {
|
||||
color: var(--app-log-debug-font-color) !important;
|
||||
}
|
||||
.log-raw {
|
||||
background-color: var(--app-log-raw) !important;
|
||||
color: var(--app-log-raw-font-color) !important;
|
||||
}
|
||||
.log-raw .td {
|
||||
color: var(--app-log-raw-font-color) !important;
|
||||
}
|
||||
.log-raw td {
|
||||
color: var(--app-log-raw-font-color) !important;
|
||||
}
|
||||
.log-highlight-item {
|
||||
background-color: #ffef00;
|
||||
color: #2e2e2e;
|
||||
@@ -168,25 +182,32 @@ return baseclass.extend({
|
||||
*
|
||||
* @property {string} viewName
|
||||
*/
|
||||
viewName : null,
|
||||
viewName : null,
|
||||
|
||||
/**
|
||||
* Page title.
|
||||
*
|
||||
* @property {string} title
|
||||
*/
|
||||
title : null,
|
||||
title : null,
|
||||
|
||||
/**
|
||||
* Enable auto refresh log.
|
||||
*
|
||||
* @property {bool} autoRefresh
|
||||
* @property {bool} enableAutoRefresh
|
||||
*/
|
||||
autoRefresh : false,
|
||||
enableAutoRefresh : false,
|
||||
|
||||
pollInterval : L.env.pollinterval,
|
||||
/**
|
||||
* Enable timestamp conversion.
|
||||
*
|
||||
* @property {bool} enableConvertTimestamp
|
||||
*/
|
||||
enableConvertTimestamp: false,
|
||||
|
||||
logFacilities : {
|
||||
pollInterval : L.env.pollinterval,
|
||||
|
||||
logFacilities : {
|
||||
'kern' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'kern')),
|
||||
'user' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'user')),
|
||||
'mail' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'mail')),
|
||||
@@ -211,7 +232,7 @@ return baseclass.extend({
|
||||
'local7' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'local7')),
|
||||
},
|
||||
|
||||
logLevels : {
|
||||
logLevels : {
|
||||
'emerg' : E('span', { 'class': 'zonebadge log-emerg' }, E('strong', 'Emergency')),
|
||||
'alert' : E('span', { 'class': 'zonebadge log-alert' }, E('strong', 'Alert')),
|
||||
'crit' : E('span', { 'class': 'zonebadge log-crit' }, E('strong', 'Critical')),
|
||||
@@ -246,13 +267,15 @@ return baseclass.extend({
|
||||
|
||||
autoRefreshValue : true,
|
||||
|
||||
isAutorefresh : true,
|
||||
autorefreshOn : true,
|
||||
|
||||
isHosts : false,
|
||||
logTimestampFlag : false,
|
||||
|
||||
isFacilities : false,
|
||||
logHostsFlag : false,
|
||||
|
||||
isLevels : false,
|
||||
logFacilitiesFlag : false,
|
||||
|
||||
logLevelsFlag : false,
|
||||
|
||||
logHosts : {},
|
||||
|
||||
@@ -266,7 +289,13 @@ return baseclass.extend({
|
||||
|
||||
totalLogLines : 0,
|
||||
|
||||
lastHash : null,
|
||||
logCols : [ '#', null, null, null, null, _('Message') ],
|
||||
|
||||
convertTimestampValue: false,
|
||||
|
||||
convertTimestampOn : false,
|
||||
|
||||
lastHash : null,
|
||||
|
||||
actionButtons : [],
|
||||
|
||||
@@ -283,6 +312,68 @@ return baseclass.extend({
|
||||
return (/^[0-9]+$/.test(value)) ? value : 0
|
||||
},
|
||||
|
||||
makeLogConvertTimestampSection() {
|
||||
if(!this.enableConvertTimestamp) {
|
||||
return '';
|
||||
};
|
||||
return E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', {
|
||||
'class': 'cbi-value-title',
|
||||
'for' : 'convertTimestamp',
|
||||
}, _('Date')),
|
||||
E('div', { 'class': 'cbi-value-field' }, [
|
||||
E('div', { 'class': 'cbi-checkbox' }, [
|
||||
this.convertTimestamp,
|
||||
E('label', {}),
|
||||
]),
|
||||
E('div', { 'class': 'cbi-value-description' },
|
||||
_('Convert timestamps to a human readable date')
|
||||
),
|
||||
]),
|
||||
]);
|
||||
},
|
||||
|
||||
makeLogTimeFilterSection() {
|
||||
return E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', {
|
||||
'class': 'cbi-value-title',
|
||||
'for' : 'timeFilter',
|
||||
}, _('Timestamp filter')),
|
||||
E('div', { 'class': 'cbi-value-field' },
|
||||
E('span', { 'class': 'control-group' }, [
|
||||
this.timeFilter,
|
||||
E('button', {
|
||||
'class': 'cbi-button btn',
|
||||
'click': L.bind(ev => {
|
||||
ev.target.blur();
|
||||
ev.preventDefault();
|
||||
this.timeFilter.value = null;
|
||||
this.timeFilter.focus();
|
||||
}, this),
|
||||
}, '⌫'),
|
||||
])
|
||||
),
|
||||
]);
|
||||
},
|
||||
|
||||
makeLogtimeFilterReSection() {
|
||||
return E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', {
|
||||
'class': 'cbi-value-title',
|
||||
'for' : 'timeFilterRe',
|
||||
}, _('Filter is regexp')),
|
||||
E('div', { 'class': 'cbi-value-field' }, [
|
||||
E('div', { 'class': 'cbi-checkbox' }, [
|
||||
this.timeFilterRe,
|
||||
E('label', {}),
|
||||
]),
|
||||
E('div', { 'class': 'cbi-value-description' },
|
||||
_('Apply timestamp filter as regular expression')
|
||||
),
|
||||
]),
|
||||
]);
|
||||
},
|
||||
|
||||
makeLogHostsDropdownItem(host) {
|
||||
return E(
|
||||
'span',
|
||||
@@ -385,23 +476,28 @@ return baseclass.extend({
|
||||
},
|
||||
|
||||
setFilterSettings() {
|
||||
this.tailValue = this.checkZeroValue(this.tailInput.value);
|
||||
this.timeFilterValue = this.timeFilter.value;
|
||||
this.timeFilterReValue = this.timeFilterRe.checked;
|
||||
if(this.isHosts) {
|
||||
this.tailValue = this.checkZeroValue(this.tailInput.value);
|
||||
if(this.logTimestampFlag) {
|
||||
if(this.enableConvertTimestamp) {
|
||||
this.convertTimestampValue = this.convertTimestamp.checked;
|
||||
};
|
||||
this.timeFilterValue = this.timeFilter.value;
|
||||
this.timeFilterReValue = this.timeFilterRe.checked;
|
||||
};
|
||||
if(this.logHostsFlag) {
|
||||
this.hostFilterValue = this.logHostsDropdown.getValue();
|
||||
};
|
||||
if(this.isFacilities) {
|
||||
if(this.logFacilitiesFlag) {
|
||||
this.facilityFilterValue = this.logFacilitiesDropdown.getValue();
|
||||
};
|
||||
if(this.isLevels) {
|
||||
if(this.logLevelsFlag) {
|
||||
this.levelFilterValue = this.logLevelsDropdown.getValue();
|
||||
};
|
||||
this.msgFilterValue = this.msgFilter.value;
|
||||
this.msgFilterReValue = this.msgFilterRe.checked;
|
||||
this.logSortingValue = this.logSorting.value;
|
||||
this.autoRefreshValue = this.autoRefresh.checked;
|
||||
if(this.isAutorefresh) {
|
||||
this.msgFilterValue = this.msgFilter.value;
|
||||
this.msgFilterReValue = this.msgFilterRe.checked;
|
||||
this.logSortingValue = this.logSorting.value;
|
||||
this.autoRefreshValue = this.autoRefresh.checked;
|
||||
if(this.autorefreshOn) {
|
||||
if(this.autoRefreshValue) {
|
||||
poll.add(this.pollFuncWrapper, this.pollInterval);
|
||||
this.refreshBtn.style.visibility = 'hidden';
|
||||
@@ -413,16 +509,21 @@ return baseclass.extend({
|
||||
},
|
||||
|
||||
resetFormValues() {
|
||||
this.tailInput.value = this.tailValue;
|
||||
this.timeFilter.value = this.timeFilterValue;
|
||||
this.timeFilterRe.checked = this.timeFilterReValue;
|
||||
if(this.isHosts) {
|
||||
this.tailInput.value = this.tailValue;
|
||||
if(this.logTimestampFlag) {
|
||||
if(this.enableConvertTimestamp) {
|
||||
this.convertTimestamp.checked = this.convertTimestampValue;
|
||||
};
|
||||
this.timeFilter.value = this.timeFilterValue;
|
||||
this.timeFilterRe.checked = this.timeFilterReValue;
|
||||
};
|
||||
if(this.logHostsFlag) {
|
||||
this.logHostsDropdown.setValue(this.hostFilterValue);
|
||||
};
|
||||
if(this.isFacilities) {
|
||||
if(this.logFacilitiesFlag) {
|
||||
this.logFacilitiesDropdown.setValue(this.facilityFilterValue);
|
||||
};
|
||||
if(this.isLevels) {
|
||||
if(this.logLevelsFlag) {
|
||||
this.logLevelsDropdown.setValue(this.levelFilterValue);
|
||||
};
|
||||
this.msgFilter.value = this.msgFilterValue;
|
||||
@@ -508,7 +609,7 @@ return baseclass.extend({
|
||||
regExp.lastIndex = 0;
|
||||
});
|
||||
} catch(err) {
|
||||
if(err.name === 'SyntaxError') {
|
||||
if(err.name == 'SyntaxError') {
|
||||
ui.addNotification(null,
|
||||
E('p', {}, _('Invalid regular expression') + ': ' + err.message));
|
||||
return entriesArray;
|
||||
@@ -533,7 +634,7 @@ return baseclass.extend({
|
||||
let logHostsKeys = Object.keys(this.logHosts);
|
||||
if(logHostsKeys.length > 0 && this.logHostsDropdown) {
|
||||
this.logHostsDropdown.addChoices(logHostsKeys, this.logHosts);
|
||||
if(this.hostFilterValue.length === 0 || logHostsKeys.length === this.hostFilterValue.length) {
|
||||
if(this.hostFilterValue.length == 0) {
|
||||
return entriesArray;
|
||||
};
|
||||
return entriesArray.filter(e => this.hostFilterValue.includes(e[2]));
|
||||
@@ -544,7 +645,7 @@ return baseclass.extend({
|
||||
setFacilityFilter(entriesArray) {
|
||||
let logFacilitiesKeys = Object.keys(this.logFacilities);
|
||||
if(logFacilitiesKeys.length > 0 && this.logFacilitiesDropdown) {
|
||||
if(this.facilityFilterValue.length === 0 || logFacilitiesKeys.length === this.facilityFilterValue.length) {
|
||||
if(this.facilityFilterValue.length == 0) {
|
||||
return entriesArray;
|
||||
};
|
||||
return entriesArray.filter(e => this.facilityFilterValue.includes(e[3]));
|
||||
@@ -555,7 +656,7 @@ return baseclass.extend({
|
||||
setLevelFilter(entriesArray) {
|
||||
let logLevelsKeys = Object.keys(this.logLevels);
|
||||
if(logLevelsKeys.length > 0 && this.logLevelsDropdown) {
|
||||
if(this.levelFilterValue.length === 0 || logLevelsKeys.length === this.levelFilterValue.length) {
|
||||
if(this.levelFilterValue.length == 0) {
|
||||
return entriesArray;
|
||||
};
|
||||
return entriesArray.filter(e => this.levelFilterValue.includes(e[4]));
|
||||
@@ -630,7 +731,13 @@ return baseclass.extend({
|
||||
if(logSortingLocal) {
|
||||
this.logSortingValue = logSortingLocal;
|
||||
};
|
||||
if(this.isAutorefresh) {
|
||||
if(this.enableConvertTimestamp) {
|
||||
let convertTimestampLocal = localStorage.getItem(`luci-app-${this.viewName}-convertTimestampValue`);
|
||||
if(convertTimestampLocal) {
|
||||
this.convertTimestampValue = Boolean(Number(convertTimestampLocal));
|
||||
};
|
||||
};
|
||||
if(this.enableAutoRefresh) {
|
||||
let autoRefreshLocal = localStorage.getItem(`luci-app-${this.viewName}-autoRefreshValue`);
|
||||
if(autoRefreshLocal) {
|
||||
this.autoRefreshValue = Boolean(Number(autoRefreshLocal));
|
||||
@@ -638,7 +745,7 @@ return baseclass.extend({
|
||||
};
|
||||
},
|
||||
|
||||
saveSettingsToLocalStorage(tailValue, logSortingValue, autoRefreshValue) {
|
||||
saveSettingsToLocalStorage(tailValue, logSortingValue, autoRefreshValue, convertTimestampValue) {
|
||||
tailValue = this.checkZeroValue(tailValue);
|
||||
if(this.tailValue != tailValue) {
|
||||
localStorage.setItem(
|
||||
@@ -648,7 +755,13 @@ return baseclass.extend({
|
||||
localStorage.setItem(
|
||||
`luci-app-${this.viewName}-logSortingValue`, logSortingValue);
|
||||
};
|
||||
if(this.isAutorefresh) {
|
||||
if(this.convertTimestampOn) {
|
||||
if(this.convertTimestampValue != convertTimestampValue) {
|
||||
localStorage.setItem(
|
||||
`luci-app-${this.viewName}-convertTimestampValue`, String(Number(convertTimestampValue)));
|
||||
};
|
||||
};
|
||||
if(this.autorefreshOn) {
|
||||
if(this.autoRefreshValue != autoRefreshValue) {
|
||||
localStorage.setItem(
|
||||
`luci-app-${this.viewName}-autoRefreshValue`, String(Number(autoRefreshValue)));
|
||||
@@ -681,13 +794,23 @@ return baseclass.extend({
|
||||
)
|
||||
);
|
||||
if(logdata && logdata !== '') {
|
||||
if(this.isFacilities && !this.logFacilitiesDropdown) {
|
||||
if(this.enableConvertTimestamp && !this.logConvertTimestampElem) {
|
||||
this.logConvertTimestampElem = this.makeLogConvertTimestampSection();
|
||||
};
|
||||
if(this.logTimestampFlag && !this.logTimeFilterElem) {
|
||||
this.logTimeFilterElem = this.makeLogTimeFilterSection();
|
||||
};
|
||||
if(this.logTimestampFlag && !this.logtimeFilterReElem) {
|
||||
this.logtimeFilterReElem = this.makeLogtimeFilterReSection();
|
||||
};
|
||||
|
||||
if(this.logFacilitiesFlag && !this.logFacilitiesDropdown) {
|
||||
this.logFacilitiesDropdownElem = this.makeLogFacilitiesDropdownSection();
|
||||
};
|
||||
if(this.isLevels && !this.logLevelsDropdown) {
|
||||
if(this.logLevelsFlag && !this.logLevelsDropdown) {
|
||||
this.logLevelsDropdownElem = this.makeLogLevelsDropdownSection();
|
||||
};
|
||||
if(this.isHosts && !this.logHostsDropdown) {
|
||||
if(this.logHostsFlag && !this.logHostsDropdown) {
|
||||
this.logHostsDropdownElem = this.makeLogHostsDropdownSection();
|
||||
};
|
||||
};
|
||||
@@ -730,41 +853,9 @@ return baseclass.extend({
|
||||
])
|
||||
),
|
||||
]),
|
||||
E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', {
|
||||
'class': 'cbi-value-title',
|
||||
'for' : 'timeFilter',
|
||||
}, _('Timestamp filter')),
|
||||
E('div', { 'class': 'cbi-value-field' },
|
||||
E('span', { 'class': 'control-group' }, [
|
||||
this.timeFilter,
|
||||
E('button', {
|
||||
'class': 'cbi-button btn',
|
||||
'click': L.bind(ev => {
|
||||
ev.target.blur();
|
||||
ev.preventDefault();
|
||||
this.timeFilter.value = null;
|
||||
this.timeFilter.focus();
|
||||
}, this),
|
||||
}, '⌫'),
|
||||
])
|
||||
),
|
||||
]),
|
||||
E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', {
|
||||
'class': 'cbi-value-title',
|
||||
'for' : 'timeFilterRe',
|
||||
}, _('Filter is regexp')),
|
||||
E('div', { 'class': 'cbi-value-field' }, [
|
||||
E('div', { 'class': 'cbi-checkbox' }, [
|
||||
this.timeFilterRe,
|
||||
E('label', {}),
|
||||
]),
|
||||
E('div', { 'class': 'cbi-value-description' },
|
||||
_('Apply timestamp filter as regular expression')
|
||||
),
|
||||
]),
|
||||
]),
|
||||
this.logConvertTimestampElem,
|
||||
this.logTimeFilterElem,
|
||||
this.logtimeFilterReElem,
|
||||
this.logHostsDropdownElem,
|
||||
this.logFacilitiesDropdownElem,
|
||||
this.logLevelsDropdownElem,
|
||||
@@ -810,7 +901,7 @@ return baseclass.extend({
|
||||
}, _('Sorting entries')),
|
||||
E('div', { 'class': 'cbi-value-field' }, this.logSorting),
|
||||
]),
|
||||
((this.isAutorefresh) ?
|
||||
((this.autorefreshOn) ?
|
||||
E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', {
|
||||
'class': 'cbi-value-title',
|
||||
@@ -877,6 +968,25 @@ return baseclass.extend({
|
||||
throw new Error('getLogHash must be overridden by a subclass');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts the timestamp format.
|
||||
* Abstract method, must be overridden by a subclass!
|
||||
*
|
||||
* To completely disable the convert timrstamp option, views extending
|
||||
* this base class should overwrite the `convertTimestampFunc` function
|
||||
* with `null`.
|
||||
*
|
||||
* @instance
|
||||
* @abstract
|
||||
*
|
||||
* @param {string} t
|
||||
* @returns {String}
|
||||
* Returns the converted timestamp string.
|
||||
*/
|
||||
convertTimestampFunc(t) {
|
||||
throw new Error('convertTimestampFunc must be overridden by a subclass');
|
||||
},
|
||||
|
||||
async pollFunc() {
|
||||
await this.getLogHash().then(async hash => {
|
||||
if(this.lastHash !== hash) {
|
||||
@@ -895,7 +1005,8 @@ return baseclass.extend({
|
||||
};
|
||||
};
|
||||
this.saveSettingsToLocalStorage(
|
||||
this.tailInput.value, this.logSorting.value, this.autoRefresh.checked);
|
||||
this.tailInput.value, this.logSorting.value,
|
||||
this.autoRefresh.checked, this.convertTimestamp.checked);
|
||||
this.setFilterSettings();
|
||||
this.fastTailValue = Number(this.tailValue);
|
||||
return this.reloadLog(Number(this.tailValue), true);
|
||||
@@ -911,10 +1022,13 @@ return baseclass.extend({
|
||||
|
||||
load() {
|
||||
this.restoreSettingsFromLocalStorage();
|
||||
if(!this.autoRefresh || typeof(this.getLogHash) != 'function') {
|
||||
this.isAutorefresh = false;
|
||||
if(!this.enableAutoRefresh || typeof(this.getLogHash) != 'function') {
|
||||
this.autorefreshOn = false;
|
||||
this.autoRefreshValue = false;
|
||||
};
|
||||
if(this.enableConvertTimestamp && typeof(this.convertTimestampFunc) == 'function') {
|
||||
this.convertTimestampOn = true;
|
||||
};
|
||||
return this.getLogData(this.tailValue);
|
||||
},
|
||||
|
||||
@@ -939,18 +1053,13 @@ return baseclass.extend({
|
||||
this.tailInput.value = this.tailValue;
|
||||
ui.addValidator(this.tailInput, 'uinteger', true);
|
||||
|
||||
this.logHostsDropdownElem = '';
|
||||
this.logFacilitiesDropdownElem = '';
|
||||
this.logLevelsDropdownElem = '';
|
||||
if(this.isLevels) {
|
||||
this.logLevelsDropdownElem = this.makeLogLevelsDropdownSection();
|
||||
};
|
||||
if(this.isFacilities) {
|
||||
this.logFacilitiesDropdownElem = this.makeLogFacilitiesDropdownSection();
|
||||
};
|
||||
if(this.isHosts) {
|
||||
this.logHostsDropdownElem = this.makeLogHostsDropdownSection();
|
||||
};
|
||||
this.convertTimestamp = E('input', {
|
||||
'id' : 'convertTimestamp',
|
||||
'name' : 'convertTimestamp',
|
||||
'type' : 'checkbox',
|
||||
'form' : 'logFilterForm',
|
||||
});
|
||||
this.convertTimestamp.checked = this.convertTimestampValue;
|
||||
|
||||
this.timeFilter = E('input', {
|
||||
'id' : 'timeFilter',
|
||||
@@ -971,6 +1080,28 @@ return baseclass.extend({
|
||||
|
||||
this.setRegexpValidator(this.timeFilter, this.timeFilterRe);
|
||||
|
||||
this.logConvertTimestampElem = '';
|
||||
this.logTimeFilterElem = '';
|
||||
this.logtimeFilterReElem = '';
|
||||
this.logHostsDropdownElem = '';
|
||||
this.logFacilitiesDropdownElem = '';
|
||||
this.logLevelsDropdownElem = '';
|
||||
|
||||
if(this.logTimestampFlag) {
|
||||
this.logConvertTimestampElem = this.makeLogConvertTimestampSection();
|
||||
this.logTimeFilterElem = this.makeLogTimeFilterSection();
|
||||
this.logtimeFilterReElem = this.makeLogtimeFilterReSection();
|
||||
};
|
||||
if(this.logLevelsFlag) {
|
||||
this.logLevelsDropdownElem = this.makeLogLevelsDropdownSection();
|
||||
};
|
||||
if(this.logFacilitiesFlag) {
|
||||
this.logFacilitiesDropdownElem = this.makeLogFacilitiesDropdownSection();
|
||||
};
|
||||
if(this.logHostsFlag) {
|
||||
this.logHostsDropdownElem = this.makeLogHostsDropdownSection();
|
||||
};
|
||||
|
||||
this.msgFilter = E('input', {
|
||||
'id' : 'msgFilter',
|
||||
'name' : 'msgFilter',
|
||||
@@ -1123,7 +1254,7 @@ return baseclass.extend({
|
||||
])
|
||||
);
|
||||
|
||||
if(this.isAutorefresh && this.autoRefreshValue) {
|
||||
if(this.autorefreshOn && this.autoRefreshValue) {
|
||||
poll.add(this.pollFuncWrapper, this.pollInterval);
|
||||
};
|
||||
|
||||
|
||||
+63
-35
@@ -1,17 +1,18 @@
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
'require fs';
|
||||
'require ui';
|
||||
'require view.ruantiblock.log-widget as widget';
|
||||
|
||||
return baseclass.extend({
|
||||
view: widget.view.extend({
|
||||
enableAutoRefresh: true,
|
||||
|
||||
/**
|
||||
* Pattern for picking application-specific entries from the log.
|
||||
*
|
||||
* @property {string} appPattern
|
||||
*/
|
||||
appPattern : '^',
|
||||
appPattern : '^',
|
||||
|
||||
/**
|
||||
* Enable "tail" option for the logread (logread -l).
|
||||
@@ -19,19 +20,19 @@ return baseclass.extend({
|
||||
*
|
||||
* @property {bool} loggerTail
|
||||
*/
|
||||
loggerTail : false,
|
||||
loggerTail : false,
|
||||
|
||||
logdRegexp : new RegExp(/^([^\s]{3}\s+[^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2}\s+\d{4})\s+([a-z0-9]+)\.([a-z]+)\s+(.*)$/),
|
||||
logdRegexp : new RegExp(/^([^\s]{3}\s+[^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2}\s+\d{4})\s+([a-z0-9]+)\.([a-z]+)\s+(.*)$/),
|
||||
|
||||
syslog_ngRegexp: new RegExp(/^([^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2})\s+([^\s]+)\s+(.*)$/),
|
||||
syslog_ngRegexp : new RegExp(/^([^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2})\s+([^\s]+)\s+(.*)$/),
|
||||
|
||||
entryRegexp : null,
|
||||
entryRegexp : null,
|
||||
|
||||
isLoggerChecked: false,
|
||||
loggerChecked : false,
|
||||
|
||||
entriesHandler : null,
|
||||
entriesHandler : null,
|
||||
|
||||
logger : null,
|
||||
logger : null,
|
||||
|
||||
getLogHash() {
|
||||
return this.getLogData(1, true).then(data => {
|
||||
@@ -66,6 +67,18 @@ return baseclass.extend({
|
||||
];
|
||||
},
|
||||
|
||||
// unsupported log handler
|
||||
unsupportedLogHandler(line, lineNum) {
|
||||
return [
|
||||
lineNum, // # (Number)
|
||||
null, // Timestamp (String)
|
||||
null, // Host (String)
|
||||
null, // Facility (String)
|
||||
null, // Level (String)
|
||||
this.htmlEntities(line) || ' ', // Message (String)
|
||||
];
|
||||
},
|
||||
|
||||
checkLogread() {
|
||||
return Promise.all([
|
||||
L.resolveDefault(fs.stat('/sbin/logread'), null),
|
||||
@@ -102,8 +115,7 @@ return baseclass.extend({
|
||||
return [];
|
||||
};
|
||||
|
||||
let unsupportedLog = false;
|
||||
let strings = logdata.trim().split(/\n/);
|
||||
let strings = logdata.trim().split(/\n/);
|
||||
|
||||
if(!this.loggerTail && tail && tail > 0 && strings) {
|
||||
strings = strings.slice(-tail);
|
||||
@@ -111,45 +123,61 @@ return baseclass.extend({
|
||||
|
||||
this.totalLogLines = strings.length;
|
||||
|
||||
let entriesArray = strings.map((e, i) => {
|
||||
if(!this.isLoggerChecked) {
|
||||
let entriesArray = strings.map((e, i) => {
|
||||
if(!this.loggerChecked) {
|
||||
if(this.logdRegexp.test(e)) {
|
||||
this.entryRegexp = this.logdRegexp;
|
||||
this.isFacilities = true;
|
||||
this.isLevels = true;
|
||||
this.logHosts = {};
|
||||
this.entriesHandler = this.logdHandler;
|
||||
this.entryRegexp = this.logdRegexp;
|
||||
this.logTimestampFlag = true;
|
||||
this.logFacilitiesFlag = true;
|
||||
this.logLevelsFlag = true;
|
||||
this.logHostsFlag = false;
|
||||
this.logHosts = {};
|
||||
this.entriesHandler = this.logdHandler;
|
||||
this.logCols = [
|
||||
'#',
|
||||
_('Timestamp'),
|
||||
null,
|
||||
_('Facility'),
|
||||
_('Level'),
|
||||
_('Message'),
|
||||
];
|
||||
this.loggerChecked = true;
|
||||
}
|
||||
else if(this.syslog_ngRegexp.test(e)) {
|
||||
this.entryRegexp = this.syslog_ngRegexp;
|
||||
this.isHosts = true;
|
||||
this.logFacilities = {};
|
||||
this.logLevels = {};
|
||||
this.entriesHandler = this.syslog_ngHandler;
|
||||
this.entryRegexp = this.syslog_ngRegexp;
|
||||
this.logTimestampFlag = true;
|
||||
this.logFacilitiesFlag = false;
|
||||
this.logLevelsFlag = false;
|
||||
this.logHostsFlag = true;
|
||||
this.logFacilities = {};
|
||||
this.logLevels = {};
|
||||
this.entriesHandler = this.syslog_ngHandler;
|
||||
this.logCols = [
|
||||
'#',
|
||||
_('Timestamp'),
|
||||
_('Host'),
|
||||
null,
|
||||
null,
|
||||
_('Message'),
|
||||
];
|
||||
this.loggerChecked = true;
|
||||
} else {
|
||||
unsupportedLog = true;
|
||||
return;
|
||||
return this.unsupportedLogHandler(e, i + 1);
|
||||
};
|
||||
this.isLoggerChecked = true;
|
||||
};
|
||||
|
||||
let strArray = e.match(this.entryRegexp);
|
||||
if(strArray) {
|
||||
return this.entriesHandler(strArray, i + 1);
|
||||
} else {
|
||||
unsupportedLog = true;
|
||||
return;
|
||||
return this.unsupportedLogHandler(e, i + 1);
|
||||
};
|
||||
});
|
||||
|
||||
if(unsupportedLog) {
|
||||
throw new Error(_('Unable to load log data:') + ' ' + _('Unsupported log format'));
|
||||
} else {
|
||||
if(this.logSortingValue === 'desc') {
|
||||
entriesArray.reverse();
|
||||
};
|
||||
return entriesArray;
|
||||
if(this.logSortingValue == 'desc') {
|
||||
entriesArray.reverse();
|
||||
};
|
||||
return entriesArray;
|
||||
},
|
||||
}),
|
||||
});
|
||||
@@ -46,38 +46,50 @@ return baseclass.extend({
|
||||
if(e[4] in this.logLevels) {
|
||||
this.logLevelsStat[e[4]] = this.logLevelsStat[e[4]] + 1;
|
||||
};
|
||||
lines.push(
|
||||
`<tr class="tr log-${e[4] || 'empty'}"><td class="td left log-entry-text-nowrap" data-title="#">${e[0]}</td>` +
|
||||
((e[1]) ? `<td class="td left log-entry-time-cell" data-title="${_('Timestamp')}">${e[1]}</td>` : '') +
|
||||
((e[2]) ? `<td class="td left log-entry-host-cell" data-title="${_('Host')}">${e[2]}</td>` : '') +
|
||||
((e[3]) ? `<td class="td left log-entry-text-nowrap" data-title="${_('Facility')}">${e[3]}</td>` : '') +
|
||||
((e[4]) ? `<td class="td left log-entry-text-nowrap" data-title="${_('Level')}">${e[4]}</td>` : '') +
|
||||
((e[5]) ? `<td class="td left log-entry-message-cell" data-title="${_('Message')}">${e[5]}</td>` : '') +
|
||||
'</tr>'
|
||||
);
|
||||
|
||||
let line = [ `<tr class="tr log-${(e[1]) ? e[4] || 'empty' : (this.entriesHandler) ? 'raw' : 'empty'}">` ];
|
||||
this.logCols.forEach((c, i) => {
|
||||
if(c) {
|
||||
let cellClass = '';
|
||||
switch(i) {
|
||||
case 0:
|
||||
case 3:
|
||||
case 4:
|
||||
cellClass = 'log-entry-text-nowrap';
|
||||
break;
|
||||
case 1:
|
||||
cellClass = 'log-entry-time-cell';
|
||||
break;
|
||||
case 2:
|
||||
cellClass = 'log-entry-host-cell';
|
||||
break;
|
||||
case 5:
|
||||
cellClass = 'log-entry-message-cell';
|
||||
break;
|
||||
};
|
||||
line.push(`<td class="td left ${cellClass}" data-title="${c}">${e[i] || ' '}</td>`);
|
||||
};
|
||||
});
|
||||
line.push('</tr>');
|
||||
lines.push(line.join(''));
|
||||
});
|
||||
lines = lines.join('');
|
||||
logTable.append(
|
||||
E('tr', { 'class': 'tr table-titles' }, [
|
||||
E('th', { 'class': 'th left log-entry-text-nowrap' }, '#'),
|
||||
(logdataArray[0][1]) ?
|
||||
E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Timestamp')) : '',
|
||||
(logdataArray[0][2]) ?
|
||||
E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Host')) : '',
|
||||
(logdataArray[0][3]) ?
|
||||
E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Facility')) : '',
|
||||
(logdataArray[0][4]) ?
|
||||
E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Level')) : '',
|
||||
(logdataArray[0][5]) ?
|
||||
E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Message')) : '',
|
||||
])
|
||||
);
|
||||
|
||||
let logTableHeader = E('tr', { 'class': 'tr table-titles' });
|
||||
this.logCols.forEach(e => {
|
||||
if(e) {
|
||||
logTableHeader.append(
|
||||
E('th', { 'class': 'th left log-entry-text-nowrap' }, e)
|
||||
);
|
||||
};
|
||||
});
|
||||
logTable.append(logTableHeader);
|
||||
};
|
||||
|
||||
try {
|
||||
logTable.insertAdjacentHTML('beforeend', lines);
|
||||
} catch(err) {
|
||||
if(err.name === 'SyntaxError') {
|
||||
if(err.name == 'SyntaxError') {
|
||||
ui.addNotification(null,
|
||||
E('p', {}, _('HTML/XML error') + ': ' + err.message), 'error');
|
||||
};
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
'require view.ruantiblock.log-abstract as abc';
|
||||
'require view.ruantiblock.log-system as abc';
|
||||
'require view.ruantiblock.tools as tools';
|
||||
|
||||
return abc.view.extend({
|
||||
viewName : 'ruantiblock',
|
||||
title : _('Ruantiblock') + ' - ' + _('Log'),
|
||||
autoRefresh: false,
|
||||
appPattern : tools.appName + ':',
|
||||
viewName : 'ruantiblock',
|
||||
title : _('Ruantiblock') + ' - ' + _('Log'),
|
||||
enableAutoRefresh: false,
|
||||
appPattern : tools.appName + ':',
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user