From e3e5becf5b87297c5af7170755ead3f2534ac1ad Mon Sep 17 00:00:00 2001 From: Thomas Ciesla Date: Thu, 8 Jan 2026 09:26:02 +0100 Subject: [PATCH] server req/min --- jtl-wafi-dashboard.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/jtl-wafi-dashboard.py b/jtl-wafi-dashboard.py index 6170edb..2584260 100644 --- a/jtl-wafi-dashboard.py +++ b/jtl-wafi-dashboard.py @@ -1463,6 +1463,9 @@ def get_dashboard_html() -> str: .stat-value.success { color: var(--success); } .stat-value.warning { color: var(--warning); } .stat-value.danger { color: var(--danger); } + td.success { color: var(--success); } + td.warning { color: var(--warning); } + td.danger { color: var(--danger); } .stat-value.link11 { color: var(--link11); } .stat-value.direct { color: var(--danger); } .top-shops-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px; padding: 20px; margin-bottom: 24px; } @@ -1616,7 +1619,7 @@ def get_dashboard_html() -> str:

πŸ–₯️ Server

0
-
Status⇅Hostname⇅Shops⇅Load⇅Memory⇅Zuletzt⇅Aktionen
+
Status⇅Hostname⇅Shops⇅Human/min⇅Bot/min⇅Load⇅Memory⇅Zuletzt⇅Aktionen

πŸ›‘οΈ Shops hinter Link11

