30 lines
4.3 KiB
JavaScript
30 lines
4.3 KiB
JavaScript
'use strict';
|
|
// Explicitly authorized synthetic fixture only. Private bounded in-memory OTLP
|
|
// receiver; no real management policy, content, token or production exporter.
|
|
const http=require('node:http');
|
|
const {createDiagnostics}=require('../../apps/browser/diagnostics.cjs');
|
|
async function createFixtureDiagnostics({enabled,policy,audit}){
|
|
if(!enabled)return {persist:audit.persist,run:(_attributes,fn)=>fn(),stage:(_name,_attributes,fn)=>fn(),finish:async()=>({enabled:false})};
|
|
const batches=[];let storedBytes=0,invalid=0;const spans=()=>batches.flatMap(batch=>(batch.resourceSpans||[]).flatMap(resource=>(resource.scopeSpans||[]).flatMap(scope=>scope.spans||[])));
|
|
const server=http.createServer({maxHeaderSize:8192},async(request,response)=>{
|
|
if(request.method==='GET'&&/^\/api\/trace\/[a-f0-9]{32}$/.test(request.url)){const id=request.url.split('/').pop();response.setHeader('content-type','application/json');response.end(JSON.stringify({spans:spans().filter(span=>span.traceId===id)}));return;}
|
|
if(request.method!=='POST'||!['/v1/traces','/v1/logs'].includes(request.url)){response.writeHead(404);response.end();return;}
|
|
const chunks=[];let size=0;
|
|
try{for await(const chunk of request){size+=chunk.length;if(size>1048576||storedBytes+size>4194304)throw Error('fixed-budget');chunks.push(chunk);}const text=Buffer.concat(chunks).toString();if(text.includes('SYNTHETIC_PRIVATE')||text.includes('proxy-password')||text.includes('%PDF-'))throw Error('fixed-content');const value=JSON.parse(text);if(request.url==='/v1/traces')batches.push(value);storedBytes+=size;response.setHeader('content-type','application/json');response.end('{}');}catch{invalid++;response.writeHead(400);response.end('{}');}
|
|
});server.maxConnections=8;server.listen(0,'127.0.0.1');await new Promise(resolve=>server.once('listening',resolve));
|
|
const endpoint=`http://127.0.0.1:${server.address().port}`,diagnostics=createDiagnostics();let active;
|
|
policy.diagnostics={...policy.diagnostics,enabled:true,mode:'debug',endpoint,sampleRate:1,debugSampleRate:1,maxRecordAgeMs:120000};
|
|
if(!diagnostics.configure(policy.diagnostics,{policyVersion:policy.version,deviceId:'native-production-fixture'}))throw Error('fixture-diagnostics-unavailable');
|
|
return {
|
|
stage:(name,attributes,fn)=>diagnostics.span(name,attributes,fn),
|
|
async trace(traceId){if(!/^[a-f0-9]{32}$/.test(traceId))throw Error('fixture-trace-invalid');await diagnostics.flush();const response=await fetch(endpoint+'/api/trace/'+traceId);if(!response.ok)throw Error('fixture-trace-unavailable');return response.json();},
|
|
persist:event=>diagnostics.withCorrelation(active,()=>diagnostics.spanSync('browser.management',{operation:'audit.deliver',component:'management'},()=>audit.persist({...event,...diagnostics.correlation()}))),
|
|
run:(attributes,fn)=>diagnostics.span('browser.request',{operation:'broker.request',component:'network',...attributes},async()=>{active=diagnostics.correlation();try{return await fn();}finally{active=undefined;}}),
|
|
async finish(){
|
|
try{await diagnostics.flush();const status=diagnostics.status();if(status.failedExports||status.lifetimeFailedExports||invalid)throw Error('fixture-diagnostics-export-failed');const event=audit.events().find(value=>value.traceId);if(!event)throw Error('fixture-diagnostics-correlation-missing');const response=await fetch(endpoint+'/api/trace/'+event.traceId),trace=await response.json();const child=trace.spans.find(value=>value.spanId===event.spanId),parent=trace.spans.find(value=>value.spanId===child?.parentSpanId);if(!child||!parent||parent.name!=='browser.request'||BigInt(parent.endTimeUnixNano)<=BigInt(parent.startTimeUnixNano))throw Error('fixture-diagnostics-parent-missing');const stages=trace.spans.filter(value=>value.name.startsWith('browser.broker.')).map(value=>({name:value.name,parentSpanId:value.parentSpanId,durationMs:Number(BigInt(value.endTimeUnixNano)-BigInt(value.startTimeUnixNano))/1e6}));return {enabled:true,traceId:event.traceId,auditSpanId:event.spanId,parentSpanId:parent.spanId,spanCount:spans().length,storedBytes,stages,invalid,failedExports:status.failedExports,lifetimeFailedExports:status.lifetimeFailedExports};}
|
|
finally{await diagnostics.shutdown();server.closeAllConnections();await new Promise(resolve=>server.close(resolve));}
|
|
}
|
|
};
|
|
}
|
|
module.exports={createFixtureDiagnostics};
|