opentelemetry-langfuse

Crates.ioopentelemetry-langfuse
lib.rsopentelemetry-langfuse
version0.3.1
created_at2025-08-31 09:28:56.631329+00
updated_at2025-08-31 19:37:05.968917+00
descriptionOpenTelemetry components and utilities for Langfuse LLM observability
homepagehttps://github.com/genai-rs/opentelemetry-langfuse
repositoryhttps://github.com/genai-rs/opentelemetry-langfuse
max_upload_size
id1818346
size174,905
Tim Van Wassenhove (timvw)

documentation

https://docs.rs/opentelemetry-langfuse

README

opentelemetry-langfuse

Crates.io Documentation CI MSRV License

OpenTelemetry integration for Langfuse, the open-source LLM observability platform.

This crate provides OpenTelemetry components and utilities for integrating with Langfuse, enabling comprehensive observability for LLM applications. For more information about OpenTelemetry support in Langfuse, see the official Langfuse OpenTelemetry documentation.

Features

  • 🚀 OTLP Exporter - Configured exporter for sending traces to Langfuse
  • 🔌 Composable - Integrates with your existing OpenTelemetry setup
  • 🏗️ Builder Pattern - Flexible configuration API
  • 🔐 Secure - Handles authentication with Langfuse credentials
  • 🌐 Dual Configuration - Supports both Langfuse-specific and standard OTEL environment variables

Installation

[dependencies]
opentelemetry-langfuse = "*"

Quick Start

use opentelemetry::global;
use opentelemetry_langfuse::exporter_from_env;
use opentelemetry_sdk::trace::SdkTracerProvider;
use opentelemetry_sdk::Resource;
use opentelemetry::KeyValue;

// Create the Langfuse exporter
let exporter = exporter_from_env()?;

// Build your tracer provider with the exporter
let provider = SdkTracerProvider::builder()
    .with_batch_exporter(exporter)
    .with_resource(Resource::builder().with_attributes(vec![
        KeyValue::new("service.name", "my-service"),
    ]).build())
    .build();

// Set as global provider and start tracing
global::set_tracer_provider(provider);

Configuration

The exporter can be configured using environment variables. You have three options:

Option 1: Langfuse-Specific Variables

Use exporter_from_langfuse_env() with these variables:

LANGFUSE_PUBLIC_KEY=pk-lf-...              # Your public key
LANGFUSE_SECRET_KEY=sk-lf-...              # Your secret key
LANGFUSE_HOST=https://cloud.langfuse.com   # Optional: Defaults to cloud instance

Option 2: Standard OpenTelemetry Variables

Use exporter_from_otel_env() following the OTLP Exporter specification:

# For endpoint (use ONE of these):
# Option A: Direct traces endpoint (recommended)
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://cloud.langfuse.com/api/public/otel/v1/traces

# Option B: Base endpoint that works with Langfuse
OTEL_EXPORTER_OTLP_ENDPOINT=https://cloud.langfuse.com/api/public/otel  # /v1/traces will be appended
# This creates: https://cloud.langfuse.com/api/public/otel/v1/traces (which Langfuse accepts)

# For authentication
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <base64_encoded_credentials>"

⚠️ Important: Do NOT use OTEL_EXPORTER_OTLP_ENDPOINT=https://cloud.langfuse.com/api/public as this would create /api/public/v1/traces which Langfuse does not accept.

Option 3: Automatic Fallback

Use exporter_from_env() for automatic fallback with sensible defaults. Priority order:

For endpoint:

  1. LANGFUSE_HOST (appends /api/public/otel/v1/traces)
  2. OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
  3. OTEL_EXPORTER_OTLP_ENDPOINT (appends /v1/traces)
  4. Default: https://cloud.langfuse.com/api/public/otel/v1/traces (when no endpoint variables are set)

For authentication:

  1. LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY
  2. OTEL_EXPORTER_OTLP_TRACES_HEADERS
  3. OTEL_EXPORTER_OTLP_HEADERS

Manual Configuration

You can also configure the exporter programmatically:

use opentelemetry_langfuse::ExporterBuilder;
use std::time::Duration;

let exporter = ExporterBuilder::new()
    .with_host("https://cloud.langfuse.com")
    .with_basic_auth("pk-lf-...", "sk-lf-...")
    .with_timeout(Duration::from_secs(10))
    .build()?;

Custom HTTP Client

By default, the exporter creates a new reqwest::Client with rustls TLS support, which is suitable for most use cases and works with HTTPS endpoints out of the box.

You can provide your own client for advanced configurations:

  • Proxy settings
  • Custom root certificates
  • Connection pooling
  • Custom timeout configurations
use opentelemetry_langfuse::ExporterBuilder;
use std::time::Duration;

let custom_client = reqwest::Client::builder()
    .timeout(Duration::from_secs(30))
    .proxy(reqwest::Proxy::http("http://proxy.example.com:8080")?)
    .build()?;

let exporter = ExporterBuilder::new()
    .with_host("https://cloud.langfuse.com")
    .with_basic_auth("pk-lf-...", "sk-lf-...")
    .with_http_client(custom_client)
    .build()?;

Note on TLS: The crate includes rustls-tls by default for HTTPS support. If you're building a custom client or have specific TLS requirements, ensure your reqwest client is configured with appropriate TLS features.

Examples

See the examples directory for complete working examples:

License

Licensed under either of:

Contributing

See CONTRIBUTING.md for guidelines.

Resources

Commit count: 32

cargo fmt