feat(sdk): support multiple OTLP span exporters (dual-write alongside Langfuse)
Maintainer antworten meist innerhalb von 1 Tag
@hassiebp arbeitet bereits daran.
Seit 18.6.2026.
Bewertung
Dieses Issue wurde noch nicht bewertet.
Beschreibung
Summary
We would like Langfuse SDKs to support exporting spans to more than one destination—specifically, keep the default Langfuse OTLP export and optionally forward the same spans to an additional OTLP endpoint (or custom SpanExporter).
This would follow the standard OpenTelemetry pattern of attaching multiple SpanProcessors to a single TracerProvider, without requiring users to replace Langfuse's built-in exporter.
Problem
Today, when instrumenting with the Langfuse Python SDK (@observe(), LangChain callbacks, etc.), spans are exported through Langfuse's internal OTLP pipeline to the configured Langfuse host.
Some deployments need parallel export to another OTLP-compatible backend—for example:
- An internal observability or logging pipeline (same VPC / on-prem)
- A secondary sink during migration or validation
- Environment-specific routing (e.g. dev/staging copies to a local collector)
PR https://github.com/langfuse/langfuse-python/pull/1618 added optional span_exporter, which is helpful for customization, but it replaces the default Langfuse exporter rather than adding a second one. Setting generic OTEL_EXPORTER_OTLP_* env vars also does not appear to dual-write when using Langfuse's own TracerProvider initialization.
Proposed behavior
Support one or more additional exporters while preserving the default Langfuse export path.
Option A — constructor / client API
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
Langfuse(
additional_span_exporters=[
OTLPSpanExporter(endpoint="https://internal-collector.example.com/v1/traces"),
],
)
Option B — environment variables (no code changes)
# Existing Langfuse config unchanged
LANGFUSE_PUBLIC_KEY=...
LANGFUSE_SECRET_KEY=...
LANGFUSE_HOST=...
# Additional OTLP sink
LANGFUSE_ADDITIONAL_OTLP_ENDPOINT=https://internal-collector.example.com
LANGFUSE_ADDITIONAL_OTLP_HEADERS=Authorization=Bearer ...
Requirements we care about:
- Default behavior unchanged when additional exporters are not configured
- Additional exporters receive the same spans as Langfuse (no silent filtering unless explicitly configured later)
- get_client() / singleton initialization should preserve additional exporters
- Clear documentation on auth headers, timeouts, and failure isolation (one exporter failing should not break the other)
Alternatives considered
- Replace exporter via span_exporter (#1618) — loses default Langfuse export unless manually re-wired
- User-owned OTEL Collector sidecar — works but adds operational overhead; SDK-level dual export is simpler for many teams
- Application-level double instrumentation — fragile across frameworks and easy to break on upgrades
Questions for maintainers
- Is dual / multi-exporter export something the Langfuse SDK team would consider?
- Would you prefer an explicit additional_span_exporters API, env-based configuration, or both?
- Should this live in langfuse-python first, with parity in langfuse-js?
- Any concerns about performance, backpressure, or support burden we should address in a PR?
Happy to contribute a PR if there is alignment on the API shape. Thanks!
- Vorherrschende Sprache
- Python
- Sterne
- 502
- Forks
- 381
- Ø Merge
- 1 T. 1 Std.
- Gemergte PRs (30 T.)
- 64
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Hat eine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus langfuse/langfuse-python
-
bug(scores): create_score sends numpy.bool_ as JSON `true` and Decimal as "<Decimal>" since v5.0.2Evtl. vergeben @lalith0407 hat das vor 2 Tagen übernommen. Offenbug feat-scores sdk-python
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 74/100
langfuse/langfuse-python#2057 ·
Maintainer antworten meist innerhalb von 1 Tag
-
tests/unit/test_prompt.py fails on a fresh clone without LANGFUSE_* env varsEvtl. vergeben @Mathoholic hat das vor 15 Tagen übernommen. Offenbug feat-prompt-management sdk-python
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 80/100
langfuse/langfuse-python#1976 · 3 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug(openai): a stream that fails mid-iteration ends the generation without level ERROREvtl. vergeben @hassiebp hat das vor 5 Tagen übernommen. Offenbug integration-openai sdk-python
langfuse/langfuse-python#2039 · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
fix(serializer): handle single-string __slots__ and detect cycles in slotted objectsEvtl. vergeben @hassiebp hat das vor 10 Tagen übernommen. Offenbug sdk-python
langfuse/langfuse-python#2014 · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug: ChatPromptClient.compile appends str(whole list) once per non-dict placeholder itemEvtl. vergeben @nimarb hat das vor 5 Tagen übernommen. Offenbug feat-prompt-management sdk-python
langfuse/langfuse-python#1971 · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in langfuse/langfuse-python
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
scikit-learn-contrib/category_encoders#553 ·
Maintainer antworten meist innerhalb von 1 Tag
-
tests/strategies_test.py:174 goes uncovered on about 1 run in 100, failing the coverage ratchetOffenflaky-watch
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
btclib-org/btclib#2839 ·
Maintainer antworten meist innerhalb von 1 Tag
-
BarrelList constructor drops false-valued iterable contentsEvtl. vergeben @Gambit-Checkmate hat das heute übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
Maintainer antworten meist innerhalb von 19 Tagen
-
[Performance]: Redundant object-storage pull when model and tokenizer share the same RunAI URIOffen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 77/100
vllm-project/vllm#63863 ·
Maintainer antworten meist innerhalb von 1 Tag