3. In your callApi function, parse the traceparent and create spans:
async callApi(prompt, promptfooContext) {
if (!promptfooContext?.traceparent) {
return { output: await yourLLMCall(prompt) };
}
// Parse traceparent
const matches = promptfooContext.traceparent.match(
/^(\d{2})-([a-f0-9]{32})-([a-f0-9]{16})-(\d{2})$/
);
if (!matches) return { output: await yourLLMCall(prompt) };
const [, , traceId, parentId, traceFlags] = matches;
// Create parent context
const parentCtx = trace.setSpanContext(context.active(), {
traceId,
spanId: parentId,
traceFlags: parseInt(traceFlags, 16),
isRemote: true,
});
// Run within trace context
return context.with(parentCtx, async () => {
const span = tracer.startSpan('provider.call');
try {
const result = await yourLLMCall(prompt);
span.setStatus({ code: SpanStatusCode.OK });
// CRITICAL: Force flush before returning
await spanProcessor.forceFlush();
return { output: result };
} catch (error) {
span.recordException(error);
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
throw error;
} finally {
span.end();
}
});
}