Skip to content
Last9
Book demo

Langfuse

Export OpenTelemetry traces from Langfuse to Last9 for unified LLM observability and monitoring

Monitor your LLM applications with Langfuse traces exported to Last9. Combine Langfuse’s prompt management and evaluation capabilities with Last9’s observability platform for comprehensive AI monitoring.

What is Langfuse?

Langfuse is an open-source LLM engineering platform that provides observability, prompt management, and evaluation tools for AI applications. It helps teams debug, analyze, and iterate on their LLM-powered features.

Key capabilities include:

  • Tracing - Track LLM calls, chains, and agents with detailed span data
  • Prompt management - Version and deploy prompts with built-in experimentation
  • Evaluation - Score and analyze LLM outputs for quality monitoring
  • OpenTelemetry export - Send trace data to external observability platforms

Prerequisites

Before setting up the integration:

  1. Last9 Account - Sign up at app.last9.io
  2. Langfuse Account - Create an account at langfuse.com or self-host Langfuse
  3. LLM Application - An existing application instrumented with Langfuse SDK

Instrument Your Application

If you haven’t already instrumented your application with Langfuse, here’s how to get started:

  1. Install the Langfuse SDK

    pip install langfuse
  2. Configure Langfuse Credentials

    Set your Langfuse credentials as environment variables:

    export LANGFUSE_PUBLIC_KEY="pk-..."
    export LANGFUSE_SECRET_KEY="sk-..."
    export LANGFUSE_HOST="https://cloud.langfuse.com" # or your self-hosted URL
  3. Instrument Your LLM Calls

    Use the @observe decorator to trace your LLM operations:

    from langfuse import observe
    from openai import OpenAI
    client = OpenAI()
    @observe()
    def answer_question(question: str) -> str:
    response = client.chat.completions.create(
    model="gpt-4",
    messages=[
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": question}
    ]
    )
    return response.choices[0].message.content
    # Usage
    answer = answer_question("What is observability?")

    For framework integrations:

    # LangChain integration
    from langfuse.langchain import CallbackHandler
    langfuse_handler = CallbackHandler()
    # Pass to your LangChain calls
    chain.invoke({"input": "Hello"}, config={"callbacks": [langfuse_handler]})

Integration Setup

The Langfuse SDK (v3+) is OpenTelemetry-native, so add Last9 as a second span processor in your application’s own OpenTelemetry setup. Langfuse has no deployment-level or dashboard toggle that forwards traces to a third-party OTLP backend. This works the same way for Langfuse Cloud and self-hosted Langfuse.

  1. Get Your Last9 OTel Credentials

    Navigate to Integrations → OpenTelemetry in your Last9 dashboard. Copy the OTel Endpoint and Auth Header values.

  2. Install the OpenTelemetry Exporter

    pip install opentelemetry-exporter-otlp-proto-http
  3. Add Last9 as a Second Span Processor

    The Langfuse Python SDK doesn’t expose a standalone LangfuseSpanProcessor — instead, pass your own TracerProvider to the Langfuse client, and attach Last9’s exporter to that same provider. This requires the Langfuse credentials (LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_HOST) from Instrument Your Application:

    from langfuse import Langfuse
    from opentelemetry import trace
    from opentelemetry.sdk.resources import Resource
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import BatchSpanProcessor
    from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
    provider = TracerProvider(
    resource=Resource.create({"service.name": "my-llm-app"})
    )
    provider.add_span_processor(
    BatchSpanProcessor(
    OTLPSpanExporter(
    endpoint="https://otlp.last9.io/v1/traces",
    headers={"Authorization": "<your-auth-header>"},
    )
    )
    )
    trace.set_tracer_provider(provider)
    langfuse = Langfuse(tracer_provider=provider)

    Replace <your-auth-header> with the full Auth Header value from Step 1, including the Basic prefix. Replace my-llm-app with your service name. Set this up once, before any @observe-decorated code runs — constructing Langfuse(...) registers it as the client @observe and get_client() use.

  4. Verify the Integration

    Make some LLM calls through your Langfuse-instrumented application, then check the Last9 Traces Explorer to see your traces.

View Traces in Last9

After the integration is active, your Langfuse traces appear in Last9:

  1. Navigate to Traces Explorer
  2. Filter by the service name you set in Integration Setup, for example my-llm-app
  3. Explore trace data including:
    • LLM generations - Model calls with prompts, completions, and token counts
    • Trace hierarchy - Parent-child relationships between operations
    • Latency breakdown - Time spent in each span
    • Metadata - Custom attributes and tags from Langfuse

Correlate with Application Traces

Langfuse and Last9 share the same OpenTelemetry TracerProvider, which you set up in Integration Setup. As a result, Langfuse spans and your application’s other spans already share the same trace ID, so you do not need to propagate metadata manually. A request that flows through your app and into an @observe-decorated LLM call shows up as a single trace in Last9’s Traces Explorer.

Advanced Configuration

Filter Exported Traces

The BatchSpanProcessor / SimpleSpanProcessor you added for Last9 receives every span from the shared TracerProvider, independent of Langfuse’s own export filtering. To reduce volume sent to Last9, add a span processor filter or an OpenTelemetry Collector-based sampler in front of the exporter, rather than relying on Langfuse-side settings.

Custom Attributes

Add custom attributes to your Langfuse traces that will appear in Last9. Wrap the operation in propagate_attributes rather than calling a trace-update method on the client:

from langfuse import observe, propagate_attributes
@observe()
def process_document(doc_id: str, user_id: str):
# Your logic here
pass
# Usage
with propagate_attributes(
user_id="user-123",
metadata={
"document_id": "doc-456",
"environment": "production",
"feature": "document-qa",
},
tags=["production", "document-processing"],
):
process_document("doc-456", "user-123")

These attributes enable filtering and grouping in Last9’s Traces Explorer.

Use Cases

  • Unified Observability - View LLM traces alongside your application’s HTTP requests, database queries, and other operations in a single platform.
  • Production Monitoring - Set up alerts on LLM latency, error rates, and token consumption using Last9’s alerting capabilities.
  • Cost Analysis - Correlate Langfuse’s token tracking with Last9’s analytics to understand LLM costs per feature or user segment.
  • Debugging - Trace issues from Last9 alerts back to specific Langfuse generations, prompts, and model responses.
  • Compliance - Maintain a complete audit trail of all LLM interactions in your observability infrastructure.

Troubleshooting

  • Traces do not appear in Last9

    • Verify the OTLPSpanExporter / OTLPTraceExporter endpoint is set to https://otlp.last9.io/v1/traces
    • Confirm the exporter’s Authorization header is correctly configured (including the Basic prefix)
    • Ensure the Last9 span processor is registered on the same TracerProvider as LangfuseSpanProcessor, and that this setup runs before any @observe-decorated code or startActiveObservation calls
    • Ensure your Langfuse application is generating traces (check the Langfuse dashboard first)
    • In Node.js, confirm the process calls sdk.shutdown() (or otherwise flushes) before exit so batched spans aren’t dropped

Please get in touch with us on Discord or Email if you have any questions.