The recommended approach is to add the user ID as metadata to your traces. This allows you to filter and search for traces by user ID later.
import { Laminar } from '@lmnr-ai/lmnr';// Option 1: Using withMetadataLaminar.withMetadata({ userId: 'user_123'}, () => { // All traces created inside this function will have userId: user_123});// Option 2: With the observe wrapperimport { observe } from '@lmnr-ai/lmnr';await observe({ name: 'processUserRequest', userId: 'user_123'}, async () => { // Process user request here});
import { Laminar } from '@lmnr-ai/lmnr';// Option 1: Using withMetadataLaminar.withMetadata({ userId: 'user_123'}, () => { // All traces created inside this function will have userId: user_123});// Option 2: With the observe wrapperimport { observe } from '@lmnr-ai/lmnr';await observe({ name: 'processUserRequest', userId: 'user_123'}, async () => { // Process user request here});
from lmnr import Laminar, observe# Option 1: Using set_metadata within a span context@observe()def process_user_request(user_id): # IMPORTANT: set_metadata must be called within an active span context # Here, the @observe decorator creates that context Laminar.set_metadata({ 'userId': user_id }) # Process user request here# Option 2: Directly in the observe decorator (preferred method)@observe(user_id='user_123')def process_user_request_alt(): # Process user request here pass
In Python, Laminar.set_metadata() must be called within an active span context (such as within a function decorated with @observe() or inside a Laminar.start_as_current_span block). If called outside of any span context, it will have no effect.
Another approach using start_as_current_span:
from lmnr import Laminardef process_user_request(user_id): with Laminar.start_as_current_span(name="process_request") as span: # Now we have an active span context Laminar.set_metadata({'userId': user_id}) # Your code here # Clear when done if needed Laminar.clear_metadata()
❌ Incorrect usage (will not work):
# This won't work because it's outside any span contextLaminar.set_metadata({'userId': 'user_123'})@observe()def my_function(): # The metadata set above won't be applied here pass
✅ Correct usage:
@observe()def my_function(): # Set metadata inside the span context Laminar.set_metadata({'userId': 'user_123'}) # Your code here
When including user IDs in traces, consider the following privacy practices:
Use anonymous or pseudonymous IDs rather than personally identifiable information
Consider your data retention policies
Use Laminar’s tracing level settings to control sensitive data
Follow relevant data protection regulations
// Use TracingLevel.META_ONLY for sensitive user operationsimport { withTracingLevel, TracingLevel } from "@lmnr-ai/lmnr";withTracing(TracingLevel.META_ONLY, () => { // Sensitive operations here will only record metadata // Input/output content won't be saved});
// Use TracingLevel.META_ONLY for sensitive user operationsimport { withTracingLevel, TracingLevel } from "@lmnr-ai/lmnr";withTracing(TracingLevel.META_ONLY, () => { // Sensitive operations here will only record metadata // Input/output content won't be saved});
from lmnr import Laminar, TracingLevelwith Laminar.set_tracing_level(TracingLevel.META_ONLY): # Sensitive operations here will only record metadata # Input/output content won't be saved
For a complete picture of user interactions, combine user IDs with session tracking:
// Track both user and sessionLaminar.withMetadata({ userId: 'user_123'}, () => { Laminar.withSession({ sessionId: 'session_456' }, () => { // All operations here are tracked with both user ID and session ID });});
// Track both user and sessionLaminar.withMetadata({ userId: 'user_123'}, () => { Laminar.withSession({ sessionId: 'session_456' }, () => { // All operations here are tracked with both user ID and session ID });});
@observe()def process_request(user_id, session_id): # Set both user ID and session in the same span context Laminar.set_metadata({'userId': user_id}) Laminar.set_session(session_id=session_id) # Your code here