Configuration for attributes to propagate
Callback function (sync or async) within which attributes are propagated
The result of the callback function
Basic usage with user and session tracking:
import { startActiveObservation, propagateAttributes } from '@langfuse/tracing';
// Set attributes early in the trace
await startActiveObservation('user_workflow', async (span) => {
await propagateAttributes({
userId: 'user_123',
sessionId: 'session_abc',
metadata: { experiment: 'variant_a', environment: 'production' }
}, async () => {
// All spans created here will have userId, sessionId, and metadata
const llmSpan = startObservation('llm_call', { input: 'Hello' });
// This span inherits: userId, sessionId, experiment, environment
llmSpan.end();
const gen = startObservation('completion', {}, { asType: 'generation' });
// This span also inherits all attributes
gen.end();
});
});
Late propagation (anti-pattern):
await startActiveObservation('workflow', async (span) => {
// These spans WON'T have userId
const earlySpan = startObservation('early_work', { input: 'data' });
earlySpan.end();
// Set attributes in the middle
await propagateAttributes({ userId: 'user_123' }, async () => {
// Only spans created AFTER this point will have userId
const lateSpan = startObservation('late_work', { input: 'more' });
lateSpan.end();
});
// Result: Aggregations by userId will miss "early_work" span
});
Cross-service propagation with baggage (advanced):
import fetch from 'node-fetch';
// Service A - originating service
await startActiveObservation('api_request', async () => {
await propagateAttributes({
userId: 'user_123',
sessionId: 'session_abc',
asBaggage: true // Propagate via HTTP headers
}, async () => {
// Make HTTP request to Service B
const response = await fetch('https://service-b.example.com/api');
// userId and sessionId are now in HTTP headers
});
});
// Service B - downstream service
// OpenTelemetry will automatically extract baggage from HTTP headers
// and propagate to spans in Service B
asBaggage=true, attribute values are added to HTTP
headers on outbound requests. Only use for non-sensitive values and when you
need cross-service tracing.
Propagate trace-level attributes to all spans created within this context.
This function sets attributes on the currently active span AND automatically propagates them to all new child spans created within the callback. This is the recommended way to set trace-level attributes like userId, sessionId, and metadata dimensions that should be consistently applied across all observations in a trace.
IMPORTANT: Call this as early as possible within your trace/workflow. Only the currently active span and spans created after entering this context will have these attributes. Pre-existing spans will NOT be retroactively updated.
Why this matters: Langfuse aggregation queries (e.g., total cost by userId, filtering by sessionId) only include observations that have the attribute set. If you call
propagateAttributeslate in your workflow, earlier spans won't be included in aggregations for that attribute.