0
@@ -1679,16 +1682,17 @@ def get_dashboard_html() -> str: function scheduleRender(){pendingRender=true;} // Sort state fΓΌr jede Tabelle let sortState={agents:{col:null,asc:false},link11:{col:null,asc:false},direct:{col:null,asc:false}}; - function updateSortIcons(tableId,col,asc){const table=document.getElementById(tableId);if(!table)return;table.querySelectorAll('th.sortable').forEach(th=>{th.classList.remove('asc','desc');const icon=th.querySelector('.sort-icon');if(icon)icon.textContent='β‡…';});if(col){const ths=table.querySelectorAll('th.sortable');ths.forEach(th=>{if(th.textContent.replace('β‡…','').trim().toLowerCase().includes(col.substring(0,3))){th.classList.add(asc?'asc':'desc');const icon=th.querySelector('.sort-icon');if(icon)icon.textContent=asc?'β–²':'β–Ό';}});}} + function updateSortIcons(tableId,col,asc){const table=document.getElementById(tableId);if(!table)return;table.querySelectorAll('th.sortable').forEach(th=>{th.classList.remove('asc','desc');const icon=th.querySelector('.sort-icon');if(icon)icon.textContent='β‡…';});if(col){const colMap={status:'sta',hostname:'hos',shops:'sho',human_rpm:'hum',bot_rpm:'bot',load:'loa',memory:'mem',last_seen:'zul',domain:'dom',server:'ser',modus:'mod',req:'req',bans:'ban',runtime:'lau'};const matchStr=colMap[col]||col.substring(0,3);const ths=table.querySelectorAll('th.sortable');ths.forEach(th=>{if(th.textContent.replace('β‡…','').trim().toLowerCase().includes(matchStr)){th.classList.add(asc?'asc':'desc');const icon=th.querySelector('.sort-icon');if(icon)icon.textContent=asc?'β–²':'β–Ό';}});}} function sortAgents(col){const st=sortState.agents;if(st.col===col){st.asc=!st.asc;}else{st.col=col;st.asc=false;}renderAgents();updateSortIcons('agentsTable',col,st.asc);} function sortShops(type,col){const st=sortState[type];if(st.col===col){st.asc=!st.asc;}else{st.col=col;st.asc=false;}renderShops();const tableId=type==='link11'?'tableLink11':'tableDirect';updateSortIcons(tableId,col,st.asc);} - function getSortedAgents(){const list=Object.values(agents);const st=sortState.agents;if(!st.col)return list;const dir=st.asc?1:-1;return list.sort((a,b)=>{let va,vb;switch(st.col){case'status':const order={online:3,pending:2,offline:1};va=order[a.status]||0;vb=order[b.status]||0;break;case'hostname':va=(a.hostname||'').toLowerCase();vb=(b.hostname||'').toLowerCase();return dir*(vavb?1:0);case'shops':va=(a.shops_active||0);vb=(b.shops_active||0);break;case'load':va=(a.load_1m||0);vb=(b.load_1m||0);break;case'memory':va=(a.memory_percent||0);vb=(b.memory_percent||0);break;case'last_seen':va=a.last_seen||'';vb=b.last_seen||'';return dir*(vavb?1:0);default:return 0;}return dir*(va-vb);});} + function getSortedAgents(){const list=Object.values(agents);const st=sortState.agents;if(!st.col)return list;const dir=st.asc?1:-1;return list.sort((a,b)=>{let va,vb;switch(st.col){case'status':const order={online:3,pending:2,offline:1};va=order[a.status]||0;vb=order[b.status]||0;break;case'hostname':va=(a.hostname||'').toLowerCase();vb=(b.hostname||'').toLowerCase();return dir*(vavb?1:0);case'shops':va=(a.shops_active||0);vb=(b.shops_active||0);break;case'human_rpm':const rpmA=getAgentRpm(a.id);va=rpmA.humanRpm;const rpmB_h=getAgentRpm(b.id);vb=rpmB_h.humanRpm;break;case'bot_rpm':const rpmA_b=getAgentRpm(a.id);va=rpmA_b.botRpm;const rpmB_b=getAgentRpm(b.id);vb=rpmB_b.botRpm;break;case'load':va=(a.load_1m||0);vb=(b.load_1m||0);break;case'memory':va=(a.memory_percent||0);vb=(b.memory_percent||0);break;case'last_seen':va=a.last_seen||'';vb=b.last_seen||'';return dir*(vavb?1:0);default:return 0;}return dir*(va-vb);});} function getSortedShops(list,type){const st=sortState[type];if(!st.col)return list;const dir=st.asc?1:-1;return list.sort((a,b)=>{let va,vb;switch(st.col){case'status':va=a.status==='active'?1:0;vb=b.status==='active'?1:0;break;case'domain':va=(a.domain||'').toLowerCase();vb=(b.domain||'').toLowerCase();return dir*(vavb?1:0);case'server':va=(a.agent_hostname||'').toLowerCase();vb=(b.agent_hostname||'').toLowerCase();return dir*(vavb?1:0);case'modus':va=(a.mode||'').toLowerCase();vb=(b.mode||'').toLowerCase();return dir*(vavb?1:0);case'req':va=(a.stats?.req_per_min||0);vb=(b.stats?.req_per_min||0);break;case'bans':va=((a.stats?.active_bot_bans||0)+(a.stats?.active_country_bans||0));vb=((b.stats?.active_bot_bans||0)+(b.stats?.active_country_bans||0));break;case'runtime':va=(a.runtime_minutes||0);vb=(b.runtime_minutes||0);break;default:return 0;}return dir*(va-vb);});} function updateClock(){document.getElementById('clock').textContent=new Date().toLocaleTimeString('de-DE');} setInterval(updateClock,1000);updateClock(); function connect(){const p=location.protocol==='https:'?'wss:':'ws:';ws=new WebSocket(p+'//'+location.host+'/ws/dashboard');ws.onopen=()=>{document.getElementById('wsStatus').classList.add('connected');document.getElementById('wsStatusText').textContent='Verbunden';};ws.onclose=()=>{document.getElementById('wsStatus').classList.remove('connected');document.getElementById('wsStatusText').textContent='Getrennt';setTimeout(connect,3000);};ws.onmessage=e=>handleMessage(JSON.parse(e.data));} function handleMessage(msg){switch(msg.type){case'initial_state':case'refresh':agents={};msg.data.agents.forEach(a=>agents[a.id]=a);shops={};msg.data.shops.forEach(s=>shops[s.domain]=s);updateStats(msg.data.stats);renderAgents();renderShops();renderTopShops();break;case'agent.online':case'agent.update':case'agent.pending':const a=msg.data;if(!agents[a.agent_id])agents[a.agent_id]={};Object.assign(agents[a.agent_id],{id:a.agent_id,hostname:a.hostname,status:a.status||'online',approved:a.approved,shops_total:a.shops_summary?.total||0,shops_active:a.shops_summary?.active||0,load_1m:a.system?.load_1m,memory_percent:a.system?.memory_percent,last_seen:new Date().toISOString()});scheduleRender();break;case'agent.offline':if(agents[msg.data.agent_id]){agents[msg.data.agent_id].status='offline';scheduleRender();}break;case'agent.approved':if(agents[msg.data.agent_id]){agents[msg.data.agent_id].status='online';agents[msg.data.agent_id].approved=true;scheduleRender();toast('Agent freigegeben','success');}break;case'shop.full_update':msg.data.shops.forEach(s=>{shops[s.domain]={...s,agent_id:msg.data.agent_id,agent_hostname:msg.data.hostname};});scheduleRender();break;case'shop.stats':if(shops[msg.data.domain]){shops[msg.data.domain].stats=msg.data.stats;scheduleRender();}break;case'shop_history':updateBotChart(msg.data);updateCountryChart(msg.data);break;case'top_shops':case'all_shops_sorted':renderAllShopsTable(msg.data.shops,msg.data.sort_by);break;case'log.entry':if(msg.data.shop===currentLogsShop)addLogEntry(msg.data.line);break;case'bot.banned':toast('🚫 '+msg.data.bot_name+' gebannt','warning');break;case'command.result':toast(msg.data.message,msg.data.status==='success'?'success':'error');break;case'livestats.result':renderLiveStats(msg.data);break;}} - function renderAgents(){const t=document.getElementById('agentsTable'),l=getSortedAgents();document.getElementById('agentCount').textContent=l.length+' Agents';document.getElementById('agentCountDropdown').textContent=l.length;t.innerHTML=l.map(a=>''+(a.status==='online'?'🟒':a.status==='pending'?'🟑':'πŸ”΄')+' '+(a.status==='pending'?'Warte':a.status==='online'?'Online':'Offline')+''+a.hostname+''+(a.shops_active||0)+'/'+(a.shops_total||0)+''+(a.load_1m!=null?a.load_1m.toFixed(2):'-')+''+(a.memory_percent!=null?a.memory_percent.toFixed(1)+'%':'-')+''+(a.last_seen?formatTime(a.last_seen):'-')+''+(a.status==='pending'?'':'')+'').join('');} + function getAgentRpm(agentId){const agentShops=Object.values(shops).filter(s=>s.agent_id===agentId);let humanRpm=0,botRpm=0;agentShops.forEach(s=>{const st=s.stats||{};humanRpm+=(st.human_rpm||0);botRpm+=(st.bot_rpm||0);});return {humanRpm,botRpm};} + function renderAgents(){const t=document.getElementById('agentsTable'),l=getSortedAgents();document.getElementById('agentCount').textContent=l.length+' Agents';document.getElementById('agentCountDropdown').textContent=l.length;t.innerHTML=l.map(a=>{const rpm=getAgentRpm(a.id);return ''+(a.status==='online'?'🟒':a.status==='pending'?'🟑':'πŸ”΄')+' '+(a.status==='pending'?'Warte':a.status==='online'?'Online':'Offline')+''+a.hostname+''+(a.shops_active||0)+'/'+(a.shops_total||0)+''+rpm.humanRpm.toFixed(1)+''+rpm.botRpm.toFixed(1)+''+(a.load_1m!=null?a.load_1m.toFixed(2):'-')+''+(a.memory_percent!=null?a.memory_percent.toFixed(1)+'%':'-')+''+(a.last_seen?formatTime(a.last_seen):'-')+''+(a.status==='pending'?'':'')+'';}).join('');} function renderShops(){const all=Object.values(shops);let l11=all.filter(s=>s.link11),dir=all.filter(s=>!s.link11);l11=getSortedShops(l11,'link11');dir=getSortedShops(dir,'direct');document.getElementById('link11Count').textContent=l11.length+' Shops';document.getElementById('directCount').textContent=dir.length+' Shops';document.getElementById('shopsLink11Table').innerHTML=renderShopRows(l11);document.getElementById('shopsDirectTable').innerHTML=renderShopRows(dir);} function renderShopRows(l){return l.map(s=>{const modeStr=s.monitor_only?'πŸ” Monitor':((s.bot_mode?'πŸ€–':'')+(s.country_mode?' 🌍':''))||'-';const bansStr=s.monitor_only?'-':((s.stats?.active_bot_bans||0)+(s.stats?.active_country_bans||0));return ''+(s.status==='active'?'βœ…':'β­•')+''+s.domain+''+(s.agent_hostname||'-')+''+modeStr+''+((s.stats?.req_per_min||0).toFixed(1))+''+bansStr+''+formatRuntime(s.runtime_minutes)+'πŸ”—'+(s.status==='active'?'':'')+'';}).join('');} function renderTopShops(){const l=Object.values(shops).filter(s=>s.status==='active').sort((a,b)=>(b.stats?.req_per_min||0)-(a.stats?.req_per_min||0)).slice(0,10);document.getElementById('topShopsList').innerHTML=l.map(s=>{const bans=(s.stats?.active_bot_bans||0)+(s.stats?.active_country_bans||0);return '
'+s.domain+'
'+((s.stats?.req_per_min||0).toFixed(1))+' req/m'+bans+' bans
';}).join('')||'
Keine aktiven Shops
';}