mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-06 19:46:52 +03:00
Feature/error notification
This commit is contained in:
@@ -12,6 +12,8 @@ const STATUS_COLORS = {
|
|||||||
WARNING: '#ff9800'
|
WARNING: '#ff9800'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ERROR_POLL_INTERVAL = 5000; // 5 seconds
|
||||||
|
|
||||||
async function safeExec(command, args = [], timeout = 7000) {
|
async function safeExec(command, args = [], timeout = 7000) {
|
||||||
try {
|
try {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
@@ -850,6 +852,84 @@ function checkDNSAvailability() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getPodkopErrors() {
|
||||||
|
try {
|
||||||
|
const result = await safeExec('/usr/bin/podkop', ['check_logs']);
|
||||||
|
if (!result || !result.stdout) return [];
|
||||||
|
|
||||||
|
const logs = result.stdout.split('\n');
|
||||||
|
const errors = logs.filter(log =>
|
||||||
|
// log.includes('saved for future filters') ||
|
||||||
|
log.includes('[critical]')
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('Found errors:', errors);
|
||||||
|
return errors;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting podkop logs:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let errorPollTimer = null;
|
||||||
|
let lastErrorsSet = new Set();
|
||||||
|
let isInitialCheck = true;
|
||||||
|
|
||||||
|
function showErrorNotification(error, isMultiple = false) {
|
||||||
|
const notificationContent = E('div', { 'class': 'alert-message error' }, [
|
||||||
|
E('pre', { 'class': 'error-log' }, error)
|
||||||
|
]);
|
||||||
|
|
||||||
|
ui.addNotification(null, notificationContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
function startErrorPolling() {
|
||||||
|
if (errorPollTimer) {
|
||||||
|
clearInterval(errorPollTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkErrors() {
|
||||||
|
const result = await safeExec('/usr/bin/podkop', ['check_logs']);
|
||||||
|
if (!result || !result.stdout) return;
|
||||||
|
|
||||||
|
const logs = result.stdout;
|
||||||
|
|
||||||
|
const errorLines = logs.split('\n').filter(line =>
|
||||||
|
// line.includes('saved for future filters') ||
|
||||||
|
line.includes('[critical]')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (errorLines.length > 0) {
|
||||||
|
const currentErrors = new Set(errorLines);
|
||||||
|
|
||||||
|
if (isInitialCheck) {
|
||||||
|
if (errorLines.length > 0) {
|
||||||
|
showErrorNotification(errorLines.join('\n'), true);
|
||||||
|
}
|
||||||
|
isInitialCheck = false;
|
||||||
|
} else {
|
||||||
|
const newErrors = [...currentErrors].filter(error => !lastErrorsSet.has(error));
|
||||||
|
|
||||||
|
newErrors.forEach(error => {
|
||||||
|
showErrorNotification(error, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
lastErrorsSet = currentErrors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkErrors();
|
||||||
|
|
||||||
|
errorPollTimer = setInterval(checkErrors, ERROR_POLL_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopErrorPolling() {
|
||||||
|
if (errorPollTimer) {
|
||||||
|
clearInterval(errorPollTimer);
|
||||||
|
errorPollTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return view.extend({
|
return view.extend({
|
||||||
async render() {
|
async render() {
|
||||||
document.head.insertAdjacentHTML('beforeend', `
|
document.head.insertAdjacentHTML('beforeend', `
|
||||||
@@ -1348,8 +1428,10 @@ return view.extend({
|
|||||||
const diagnosticsContainer = document.getElementById('diagnostics-status');
|
const diagnosticsContainer = document.getElementById('diagnostics-status');
|
||||||
if (document.hidden) {
|
if (document.hidden) {
|
||||||
stopDiagnosticsUpdates();
|
stopDiagnosticsUpdates();
|
||||||
|
stopErrorPolling();
|
||||||
} else if (diagnosticsContainer && diagnosticsContainer.hasAttribute('data-loading')) {
|
} else if (diagnosticsContainer && diagnosticsContainer.hasAttribute('data-loading')) {
|
||||||
startDiagnosticsUpdates();
|
startDiagnosticsUpdates();
|
||||||
|
startErrorPolling();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1360,6 +1442,7 @@ return view.extend({
|
|||||||
if (!this.hasAttribute('data-loading')) {
|
if (!this.hasAttribute('data-loading')) {
|
||||||
this.setAttribute('data-loading', 'true');
|
this.setAttribute('data-loading', 'true');
|
||||||
startDiagnosticsUpdates();
|
startDiagnosticsUpdates();
|
||||||
|
startErrorPolling();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1375,9 +1458,11 @@ return view.extend({
|
|||||||
if (container && !container.hasAttribute('data-loading')) {
|
if (container && !container.hasAttribute('data-loading')) {
|
||||||
container.setAttribute('data-loading', 'true');
|
container.setAttribute('data-loading', 'true');
|
||||||
startDiagnosticsUpdates();
|
startDiagnosticsUpdates();
|
||||||
|
startErrorPolling();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stopDiagnosticsUpdates();
|
stopDiagnosticsUpdates();
|
||||||
|
stopErrorPolling();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1388,6 +1473,7 @@ return view.extend({
|
|||||||
if (container && !container.hasAttribute('data-loading')) {
|
if (container && !container.hasAttribute('data-loading')) {
|
||||||
container.setAttribute('data-loading', 'true');
|
container.setAttribute('data-loading', 'true');
|
||||||
startDiagnosticsUpdates();
|
startDiagnosticsUpdates();
|
||||||
|
startErrorPolling();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ nolog() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
|
log "Starting podkop"
|
||||||
migration
|
migration
|
||||||
|
|
||||||
config_foreach process_validate_service
|
config_foreach process_validate_service
|
||||||
@@ -1857,12 +1858,24 @@ check_fakeip() {
|
|||||||
check_logs() {
|
check_logs() {
|
||||||
nolog "Showing podkop logs from system journal..."
|
nolog "Showing podkop logs from system journal..."
|
||||||
|
|
||||||
if command -v logread >/dev/null 2>&1; then
|
if ! command -v logread >/dev/null 2>&1; then
|
||||||
logread -e podkop | tail -n 50
|
|
||||||
else
|
|
||||||
nolog "Error: logread command not found"
|
nolog "Error: logread command not found"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Get all logs first
|
||||||
|
local all_logs=$(logread)
|
||||||
|
|
||||||
|
# Find the last occurrence of "Starting podkop"
|
||||||
|
local start_line=$(echo "$all_logs" | grep -n "podkop.*Starting podkop" | tail -n 1 | cut -d: -f1)
|
||||||
|
|
||||||
|
if [ -z "$start_line" ]; then
|
||||||
|
nolog "No 'Starting podkop' message found in logs"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Output all logs from the last start
|
||||||
|
echo "$all_logs" | tail -n +"$start_line"
|
||||||
}
|
}
|
||||||
|
|
||||||
show_sing_box_config() {
|
show_sing_box_config() {
|
||||||
@@ -1918,6 +1931,7 @@ show_config() {
|
|||||||
-e 's/\(ss:\/\/[^@]*@\)/ss:\/\/MASKED@/g' \
|
-e 's/\(ss:\/\/[^@]*@\)/ss:\/\/MASKED@/g' \
|
||||||
-e 's/\(pbk=[^&]*\)/pbk=MASKED/g' \
|
-e 's/\(pbk=[^&]*\)/pbk=MASKED/g' \
|
||||||
-e 's/\(sid=[^&]*\)/sid=MASKED/g' \
|
-e 's/\(sid=[^&]*\)/sid=MASKED/g' \
|
||||||
|
-e 's/\(option dns_server '\''[^'\'']*\.dns\.nextdns\.io'\''\)/option dns_server '\''MASKED.dns.nextdns.io'\''/g' \
|
||||||
> "$tmp_config"
|
> "$tmp_config"
|
||||||
|
|
||||||
cat "$tmp_config"
|
cat "$tmp_config"
|
||||||
|
|||||||
Reference in New Issue
Block a user