windlass.providers.observability.multi¶
multi
¶
Fan-out tracing — send one trace to several backends at once.
Teams rarely have exactly one place they want traces to land. A platform team standardises on LangSmith while a product team already reads Langfuse; during a migration you want both; while debugging you want the console too. Without this you would have to pick one, or write the fan-out by hand in every application.
::
rag = Windlass.rag().observe("multi", backends=["langfuse", "langsmith"])
agent = Windlass.agent().observe(
"multi", backends=["console", Windlass.tracer("langfuse")]
)
Backends are named exactly as they are in the registry, or passed as live
:class:~windlass.interfaces.tracer.Tracer instances when they need their own
configuration.
A tracer is never allowed to break the application it observes, and that guarantee gets harder with several backends, not easier: one misconfigured exporter must not take down the others or the run. Every call into a backend is therefore isolated — a backend that raises is logged once and skipped for the rest of that call, never propagated to the caller.
Example
from windlass import Windlass tracer = Windlass.tracer("multi", backends=["memory", "memory"]) with tracer.span("work", kind="chain"): ... pass tuple(len(b.spans) for b in tracer.backends) (1, 1)
MultiTracer
¶
MultiTracer(
*,
backends: Sequence[Any] = (),
project: str | None = None,
tags: tuple[str, ...] = (),
enabled: bool = True,
**config: Any
)
Bases: Tracer
A tracer that forwards every span to several other tracers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backends
|
Sequence[Any]
|
Registry names ( |
()
|
project
|
str | None
|
Project/session name passed to any backend built by name. |
None
|
tags
|
tuple[str, ...]
|
Tags passed to any backend built by name. |
()
|
enabled
|
bool
|
Master switch. |
True
|
**config
|
Any
|
Forwarded to :class: |
{}
|
Attributes:
| Name | Type | Description |
|---|---|---|
backends |
list[Tracer]
|
The live backend tracers, in call order. |
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
When a named backend cannot be constructed. A backend you asked for by name and which cannot be built is a configuration mistake worth failing on — unlike a runtime export failure, which is isolated and logged. |
Example
from windlass import Windlass tracer = Windlass.tracer("multi", backends=["memory"]) len(tracer.backends) 1
Source code in src\windlass\providers\observability\multi.py
start_span
¶
end_span
¶
flush
¶
aclose
async
¶
Close every backend, ignoring individual failures.
Source code in src\windlass\providers\observability\multi.py
native
¶
describe
¶
Return a JSON-safe summary naming every backend.