JS Context
Trace context propagation in JavaScript/TypeScript.
The JavaScript SDK uses AsyncLocalStorage for automatic context propagation across async operations.
Getting Context
getCurrentContext()
Get the current context state:
import { getCurrentContext } from 'risicare';
const context = getCurrentContext();
if (context) {
console.log('Session:', context.session);
console.log('Agent:', context.agent);
console.log('Span:', context.span);
console.log('Phase:', context.phase);
}The context object contains nested objects:
interface ContextState {
session?: { sessionId: string; userId?: string };
agent?: { name: string; role?: string; agentId?: string };
span?: Span;
phase?: SemanticPhase;
}Individual Getters
import {
getCurrentTraceId,
getCurrentSpanId,
getCurrentAgentId,
getCurrentSessionId,
} from 'risicare';
const traceId = getCurrentTraceId();
const spanId = getCurrentSpanId();
const agentId = getCurrentAgentId();
const sessionId = getCurrentSessionId();W3C Trace Context
Propagate context across service boundaries using W3C headers:
Inject Context
import { injectTraceContext } from 'risicare';
// Inject into HTTP headers
const headers: Record<string, string> = {};
injectTraceContext(headers);
// Now headers contains:
// {
// 'traceparent': '00-abc123...-def456...-01',
// 'tracestate': 'risicare=...'
// }
await fetch('https://api.example.com', { headers });Extract Context
import { extractTraceContext, runWithContext } from 'risicare';
// In your HTTP handler
app.post('/api/endpoint', async (req, res) => {
const context = extractTraceContext(req.headers);
if (context) {
await runWithContext({ span: context }, async () => {
// All spans created here are linked to the extracted context
await processRequest(req.body);
});
}
res.json({ success: true });
});Manual Context Management
runWithContext()
Run code within a specific context override:
import { runWithContext } from 'risicare';
await runWithContext(
{
session: { sessionId: 'sess-123', userId: 'user-456' },
agent: { name: 'my-agent', role: 'worker' },
},
async () => {
// Code runs with this context
await doWork();
}
);The first parameter is a Partial<ContextState> — you only need to specify the fields you want to override.
Span Registry
Access spans by ID for use in async generators and streaming:
import {
registerSpan,
getSpanById,
unregisterSpan,
} from 'risicare';
// Register a span for later lookup by ID
registerSpan(span, 30000); // optional TTL in ms
// Get span by its ID
const span = getSpanById('abc123def456');
// Clean up when done
unregisterSpan('abc123def456');When to Use the Span Registry
The span registry is designed for async generators and streaming scenarios where contextvars context may be lost after yield. Store the span ID before yielding, then retrieve it by ID in subsequent iterations.
Cross-Process Propagation
HTTP Client
import { injectTraceContext } from 'risicare';
async function fetchWithTracing(url: string, options: RequestInit = {}) {
const headers = new Headers(options.headers);
// Inject trace context
const traceHeaders: Record<string, string> = {};
injectTraceContext(traceHeaders);
Object.entries(traceHeaders).forEach(([key, value]) => {
headers.set(key, value);
});
return fetch(url, { ...options, headers });
}Message Queues
import { injectTraceContext, extractTraceContext, runWithContext } from 'risicare';
// Producer
async function publishMessage(queue: Queue, payload: unknown) {
const headers: Record<string, string> = {};
injectTraceContext(headers);
await queue.publish({
payload,
headers,
});
}
// Consumer
async function handleMessage(message: Message) {
const context = extractTraceContext(message.headers);
if (context) {
await runWithContext({ span: context }, async () => {
await processMessage(message.payload);
});
}
}