Files
html/api/l99-stress-test.js
2026-04-12 22:57:03 +02:00

140 lines
7.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const puppeteer=require('puppeteer-core'),fs=require('fs');
const R=[];let tp=0,tc=0;
function L(n,c,p,d=''){tc++;if(p)tp++;R.push({n,c,p,d,t:Date.now()});console.log(`${p?'V':'X'} ${n}|${c}|${d}`);}
(async()=>{
const b=await puppeteer.launch({executablePath:'/usr/bin/google-chrome',headless:'new',args:['--no-sandbox','--disable-gpu','--ignore-certificate-errors','--disable-dev-shm-usage']});
const start=Date.now();
// ══════════ STRESS 1: CONCURRENT LOAD (5 pages simultanées) ══════════
console.log('=== STRESS: CONCURRENT LOAD ===');
const urls=['https://weval-consulting.com/admin-saas.html','https://weval-consulting.com/agents-archi.html','https://weval-consulting.com/wevads-ia/','https://weval-consulting.com/enterprise-model.html','https://weval-consulting.com/architecture.html'];
const t0=Date.now();
const concurrent=await Promise.all(urls.map(async u=>{
const p=await b.newPage();const s=Date.now();
try{await p.goto(u,{waitUntil:'domcontentloaded',timeout:15000});const h=await p.content();await p.close();return{u,ok:true,ms:Date.now()-s,sz:h.length};}
catch(e){await p.close();return{u,ok:false,ms:Date.now()-s,sz:0};}
}));
const concMs=Date.now()-t0;
const allOk=concurrent.every(c=>c.ok);
L('Stress','5_concurrent_pages',allOk,`${concMs}ms total`);
concurrent.forEach(c=>L('Stress',`load_${c.u.split('/').pop()}`,c.ok,`${c.ms}ms ${c.sz}b`));
L('Stress','concurrent_under_5s',concMs<5000,`${concMs}ms`);
// ══════════ STRESS 2: RAPID FIRE API (10 calls < 3s) ══════════
console.log('\n=== STRESS: RAPID FIRE API ===');
const p=await b.newPage();
await p.goto('https://weval-consulting.com',{waitUntil:'domcontentloaded',timeout:10000});
const apiStart=Date.now();
const apiResults=await p.evaluate(async()=>{
const apis=['/api/ecosystem-health.php','/api/agents-full-count.php','/api/execution-map.json',
'/api/nonreg-api.php?cat=summary','/api/wevia-master-autoheal.php',
'/api/agents-status.php','/api/agents-catalog.php',
'/api/ecosystem-health.php','/api/agents-full-count.php','/api/execution-map.json'];
const results=[];
for(const url of apis){
const s=performance.now();
try{const r=await fetch(url);const t=await r.text();results.push({url,ok:r.status===200,ms:Math.round(performance.now()-s),sz:t.length});}
catch(e){results.push({url,ok:false,ms:Math.round(performance.now()-s),sz:0});}
}
return results;
});
const apiMs=Date.now()-apiStart;
apiResults.forEach(a=>L('API_Stress',a.url.split('/').pop(),a.ok,`${a.ms}ms`));
L('API_Stress','10_calls_under_3s',apiMs<3000,`${apiMs}ms`);
// ══════════ STRESS 3: CHAT RESPONSE TIME ══════════
console.log('\n=== STRESS: CHAT LATENCY ===');
const chatStart=Date.now();
const chatResp=await p.evaluate(async()=>{
const s=performance.now();
const r=await fetch('/api/weval-ia',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:'2+2?',provider:'groq'})});
const t=await r.json();
return{ms:Math.round(performance.now()-s),ok:!!(t.result||t.response),txt:(t.result||t.response||'').substring(0,50)};
});
L('Chat','groq_response',chatResp.ok,`${chatResp.ms}ms "${chatResp.txt}"`);
L('Chat','groq_under_5s',chatResp.ms<5000,`${chatResp.ms}ms`);
// ══════════ STRESS 4: RESILIENCE — RAPID RELOAD ══════════
console.log('\n=== STRESS: RESILIENCE ===');
let reloadOk=0;
for(let i=0;i<5;i++){
await p.goto('https://weval-consulting.com/admin-saas.html',{waitUntil:'domcontentloaded',timeout:8000});
const h=await p.content();
if(h.length>10000)reloadOk++;
}
L('Resilience','5_rapid_reloads',reloadOk===5,`${reloadOk}/5`);
// ══════════ STRESS 5: SUBDOMAIN PARALLEL ══════════
console.log('\n=== STRESS: SUBDOMAIN PARALLEL ===');
const subs=['crm','mirofish','paperclip','langfuse','deerflow','analytics','mm','monitor','n8n'];
const subStart=Date.now();
const subResults=await Promise.all(subs.map(async s=>{
const pg=await b.newPage();const st=Date.now();
try{await pg.goto(`https://${s}.weval-consulting.com/`,{waitUntil:'domcontentloaded',timeout:15000});const h=await pg.content();await pg.close();return{s,ok:true,ms:Date.now()-st,sz:h.length};}
catch(e){await pg.close();return{s,ok:false,ms:Date.now()-st};}
}));
const subMs=Date.now()-subStart;
subResults.forEach(s=>L('Sub_Stress',s.s,s.ok,`${s.ms}ms`));
L('Sub_Stress','9_parallel_under_10s',subMs<10000,`${subMs}ms`);
// ══════════ STRESS 6: PAPERCLIP LOGIN FLOW ══════════
console.log('\n=== STRESS: PAPERCLIP E2E ===');
const pp=await b.newPage();
const ppStart=Date.now();
await pp.goto('https://paperclip.weval-consulting.com/auth/sign-in',{waitUntil:'networkidle2',timeout:15000});
const inputs=await pp.$$('input');
if(inputs.length>=2){await inputs[0].type('ymahboub@weval-consulting.com');await inputs[1].type('Weval2026!');}
const btns=await pp.$$('button');if(btns.length>0)await btns[btns.length-1].click();
await pp.waitForNavigation({timeout:10000}).catch(()=>{});
const ppHtml=await pp.content();
const ppMs=Date.now()-ppStart;
L('Paperclip_E2E','login_complete',ppHtml.length>2000,`${ppMs}ms`);
L('Paperclip_E2E','under_15s',ppMs<15000,`${ppMs}ms`);
await pp.close();
// ══════════ STRESS 7: BUSINESS KPI VALIDATION (6σ) ══════════
console.log('\n=== 6σ BUSINESS KPIs ===');
const ecoRaw=await p.evaluate(async()=>{const r=await fetch('/api/ecosystem-health.php');return await r.text();});
try{
const eco=JSON.parse(ecoRaw);
L('6sigma','L99_pass_rate>99%',eco.l99.pass/eco.l99.total>0.99,`${Math.round(100*eco.l99.pass/eco.l99.total)}%`);
L('6sigma','docker_healthy',eco.infra.docker>=15,`${eco.infra.docker}`);
L('6sigma','disk<90%',parseInt(eco.infra.disk)<90,eco.infra.disk);
L('6sigma','oss>700',eco.ecosystem.oss>700,`${eco.ecosystem.oss}`);
L('6sigma','skills>600',eco.ecosystem.skills>600,`${eco.ecosystem.skills}`);
L('6sigma','qdrant>10K',eco.providers.qdrant>10000,`${eco.providers.qdrant}`);
L('6sigma','sovereign>10',eco.ecosystem.sovereign_ias>10,`${eco.ecosystem.sovereign_ias}`);
}catch(e){L('6sigma','ecosystem_parse',false);}
const agRaw=await p.evaluate(async()=>{const r=await fetch('/api/agents-full-count.php');return await r.text();});
try{const ag=JSON.parse(agRaw);L('6sigma','agents>5000',ag.total>5000,`${ag.total}`);}catch(e){}
const emRaw=await p.evaluate(async()=>{const r=await fetch('/api/execution-map.json');return await r.text();});
try{const em=JSON.parse(emRaw);L('6sigma','providers>=9',Object.keys(em).length>=9,`${Object.keys(em).length}`);}catch(e){}
// ══════════ STRESS 8: ToC BOTTLENECK ══════════
console.log('\n=== ToC BOTTLENECK ===');
const times=apiResults.map(a=>a.ms);
const maxApi=Math.max(...times);const avgApi=Math.round(times.reduce((a,b)=>a+b)/times.length);
L('ToC','api_avg<500ms',avgApi<500,`avg=${avgApi}ms`);
L('ToC','api_max<2s',maxApi<2000,`max=${maxApi}ms`);
L('ToC','bottleneck_id',true,maxApi>1000?`SLOW: ${apiResults.find(a=>a.ms===maxApi)?.url}`:'No bottleneck');
const totalMs=Date.now()-start;
L('ToC','total_stress<60s',totalMs<60000,`${totalMs}ms`);
await p.close();
await b.close();
// SUMMARY
const pct=Math.round(100*tp/tc);
console.log(`\n${'='.repeat(60)}`);
console.log(`L99 STRESS 6σ/Lean/ToC: ${tp}/${tc} = ${pct}%`);
console.log(`Total time: ${Date.now()-start}ms`);
console.log(`${'='.repeat(60)}`);
const fails=R.filter(r=>!r.p);
if(fails.length)fails.forEach(f=>console.log(` X ${f.n}|${f.c}|${f.d}`));
try{fs.writeFileSync('/tmp/l99-stress-results.json',JSON.stringify({ts:new Date().toISOString(),total:tc,pass:tp,fail:tc-tp,pct,totalMs:Date.now()-start,results:R},null,2));}catch(e){}
})();