added docker logs to diagnostic
This commit is contained in:
+55
-2
@@ -127,11 +127,15 @@
|
|||||||
<button class="tab-btn" data-tab="gateway" onclick="switchTab('gateway')">Gateway <span class="tab-count" id="count-gateway">0</span></button>
|
<button class="tab-btn" data-tab="gateway" onclick="switchTab('gateway')">Gateway <span class="tab-count" id="count-gateway">0</span></button>
|
||||||
<button class="tab-btn" data-tab="rvs" onclick="switchTab('rvs')">RVS <span class="tab-count" id="count-rvs">0</span></button>
|
<button class="tab-btn" data-tab="rvs" onclick="switchTab('rvs')">RVS <span class="tab-count" id="count-rvs">0</span></button>
|
||||||
<button class="tab-btn" data-tab="proxy" onclick="switchTab('proxy')">Proxy <span class="tab-count" id="count-proxy">0</span></button>
|
<button class="tab-btn" data-tab="proxy" onclick="switchTab('proxy')">Proxy <span class="tab-count" id="count-proxy">0</span></button>
|
||||||
|
<button class="tab-btn" data-tab="bridge" onclick="switchTab('bridge')">Bridge <span class="tab-count" id="count-bridge">0</span></button>
|
||||||
<button class="tab-btn" data-tab="server" onclick="switchTab('server')">Server <span class="tab-count" id="count-server">0</span></button>
|
<button class="tab-btn" data-tab="server" onclick="switchTab('server')">Server <span class="tab-count" id="count-server">0</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="log-panel">
|
<div class="log-panel">
|
||||||
<div class="log-header">
|
<div class="log-header">
|
||||||
|
<span>
|
||||||
|
<button class="btn secondary" id="btn-docker-logs" onclick="loadDockerLogs()" style="padding:4px 10px;font-size:11px;display:none">Docker Logs laden</button>
|
||||||
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<span class="pause-hint" id="pause-hint">Autoscroll pausiert</span>
|
<span class="pause-hint" id="pause-hint">Autoscroll pausiert</span>
|
||||||
<button class="btn secondary" id="btn-scroll" onclick="resumeScroll()" style="display:none;padding:4px 10px;font-size:11px">Nach unten</button>
|
<button class="btn secondary" id="btn-scroll" onclick="resumeScroll()" style="display:none;padding:4px 10px;font-size:11px">Nach unten</button>
|
||||||
@@ -141,6 +145,7 @@
|
|||||||
<div class="log-box hidden" id="log-gateway"></div>
|
<div class="log-box hidden" id="log-gateway"></div>
|
||||||
<div class="log-box hidden" id="log-rvs"></div>
|
<div class="log-box hidden" id="log-rvs"></div>
|
||||||
<div class="log-box hidden" id="log-proxy"></div>
|
<div class="log-box hidden" id="log-proxy"></div>
|
||||||
|
<div class="log-box hidden" id="log-bridge"></div>
|
||||||
<div class="log-box hidden" id="log-server"></div>
|
<div class="log-box hidden" id="log-server"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -151,14 +156,16 @@
|
|||||||
const btnScroll = document.getElementById('btn-scroll');
|
const btnScroll = document.getElementById('btn-scroll');
|
||||||
let ws;
|
let ws;
|
||||||
let activeTab = 'all';
|
let activeTab = 'all';
|
||||||
const autoScroll = { all: true, gateway: true, rvs: true, proxy: true, server: true };
|
const DOCKER_TABS = ['gateway', 'proxy', 'bridge'];
|
||||||
const logCounts = { all: 0, gateway: 0, rvs: 0, proxy: 0, server: 0 };
|
const autoScroll = { all: true, gateway: true, rvs: true, proxy: true, bridge: true, server: true };
|
||||||
|
const logCounts = { all: 0, gateway: 0, rvs: 0, proxy: 0, bridge: 0, server: 0 };
|
||||||
|
|
||||||
const logBoxes = {
|
const logBoxes = {
|
||||||
all: document.getElementById('log-all'),
|
all: document.getElementById('log-all'),
|
||||||
gateway: document.getElementById('log-gateway'),
|
gateway: document.getElementById('log-gateway'),
|
||||||
rvs: document.getElementById('log-rvs'),
|
rvs: document.getElementById('log-rvs'),
|
||||||
proxy: document.getElementById('log-proxy'),
|
proxy: document.getElementById('log-proxy'),
|
||||||
|
bridge: document.getElementById('log-bridge'),
|
||||||
server: document.getElementById('log-server'),
|
server: document.getElementById('log-server'),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -186,6 +193,8 @@
|
|||||||
activeTab = tab;
|
activeTab = tab;
|
||||||
document.querySelectorAll('.tab-btn').forEach(b => b.classList.toggle('active', b.dataset.tab === tab));
|
document.querySelectorAll('.tab-btn').forEach(b => b.classList.toggle('active', b.dataset.tab === tab));
|
||||||
Object.entries(logBoxes).forEach(([t, box]) => box.classList.toggle('hidden', t !== tab));
|
Object.entries(logBoxes).forEach(([t, box]) => box.classList.toggle('hidden', t !== tab));
|
||||||
|
// Docker Logs Button nur bei Tabs mit Containern
|
||||||
|
document.getElementById('btn-docker-logs').style.display = DOCKER_TABS.includes(tab) ? 'inline' : 'none';
|
||||||
// Pause-Hinweis aktualisieren
|
// Pause-Hinweis aktualisieren
|
||||||
const box = logBoxes[tab];
|
const box = logBoxes[tab];
|
||||||
const atBottom = box.scrollHeight - box.scrollTop - box.clientHeight < 30;
|
const atBottom = box.scrollHeight - box.scrollTop - box.clientHeight < 30;
|
||||||
@@ -209,6 +218,7 @@
|
|||||||
if (source === 'gateway') return 'gateway';
|
if (source === 'gateway') return 'gateway';
|
||||||
if (source === 'rvs') return 'rvs';
|
if (source === 'rvs') return 'rvs';
|
||||||
if (source === 'proxy') return 'proxy';
|
if (source === 'proxy') return 'proxy';
|
||||||
|
if (source === 'bridge') return 'bridge';
|
||||||
if (source === 'server' || source === 'browser') return 'server';
|
if (source === 'server' || source === 'browser') return 'server';
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -267,6 +277,10 @@
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (msg.type === 'docker_logs') {
|
||||||
|
showDockerLogs(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (msg.type === 'response') { return; }
|
if (msg.type === 'response') { return; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -295,6 +309,11 @@
|
|||||||
send({ action: 'test_proxy', text: 'Antworte mit genau einem Wort: Ping' });
|
send({ action: 'test_proxy', text: 'Antworte mit genau einem Wort: Ping' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadDockerLogs() {
|
||||||
|
if (!DOCKER_TABS.includes(activeTab)) return;
|
||||||
|
send({ action: 'docker_logs', tab: activeTab, tail: 200 });
|
||||||
|
}
|
||||||
|
|
||||||
function updateState(state) {
|
function updateState(state) {
|
||||||
// Gateway
|
// Gateway
|
||||||
const gw = state.gateway || {};
|
const gw = state.gateway || {};
|
||||||
@@ -350,6 +369,40 @@
|
|||||||
chatBox.scrollTop = chatBox.scrollHeight;
|
chatBox.scrollTop = chatBox.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showDockerLogs(msg) {
|
||||||
|
const tab = msg.tab;
|
||||||
|
const box = logBoxes[tab];
|
||||||
|
if (!box) return;
|
||||||
|
|
||||||
|
if (msg.error) {
|
||||||
|
appendToLog(tab, 'error', `Docker Logs Fehler: ${msg.error}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bestehende Eintraege leeren und Docker-Logs einfuegen
|
||||||
|
box.innerHTML = '';
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.className = 'log-entry info';
|
||||||
|
header.textContent = `── Docker Logs: ${msg.container} (letzte ${msg.lines.length} Zeilen) ──`;
|
||||||
|
box.appendChild(header);
|
||||||
|
|
||||||
|
for (const line of msg.lines) {
|
||||||
|
const el = document.createElement('div');
|
||||||
|
el.className = 'log-entry ' + (line.match(/\b(error|Error|ERROR)\b/) ? 'error' :
|
||||||
|
line.match(/\b(warn|Warning|WARN)\b/) ? 'warn' : 'info');
|
||||||
|
el.textContent = line;
|
||||||
|
box.appendChild(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zähler aktualisieren
|
||||||
|
logCounts[tab] = msg.lines.length;
|
||||||
|
const countEl = document.getElementById(`count-${tab}`);
|
||||||
|
if (countEl) countEl.textContent = logCounts[tab];
|
||||||
|
|
||||||
|
box.scrollTop = box.scrollHeight;
|
||||||
|
autoScroll[tab] = true;
|
||||||
|
}
|
||||||
|
|
||||||
function escapeHtml(str) {
|
function escapeHtml(str) {
|
||||||
return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,6 +409,66 @@ async function testProxy(prompt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Docker Container Logs ────────────────────────────────
|
||||||
|
|
||||||
|
const CONTAINER_MAP = {
|
||||||
|
gateway: "aria-core",
|
||||||
|
proxy: "aria-proxy",
|
||||||
|
bridge: "aria-bridge",
|
||||||
|
};
|
||||||
|
|
||||||
|
function fetchDockerLogs(tab, tail) {
|
||||||
|
const containerName = CONTAINER_MAP[tab];
|
||||||
|
if (!containerName) return;
|
||||||
|
|
||||||
|
const lines = parseInt(tail, 10) || 100;
|
||||||
|
const dockerPath = `/containers/${containerName}/logs?stdout=true&stderr=true&tail=${lines}×tamps=true`;
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const req = http.request(
|
||||||
|
{ socketPath: "/var/run/docker.sock", path: dockerPath, method: "GET" },
|
||||||
|
(res) => {
|
||||||
|
const chunks = [];
|
||||||
|
res.on("data", (chunk) => chunks.push(chunk));
|
||||||
|
res.on("end", () => {
|
||||||
|
// Docker log stream hat 8-byte Header pro Frame (stream type + size)
|
||||||
|
const raw = Buffer.concat(chunks);
|
||||||
|
const logLines = [];
|
||||||
|
let offset = 0;
|
||||||
|
while (offset < raw.length) {
|
||||||
|
if (offset + 8 > raw.length) break;
|
||||||
|
const size = raw.readUInt32BE(offset + 4);
|
||||||
|
if (offset + 8 + size > raw.length) break;
|
||||||
|
const line = raw.slice(offset + 8, offset + 8 + size).toString("utf-8").trimEnd();
|
||||||
|
if (line) logLines.push(line);
|
||||||
|
offset += 8 + size;
|
||||||
|
}
|
||||||
|
resolve(logLines);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
req.on("error", (err) => reject(err));
|
||||||
|
req.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDockerLogs(ws, tab, tail) {
|
||||||
|
const containerName = CONTAINER_MAP[tab];
|
||||||
|
if (!containerName) {
|
||||||
|
ws.send(JSON.stringify({ type: "docker_logs", tab, error: `Unbekannter Tab: ${tab}` }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
log("info", "server", `Lade Docker-Logs: ${containerName} (tail ${tail || 100})`);
|
||||||
|
const lines = await fetchDockerLogs(tab, tail);
|
||||||
|
ws.send(JSON.stringify({ type: "docker_logs", tab, container: containerName, lines }));
|
||||||
|
} catch (err) {
|
||||||
|
log("error", "server", `Docker-Logs Fehler (${containerName}): ${err.message}`);
|
||||||
|
ws.send(JSON.stringify({ type: "docker_logs", tab, error: err.message }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Hilfsfunktionen ─────────────────────────────────────
|
// ── Hilfsfunktionen ─────────────────────────────────────
|
||||||
|
|
||||||
function waitForMessage(ws, timeoutMs) {
|
function waitForMessage(ws, timeoutMs) {
|
||||||
@@ -462,6 +522,8 @@ wss.on("connection", (ws) => {
|
|||||||
connectRVS();
|
connectRVS();
|
||||||
} else if (msg.action === "test_proxy") {
|
} else if (msg.action === "test_proxy") {
|
||||||
testProxy(msg.text);
|
testProxy(msg.text);
|
||||||
|
} else if (msg.action === "docker_logs") {
|
||||||
|
handleDockerLogs(ws, msg.tab, msg.tail);
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- aria
|
- aria
|
||||||
network_mode: "service:aria" # Teilt Netzwerk mit aria-core → localhost:18789
|
network_mode: "service:aria" # Teilt Netzwerk mit aria-core → localhost:18789
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
environment:
|
environment:
|
||||||
- ARIA_AUTH_TOKEN=${ARIA_AUTH_TOKEN:-}
|
- ARIA_AUTH_TOKEN=${ARIA_AUTH_TOKEN:-}
|
||||||
- PROXY_URL=http://proxy:3456
|
- PROXY_URL=http://proxy:3456
|
||||||
|
|||||||
Reference in New Issue
Block a user