Stabilize diagnostic export and preserve authorized policy continuity
This commit is contained in:
1 parent
0a5df7398e
commit
09bf616d98
18 files changed
+364
-57
No files matched your search
@@ -0,0 +1,17 @@
|
||||
import {performance} from 'node:perf_hooks';
|
||||
|
||||
// Bounds unfinished HTTP bodies and committed-work admission together. This is
|
||||
// diagnostic telemetry, separate from the durable security-event pipeline.
|
||||
export function collectorAdmission({maxRequests=8,maxBufferedBytes=8*1024*1024,maxRequestBytes=2*1024*1024,clock=()=>performance.now(),defer=setImmediate}={}){
|
||||
if([maxRequests,maxBufferedBytes,maxRequestBytes].some(value=>!Number.isSafeInteger(value)||value<1)||maxRequests>64||maxBufferedBytes>64*1024*1024||maxRequestBytes>2*1024*1024||typeof clock!=='function'||typeof defer!=='function')throw TypeError('Invalid collector admission limits');
|
||||
let active=0,buffered=0,peakRequests=0,peakBufferedBytes=0,running=false;const queue=[];
|
||||
const counters={requestLimitRejected:0,bufferLimitRejected:0,bodyLimitRejected:0,commits:0,commitFailures:0,lastQueueWaitMs:0,maxQueueWaitMs:0,lastCommitMs:0,maxCommitMs:0};
|
||||
const duration=start=>Math.max(0,clock()-start);
|
||||
function drain(){if(running||!queue.length)return;running=true;defer(async()=>{const job=queue.shift();if(!job){running=false;drain();return;}try{if(!job.live())throw Error('Collector request cancelled');const wait=duration(job.readyAt);counters.lastQueueWaitMs=wait;counters.maxQueueWaitMs=Math.max(counters.maxQueueWaitMs,wait);const start=clock();try{const result=await job.fn();counters.commits++;job.resolve(result);}catch(error){counters.commitFailures++;job.reject(error);}finally{const elapsed=duration(start);counters.lastCommitMs=elapsed;counters.maxCommitMs=Math.max(counters.maxCommitMs,elapsed);}}catch(error){job.reject(error);}finally{running=false;drain();}});}
|
||||
function acquire(){if(active>=maxRequests){counters.requestLimitRejected++;return null;}active++;peakRequests=Math.max(peakRequests,active);let bytes=0,released=false,enqueued=false,queuedJob;
|
||||
return {add(size){if(released||enqueued||!Number.isSafeInteger(size)||size<0)throw Error('Collector admission unavailable');if(bytes+size>maxRequestBytes){counters.bodyLimitRejected++;return 'body-limit';}if(buffered+size>maxBufferedBytes){counters.bufferLimitRejected++;return 'buffer-limit';}bytes+=size;buffered+=size;peakBufferedBytes=Math.max(peakBufferedBytes,buffered);return null;},
|
||||
enqueue(fn){if(released||enqueued||typeof fn!=='function')return Promise.reject(Error('Collector admission unavailable'));enqueued=true;return new Promise((resolve,reject)=>{queuedJob={fn,resolve,reject,readyAt:clock(),live:()=>!released};queue.push(queuedJob);drain();});},
|
||||
release(){if(released)return;released=true;active--;buffered-=bytes;bytes=0;if(queuedJob){const index=queue.indexOf(queuedJob);if(index>=0){queue.splice(index,1);queuedJob.reject(Error('Collector request cancelled'));}}}};
|
||||
}
|
||||
return {acquire,summary:()=>({maxRequests,maxBufferedBytes,maxRequestBytes,activeRequests:active,bufferedBytes:buffered,queuedCommits:queue.length,commitActive:running,peakRequests,peakBufferedBytes,...counters})};
|
||||
}
|
||||
Reference in new issue
Block a user