diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8ab349cbc..3a8ed9c66 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -60,6 +60,7 @@
- Add VAE civitai scan metadata/preview
- More efficient in-browser callbacks
- Updated all system requirements
+ - UI log monitor will auto-reconnect to server on server restart
- Support controlnet manually downloads models in both standalone and diffusers format
For standalone, simply copy safetensors file to `models/control/controlnet` folder
For diffusers format, create folder with model name in `models/control/controlnet/`
diff --git a/javascript/logMonitor.js b/javascript/logMonitor.js
index ebdeb9137..18a945fa0 100644
--- a/javascript/logMonitor.js
+++ b/javascript/logMonitor.js
@@ -17,45 +17,61 @@ function dateToStr(ts) {
}
async function logMonitor() {
- if (logMonitorStatus) setTimeout(logMonitor, opts.logmonitor_refresh_period);
- if (!opts.logmonitor_show) return;
- logMonitorStatus = false;
- let res;
- try { res = await fetch('/sdapi/v1/log?clear=True'); } catch {}
- if (res?.ok) {
- logMonitorStatus = true;
- if (!logMonitorEl) {
- logMonitorEl = document.getElementById('logMonitorData');
- logMonitorEl.onscrollend = () => {
- const at_bottom = logMonitorEl.scrollHeight <= (logMonitorEl.scrollTop + logMonitorEl.clientHeight);
- if (at_bottom) logMonitorEl.parentElement.style = '';
- };
- }
- if (!logMonitorEl) return;
- const at_bottom = logMonitorEl.scrollHeight <= (logMonitorEl.scrollTop + logMonitorEl.clientHeight);
- const lines = await res.json();
- if (logMonitorEl && lines?.length > 0) logMonitorEl.parentElement.parentElement.style.display = opts.logmonitor_show ? 'block' : 'none';
- for (const line of lines) {
- try {
- const l = JSON.parse(line.replaceAll('\n', ' '));
- const row = document.createElement('tr');
- // row.style = 'padding: 10px; margin: 0;';
- const level = `
${l.level} | `;
- if (l.level === 'WARNING') logWarnings++;
- if (l.level === 'ERROR') logErrors++;
- const module = `${l.module} | `;
- row.innerHTML = `${dateToStr(l.created)} | ${level}${l.facility} | ${module}${l.msg} | `;
- logMonitorEl.appendChild(row);
- } catch (e) {
- console.log('logMonitor', e);
- console.error('logMonitor line', line);
- }
+ const addLogLine = (line) => {
+ try {
+ const l = JSON.parse(line.replaceAll('\n', ' '));
+ const row = document.createElement('tr');
+ // row.style = 'padding: 10px; margin: 0;';
+ const level = `${l.level} | `;
+ if (l.level === 'WARNING') logWarnings++;
+ if (l.level === 'ERROR') logErrors++;
+ const module = `${l.module} | `;
+ row.innerHTML = `${dateToStr(l.created)} | ${level}${l.facility} | ${module}${l.msg} | `;
+ logMonitorEl.appendChild(row);
+ } catch (e) {
+ console.log('logMonitor', e);
+ console.error('logMonitor line', line);
}
+ };
+
+ const cleanupLog = (atBottom) => {
while (logMonitorEl.childElementCount > 100) logMonitorEl.removeChild(logMonitorEl.firstChild);
- if (at_bottom) logMonitorEl.scrollTop = logMonitorEl.scrollHeight;
- else if (lines?.length > 0) logMonitorEl.parentElement.style = 'border-bottom: 2px solid var(--highlight-color);';
+ if (atBottom) logMonitorEl.scrollTop = logMonitorEl.scrollHeight;
+ else logMonitorEl.parentElement.style = 'border-bottom: 2px solid var(--highlight-color);';
document.getElementById('logWarnings').innerText = logWarnings;
document.getElementById('logErrors').innerText = logErrors;
+ };
+
+ // addLogLine(`{ "created": ${Date.now() / 1000}, "level":"DEBUG", "module":"ui", "facility":"logMonitor", "msg":"Log refresh" }`);
+ if (logMonitorStatus) setTimeout(logMonitor, opts.logmonitor_refresh_period);
+ else setTimeout(logMonitor, 10 * opts.logmonitor_refresh_period);
+ if (!opts.logmonitor_show) return;
+ logMonitorStatus = false;
+ if (!logMonitorEl) {
+ logMonitorEl = document.getElementById('logMonitorData');
+ logMonitorEl.onscrollend = () => {
+ const atBottom = logMonitorEl.scrollHeight <= (logMonitorEl.scrollTop + logMonitorEl.clientHeight);
+ if (atBottom) logMonitorEl.parentElement.style = '';
+ };
+ }
+ if (!logMonitorEl) return;
+ const atBottom = logMonitorEl.scrollHeight <= (logMonitorEl.scrollTop + logMonitorEl.clientHeight);
+ try {
+ const res = await fetch('/sdapi/v1/log?clear=False');
+ if (res?.ok) {
+ logMonitorStatus = true;
+ const lines = await res.json();
+ if (logMonitorEl && lines?.length > 0) logMonitorEl.parentElement.parentElement.style.display = opts.logmonitor_show ? 'block' : 'none';
+ for (const line of lines) addLogLine(line);
+ } else {
+ addLogLine(`{ "created": ${Date.now()}, "level":"ERROR", "module":"logMonitor", "facility":"ui", "msg":"Failed to fetch log: ${res?.status} ${res?.statusText}" }`);
+ logErrors++;
+ }
+ cleanupLog(atBottom);
+ } catch (err) {
+ addLogLine(`{ "created": ${Date.now()}, "level":"ERROR", "module":"logMonitor", "facility":"ui", "msg":"Failed to fetch log: server unreachable" }`);
+ logErrors++;
+ cleanupLog(atBottom);
}
}