// UPLOAD (PUT ohne Antwort, echte Bandbreite) let maxUpload = 0; async function measureUpload() {if (stopMode) return; const size = 1024 * 1024; // 1 MB const data = new Uint8Array(size); const start = performance.now(); try {await fetch("/upload.php?ignore=1", {method: "PUT",body: data,cache: "no-store"}); const sec = (performance.now() - start) / 1000; const mbps = (size * 8 / 1e6) / sec; if (mbps > maxUpload) maxUpload = mbps; getEl("ht-upload").textContent = maxUpload.toFixed(2) + " Mbit/s";} catch (e) {getEl("ht-upload").textContent = "⏳";} } // PING (HEAD auf robots.txt, echte RTT) let bestPing = Infinity; async function measurePing() { if (stopMode) return; const el = getEl("ht-ping"); if (!el) return; const start = performance.now(); try {await fetch("/robots.txt", {method: "HEAD",cache: "no-store"}); const ms = performance.now() - start; if (ms < bestPing) bestPing = ms; el.textContent = bestPing.toFixed(0) + " ms";} catch (e) {el.textContent = "⏳";} } // Ladezeit function measureLoadTimes(){if (stopMode) return;const msL = performance.now() - window.tmStart;setLoad(msL.toFixed(0) + " ms");} window.addEventListener("load", () => {measureLoadTimes();});
// UPDATE function upd(force) { if (stopMode && !force) return; const now = Date.now(); while (ts.length && now - ts[0].t > WIN) ts.shift(); while (tsHTML.length && now - tsHTML[0].t > WIN) tsHTML.shift(); const htmlInhalte = tsHTML.length, htmlBytes = tsHTML.reduce((a, b) => a + b.size, 0); getEl("tcontent").textContent = htmlInhalte; getEl("tbytes").textContent = (htmlBytes / 1024).toFixed(1) + " KB"; bf.textContent = fC;bx.textContent = xC;be.textContent = eC;tf.textContent = fC;tx.textContent = xC;te.textContent = eC; let f = 0, x = 0; for (const p of ts) {if (p.type === "fetch") f++;else x++;} gf.textContent = f; gx.textContent = x; // Top-URLs effizient rendern (unverändert, aber minimal schneller) let topHTML = ""; const entries = Object.entries(urls); if (entries.length) {const sorted = entries.sort((a, b) => b[1] - a[1]).slice(0, MAX_T); for (const [u, c] of sorted) {topHTML += `<div>• <span class="ht-url">${u}</span> (${c})</div>`;}} else {topHTML = "<div>Keine</div>";} tu.innerHTML = topHTML; // HISTORIE-Rendering optimiert (keine Flicker, keine Reflows) let histHTML = ""; if (hist.length) { const items = hist.slice(0, 20); // nur die letzten 20 for (const h of items) { histHTML += ` <div class="ht-history-item"> <div class="ht-history-line1"> <span class="ht-h-time">${h.time}</span> <span class="ht-h-type">${h.type === "sonstige" ? "SONST." : h.type.toUpperCase()}</span> <span class="ht-h-dur">${h.duration.toFixed(1)} ms</span> <span class="ht-h-status ${h.status >= 500 ? "ht-status-error" : h.status >= 400 ? "ht-status-warn" : "ht-status-ok"}">Status: ${h.status} ${h.statusText || ""}</span> </div> <div class="ht-history-line2"><span class="ht-h-url">• ${h.url}</span></div> </div> `;} } else {histHTML = `<div class="ht-history-item"><div class="ht-history-line1">Keine</div></div>`;} hi.innerHTML = histHTML; // Verbindung const et = navigator.connection?.effectiveType || "?",etUp = et.toUpperCase(); let etColor = "var(--ht-green)"; if (et === "3g") etColor = "var(--ht-warn)";if (et.includes("2g")) etColor = "var(--ht-red)"; getEl("ht-conn").textContent = etUp; getEl("ht-conn").style.color = etColor; // SESSIONSTORAGE-Optimierung (nur speichern, wenn nötig) try { // Nur die letzten 20 History-Einträge speichern const histSmall = hist.slice(0, 20); // Nur die Top-20 URLs speichern const urlsSmall = Object.entries(urls).sort((a, b) => b[1] - a[1]).slice(0, 20).reduce((o, [u, c]) => (o[u] = c, o), {}); // Hash erzeugen const hash = JSON.stringify({fC, xC, eC,hist: histSmall,urls: urlsSmall}); // Nur speichern, wenn sich etwas geändert hat if (sessionStorage.lastHash !== hash) {sessionStorage.lastHash = hash;sessionStorage.fC = fC;sessionStorage.xC = xC;sessionStorage.eC = eC;sessionStorage.hist = JSON.stringify(histSmall);sessionStorage.urls = JSON.stringify(urlsSmall);} } catch (e) {} }
// UPDATE-Limiter (max 4 Updates/Sekunde) let lastUpd = 0; let updPending = false; function updDebounced() { const now = performance.now(); // Nur alle 250 ms ein Update zulassen if (now - lastUpd < 250) {if (!updPending) {updPending = true;setTimeout(() => {upd(true);lastUpd = performance.now();updPending = false;}, 250 - (now - lastUpd));}return;} // Sofortiges Update lastUpd = now; upd(true); }
// OBSERVER - Nur relevante Events erfassen (Fetch/XHR) const perfObs = new PerformanceObserver(list => { if (stopMode) return; for (const e of list.getEntries()) {const type = e.initiatorType; if (type !== "fetch" && type !== "xmlhttprequest") continue; const url = e.name;
// Eigene Monitor-Requests ignorieren - Speed-Test, Upload-Test, Ping-Test if (url.includes("a_901_bcb5af44.png") || url.includes("/upload.php") || url.includes("/robots.txt")) continue; const status = e.responseStatus || 200;
<!-- PopUp "Konsole öffnen" --> <div id="tm-info-overlay"><div id="tm-info-box"><div id="tm-info-close" onclick="tm_closeInfo()">×</div> <h2>🔥 Konsole öffnen</h2> <p>Um die Browser-Konsole zu öffnen, drücke:<br><br><strong>F12</strong> oder <strong>Ctrl + Shift + I</strong></p><br> <p>Wähle danach den Reiter <strong>Console</strong>.</p> <p>Dort kannst du:<br>• Test-Anfragen sehen <br>• Fehler erkennen <br>• Netzwerk-Infos prüfen</p></div> </div> `); </script>
<script> // Ansicht Console F12 oder Ctrl + Shift + I function tm_log(msg){console.log("%c[TM‑TEST] "+msg,"color:#0f0"); }
// Serveranfrage per FETCH function tm_fetch(n=1){tm_log("Fetch × "+n);for(let i=0;i<n;i++){fetch(location.pathname + "?tm_fetch="+Math.random(), {cache:"no-store"}).then(r => r.text().catch(()=>'')).catch(()=>{});}}
// Serveranfrage per XHR function tm_xhr(n=1){tm_log("XHR × "+n);for(let i=0;i<n;i++){const x = new XMLHttpRequest();x.open("GET", location.pathname + "?tm_xhr="+Math.random());x.onerror = ()=>{};x.onload = ()=>{};x.send();}}
// HTML - Loads function tm_html(n=1){tm_log("HTML × " + n);for(let i=0;i<n;i++){fetch(location.pathname + "?nav=" + Math.random(), {cache:"no-store"}).then(r => r.text()).catch(()=>{});}}
// MIX function tm_mix(){tm_log("Mix‑Test"); tm_fetch(10); tm_xhr(10); tm_html(3);}
// RANDOM - LOAD let tm_rand_int=null; function tm_random(){tm_log("Random‑Load 5s");let end=Date.now()+5000;tm_rand_int=setInterval(()=>{let r=Math.random();if(r<0.33) tm_fetch(3);else if(r<0.66) tm_xhr(3);else tm_html(1);if(Date.now()>end){clearInterval(tm_rand_int); tm_log("Random‑Load beendet");}},150);}
// STOP function tm_stop(){tm_log("STOP");if(tm_rand_int){clearInterval(tm_rand_int); tm_rand_int=null;}}
// POPUP Consolen-Info function tm_showInfo(){document.getElementById("tm-info-overlay").style.display="block";} function tm_closeInfo(){document.getElementById("tm-info-overlay").style.display="none";} </script>
vielen Dank, der Einbau bottom_header hat problemlos geklappt. Jetzt komm ich mir ein bisschen vor wie ein Zauberlehrling... Ist das Tool überhaupt was für jemanden so unbedarft wie mich?
Jedenfalls war ich beruhigt, dass Fehler erstmal als 0 angezeigt wurden. Dann hab ich in dem linken Forum-Test-Fensterchen ein bisschen ahnungslos herumgeklickt und dann kamen doch 3 Fehler auf. Also fn+F12 für die Konsole, Tab Konsole gewählt und sehe 2 Matomo-Fehler, auch rechts bei "Errors" nur 2, die 2. Die gabs aber schon immer, normal glaub ich... aber wo bleibt der 3. Fehler...?
Gibt es irgendwo eine Einführung "für Dummies" in die Bedeutung und Tragweite der Zahlen?