Trace-First Context Management: Langfuse v4+ transitions to an observation-centric model prioritizing context managers over trace-specific imperative updates. This ensures correlating attributes (user_id, session_id) universally apply to all downstream spans without complex joins.

πŸš€ Quick Start: Context Propagation

Use propagate_attributes() as a context manager nested inside the @observe() decorator. Do not use it as a standalone decorator.

from langfuse.decorators import observe
from langfuse import propagate_attributes
 
@observe()
def run_pipeline(user_query):
    # Apply global tracking attributes to all child observations
    with propagate_attributes(
        user_id="user_987",
        session_id="session_xyz",
        metadata={"source": "api", "region": "eu-central"},
        tags=["prod", "v2-pipeline"]
    ):
        return execute_llm_chain(user_query) # Inherits all attributes automatically

πŸ’‘ Best Practices: Patterns & Strategy

  • Hybrid Instrumentation: Use @observe() to define high-level workflow boundaries (RAG logic, agents). Let native integrations (Langchain, OpenAI) handle low-level LLM spans.
  • Embrace Default Filters: Langfuse v4+ uses smart default span filters to block non-GenAI infrastructure noise (HTTP requests, DB). Rely on these defaults out-of-the-box before building custom filters.
  • Observation-Centric Enrichment: Use propagate_attributes() instead of old trace-specific update methods to enrich telemetry. This pushes attributes down to every observation, making single-table queries extremely efficient.

🚨 Gotchas / Anti-Patterns

  • β€œExport Everything” Bloat: Reverting to pre-v4 behavior (exporting all non-blocked spans) massively increases noise and cost. Do not disable span filtering unless actively debugging.
  • Orphaning Child Spans: Filtering out a parent span but keeping its children creates orphaned observations. This fundamentally breaks trace tree visualization in the Langfuse UI.
  • Heavy Manual Nesting: Avoid imperative, verbose span generation logic inside business flows. Drop down to manual spans only when specific precision or standalone metadata is strictly required.
  • Context Scope Leaks: propagate_attributes() scopes exactly to its with block. Observations fired outside this block drop the context correlation completely.

πŸ”§ Configuration: Custom Hardening & Filters

Compose custom rules safely by augmenting the default filters, rather than overwriting them entirely. Use mask_otel_spans at the export stage to sanitize PII.

from langfuse import Langfuse
from langfuse.span_filter import is_default_export_span
 
# 1. Expand span capture safely
langfuse = Langfuse(
    should_export_span=lambda span: is_default_export_span(span) or
                                    span.instrumentation_scope_name == "custom-db-layer"
)
 
# 2. Debug span drops (check logs for 'dropped-span')
# export LANGFUSE_DEBUG="True"

πŸ” Research / References