mirror of
https://github.com/openwrt/luci.git
synced 2025-12-21 19:14:34 +04:00
luci-mod-status: update syslog viewer to use the remodeled CBILogreadBox
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
This commit is contained in:
@@ -1,228 +1,4 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
'require view';
|
'require tools.views as views';
|
||||||
'require fs';
|
|
||||||
'require poll';
|
|
||||||
'require ui';
|
|
||||||
|
|
||||||
return view.extend({
|
return views.LogreadBox(null, _('System'));
|
||||||
logFacilityFilter: 'any',
|
|
||||||
invertLogFacilitySearch: false,
|
|
||||||
logSeverityFilter: 'any',
|
|
||||||
invertLogSeveritySearch: false,
|
|
||||||
logTextFilter: '',
|
|
||||||
invertLogTextSearch: false,
|
|
||||||
|
|
||||||
facilities: [
|
|
||||||
['any', 'any', _('Any')],
|
|
||||||
['0', 'kern', _('Kernel')],
|
|
||||||
['1', 'user', _('User')],
|
|
||||||
['2', 'mail', _('Mail')],
|
|
||||||
['3', 'daemon', _('Daemon')],
|
|
||||||
['4', 'auth', _('Auth')],
|
|
||||||
['5', 'syslog', _('Syslog')],
|
|
||||||
['6', 'lpr', _('LPR')],
|
|
||||||
['7', 'news', _('News')],
|
|
||||||
['8', 'uucp', _('UUCP')],
|
|
||||||
['9', 'cron', _('Cron')],
|
|
||||||
['10', 'authpriv', _('Auth Priv')],
|
|
||||||
['11', 'ftp', _('FTP')],
|
|
||||||
['12', 'ntp', _('NTP')],
|
|
||||||
['13', 'security', _('Log audit')],
|
|
||||||
['14', 'console', _('Log alert')],
|
|
||||||
['15', 'cron', _('Scheduling daemon')],
|
|
||||||
['16', 'local0', _('Local 0')],
|
|
||||||
['17', 'local1', _('Local 1')],
|
|
||||||
['18', 'local2', _('Local 2')],
|
|
||||||
['19', 'local3', _('Local 3')],
|
|
||||||
['20', 'local4', _('Local 4')],
|
|
||||||
['21', 'local5', _('Local 5')],
|
|
||||||
['22', 'local6', _('Local 6')],
|
|
||||||
['23', 'local7', _('Local 7')]
|
|
||||||
],
|
|
||||||
|
|
||||||
severity: [
|
|
||||||
['any','any', _('Any')],
|
|
||||||
['0', 'emerg', _('Emergency')],
|
|
||||||
['1', 'alert', _('Alert')],
|
|
||||||
['2', 'crit', _('Critical')],
|
|
||||||
['3', 'err', _('Error')],
|
|
||||||
['4', 'warn', _('Warning')],
|
|
||||||
['5', 'notice', _('Notice')],
|
|
||||||
['6', 'info', _('Info')],
|
|
||||||
['7', 'debug', _('Debug')]
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
retrieveLog: async function() {
|
|
||||||
|
|
||||||
return Promise.all([
|
|
||||||
L.resolveDefault(fs.stat('/usr/libexec/syslog-wrapper'), null),
|
|
||||||
]).then((stat) => {
|
|
||||||
const logger = stat[0]?.path;
|
|
||||||
|
|
||||||
return fs.exec_direct(logger).then(logdata => {
|
|
||||||
let loglines = logdata.trim().split(/\n/);
|
|
||||||
|
|
||||||
loglines = loglines.filter(line => {
|
|
||||||
const sevMatch = this.logSeverityFilter === 'any' || line.includes(`.${this.logSeverityFilter}`);
|
|
||||||
const facMatch = this.logFacilityFilter === 'any' || line.includes(`${this.logFacilityFilter}.`);
|
|
||||||
|
|
||||||
return (this.invertLogSeveritySearch != sevMatch)
|
|
||||||
&& (this.invertLogFacilitySearch != facMatch);
|
|
||||||
});
|
|
||||||
|
|
||||||
loglines = loglines.filter(line => {
|
|
||||||
const match = line.includes(this.logTextFilter);
|
|
||||||
return this.invertLogTextSearch ? !match : match;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
value: loglines.join('\n'),
|
|
||||||
rows: loglines.length + 1
|
|
||||||
};
|
|
||||||
}).catch(function(err) {
|
|
||||||
ui.addNotification(null, E('p', {}, _('Unable to load log data: ' + err.message)));
|
|
||||||
return {
|
|
||||||
value: '',
|
|
||||||
rows: 0
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
pollLog: async function() {
|
|
||||||
const element = document.getElementById('syslog');
|
|
||||||
if (element) {
|
|
||||||
const log = await this.retrieveLog();
|
|
||||||
element.value = log.value;
|
|
||||||
element.rows = log.rows;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
poll.add(this.pollLog.bind(this));
|
|
||||||
return await this.retrieveLog();
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function(loglines) {
|
|
||||||
const scrollDownButton = E('button', {
|
|
||||||
'id': 'scrollDownButton',
|
|
||||||
'class': 'cbi-button cbi-button-neutral'
|
|
||||||
}, _('Scroll to tail', 'scroll to bottom (the tail) of the log file')
|
|
||||||
);
|
|
||||||
scrollDownButton.addEventListener('click', () => {
|
|
||||||
scrollUpButton.scrollIntoView();
|
|
||||||
scrollDownButton.blur();
|
|
||||||
});
|
|
||||||
|
|
||||||
const scrollUpButton = E('button', {
|
|
||||||
'id' : 'scrollUpButton',
|
|
||||||
'class': 'cbi-button cbi-button-neutral'
|
|
||||||
}, _('Scroll to head', 'scroll to top (the head) of the log file')
|
|
||||||
);
|
|
||||||
scrollUpButton.addEventListener('click', () => {
|
|
||||||
scrollDownButton.scrollIntoView();
|
|
||||||
scrollUpButton.blur();
|
|
||||||
});
|
|
||||||
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
// Create facility invert checkbox
|
|
||||||
const facilityInvert = E('input', {
|
|
||||||
'id': 'invertLogFacilitySearch',
|
|
||||||
'type': 'checkbox',
|
|
||||||
'class': 'cbi-input-checkbox',
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create facility select-dropdown from facilities map
|
|
||||||
const facilitySelect = E('select', {
|
|
||||||
'id': 'logFacilitySelect',
|
|
||||||
'class': 'cbi-input-select',
|
|
||||||
'style': 'margin-bottom:10px',
|
|
||||||
},
|
|
||||||
this.facilities.map(([_, val, label]) =>
|
|
||||||
E('option', { value: val }, label)
|
|
||||||
));
|
|
||||||
|
|
||||||
// Create severity invert checkbox
|
|
||||||
const severityInvert = E('input', {
|
|
||||||
'id': 'invertLogSeveritySearch',
|
|
||||||
'type': 'checkbox',
|
|
||||||
'class': 'cbi-input-checkbox',
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create severity select-dropdown from facilities map
|
|
||||||
const severitySelect = E('select', {
|
|
||||||
'id': 'logSeveritySelect',
|
|
||||||
'class': 'cbi-input-select',
|
|
||||||
},
|
|
||||||
this.severity.map(([_, val, label]) =>
|
|
||||||
E('option', { value: val }, label)
|
|
||||||
));
|
|
||||||
|
|
||||||
// Create raw text search invert checkbox
|
|
||||||
const filterTextInvert = E('input', {
|
|
||||||
'id': 'invertLogTextSearch',
|
|
||||||
'type': 'checkbox',
|
|
||||||
'class': 'cbi-input-checkbox',
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create raw text search text input
|
|
||||||
const filterTextInput = E('input', {
|
|
||||||
'id': 'logTextFilter',
|
|
||||||
'class': 'cbi-input-text',
|
|
||||||
});
|
|
||||||
|
|
||||||
function handleLogFilterChange() {
|
|
||||||
self.logFacilityFilter = facilitySelect.value;
|
|
||||||
self.invertLogFacilitySearch = facilityInvert.checked;
|
|
||||||
self.logSeverityFilter = severitySelect.value;
|
|
||||||
self.invertLogSeveritySearch = severityInvert.checked;
|
|
||||||
self.logTextFilter = filterTextInput.value;
|
|
||||||
self.invertLogTextSearch = filterTextInvert.checked;
|
|
||||||
self.pollLog();
|
|
||||||
}
|
|
||||||
|
|
||||||
facilitySelect.addEventListener('change', handleLogFilterChange);
|
|
||||||
facilityInvert.addEventListener('change', handleLogFilterChange);
|
|
||||||
severitySelect.addEventListener('change', handleLogFilterChange);
|
|
||||||
severityInvert.addEventListener('change', handleLogFilterChange);
|
|
||||||
filterTextInput.addEventListener('input', handleLogFilterChange);
|
|
||||||
filterTextInvert.addEventListener('change', handleLogFilterChange);
|
|
||||||
|
|
||||||
return E([], [
|
|
||||||
E('h2', {}, [ _('System Log') ]),
|
|
||||||
E('div', { 'id': 'content_syslog' }, [
|
|
||||||
E('div', { 'style': 'margin-bottom:10px' }, [
|
|
||||||
E('label', { 'for': 'invertLogFacilitySearch', 'style': 'margin-right:5px' }, _('Not')),
|
|
||||||
facilityInvert,
|
|
||||||
E('label', { 'for': 'logFacilitySelect', 'style': 'margin: 0 5px' }, _('facility:')),
|
|
||||||
facilitySelect,
|
|
||||||
E('label', { 'for': 'invertLogSeveritySearch', 'style': 'margin: 0 5px' }, _('Not')),
|
|
||||||
severityInvert,
|
|
||||||
E('label', { 'for': 'logSeveritySelect', 'style': 'margin: 0 5px' }, _('severity:')),
|
|
||||||
severitySelect,
|
|
||||||
]),
|
|
||||||
E('div', { 'style': 'margin-bottom:10px' }, [
|
|
||||||
E('label', { 'for': 'invertLogTextSearch', 'style': 'margin-right:5px' }, _('Not')),
|
|
||||||
filterTextInvert,
|
|
||||||
E('label', { 'for': 'logTextFilter', 'style': 'margin: 0 5px' }, _('including:')),
|
|
||||||
filterTextInput,
|
|
||||||
]),
|
|
||||||
E('div', {'style': 'padding-bottom: 20px'}, [scrollDownButton]),
|
|
||||||
E('textarea', {
|
|
||||||
'id': 'syslog',
|
|
||||||
'style': 'font-size:12px',
|
|
||||||
'readonly': 'readonly',
|
|
||||||
'wrap': 'off',
|
|
||||||
'rows': loglines.rows,
|
|
||||||
}, [ loglines.value ]),
|
|
||||||
E('div', {'style': 'padding-bottom: 20px'}, [scrollUpButton])
|
|
||||||
])
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleSaveApply: null,
|
|
||||||
handleSave: null,
|
|
||||||
handleReset: null
|
|
||||||
});
|
|
||||||
@@ -31,11 +31,10 @@
|
|||||||
"read": {
|
"read": {
|
||||||
"cgi-io": [ "exec" ],
|
"cgi-io": [ "exec" ],
|
||||||
"file": {
|
"file": {
|
||||||
"/bin/dmesg -r": [ "exec" ],
|
"/bin/dmesg -r": [ "exec" ]
|
||||||
"/usr/libexec/syslog-wrapper": [ "exec" ]
|
|
||||||
},
|
},
|
||||||
"ubus": {
|
"ubus": {
|
||||||
"file": [ "stat" ]
|
"log": [ "read" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user