How to Implement Observability in Embabel Using Zipkin and Langfuse
Embabel implements observability using OpenTelemetry with auto-configuration support for Zipkin and Langfuse exporters, automatically wiring SpanExporter beans into a BatchSpanProcessor without requiring manual instrumentation code.
The embabel/embabel-agent repository provides a production-ready observability layer built on the OpenTelemetry standard. This architecture allows developers to route distributed traces to any OpenTelemetry-compatible backend, with specific support for Zipkin and Langfuse through Spring Boot's auto-configuration mechanism.
OpenTelemetry Foundation and Auto-Configuration
The core of Embabel's observability implementation resides in the embabel-agent-observability-autoconfigure module. The class OpenTelemetrySdkAutoConfiguration serves as the central integration point, registering an SdkTracerProvider and managing the lifecycle of span exporters.
According to the source code in OpenTelemetrySdkAutoConfiguration.java, the configuration deliberately executes after Spring Boot's own exporter auto-configurations to prevent double-wrapping of exporters. This ensures that a single SpanExporter bean—whether for Zipkin, Langfuse, or OTLP—is processed exactly once (see lines 49-52).
The auto-configuration detects any SpanExporter bean present on the classpath and, if no custom SpanProcessor is defined, automatically wraps each exporter in a BatchSpanProcessor (lines 75-78). This batching mechanism optimizes network usage when transmitting spans to Zipkin or Langfuse endpoints.
Configuring Zipkin and Langfuse Exporters
Maven Dependencies
To enable Zipkin support, add the OpenTelemetry Zipkin exporter to your project dependencies:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-zipkin</artifactId>
<version>1.29.0</version>
</dependency>
For Langfuse integration, include the corresponding exporter dependency:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-langfuse</artifactId>
<version>1.29.0</version>
</dependency>
Application Properties
Once the dependency is present, configure the exporter endpoints in your application.yml. For Zipkin:
otel:
exporter:
zipkin:
endpoint: http://localhost:9411/api/v2/spans
For Langfuse, specify the API endpoint and authentication token:
otel:
exporter:
langfuse:
endpoint: https://api.langfuse.com/api/spans
api-key: ${LANGFUSE_API_KEY}
Spring Boot creates the appropriate SpanExporter bean automatically when these properties are detected. The OpenTelemetrySdkAutoConfiguration then picks up these beans through its exporter customizer logic (lines 99-102).
Granular Control via ObservabilityProperties
The ObservabilityProperties class in embabel-agent-observability/src/main/java/com/embabel/agent/observability/ObservabilityProperties.java provides hierarchical flags to control which spans are generated and exported. The Javadoc explicitly confirms compatibility with "any OpenTelemetry-compatible exporter (Zipkin, OTLP, Langfuse, etc.)".
Key configuration options include:
enabled– Global master switch for all observability featurestracing-enabled– Controls whether spans are created at alltrace-llm-calls– Specifically enables tracing of LLM invocation spanstrace-tool-loop– Enables tracing of tool execution loopsdisabled-traces– A list of observation names to suppress (useful for filtering out infrastructure noise)
Example configuration to enable full tracing for Zipkin or Langfuse:
embabel:
agent:
platform:
observability:
enabled: true
tracing-enabled: true
trace-llm-calls: true
trace-tool-loop: true
disabled-traces:
- "health-check"
- "internal-refresh"
Complete Implementation Workflow
Implementing observability in Embabel using Zipkin and Langfuse requires three steps:
- Add the exporter dependency to your
pom.xmlfor either Zipkin or Langfuse - Configure the endpoint via Spring Boot properties (
otel.exporter.*) - Enable Embabel tracing via
embabel.agent.platform.observability.tracing-enabled=true
Once configured, every Embabel-generated span—including agent runs, action executions, tool loops, LLM calls, and RAG operations—flows automatically to your chosen backend. The BatchSpanProcessor handles queueing and batch transmission, ensuring minimal performance overhead on the agent execution path.
Summary
- Embabel uses OpenTelemetry as its observability foundation, compatible with any OTel-compliant exporter including Zipkin and Langfuse.
- The
OpenTelemetrySdkAutoConfigurationclass automatically wiresSpanExporterbeans intoBatchSpanProcessorinstances without manual code changes. - Configuration is controlled through
ObservabilityProperties, offering granular switches for different trace types and a suppression list for unwanted spans. - Setup requires only adding the appropriate Maven dependency and setting the exporter endpoint in
application.yml. - The architecture prevents double-wrapping of exporters by executing after Spring Boot's native auto-configurations.
Frequently Asked Questions
Does Embabel require manual instrumentation code to send traces to Zipkin?
No. Once you add the opentelemetry-exporter-zipkin dependency and configure the endpoint, Spring Boot creates the SpanExporter bean automatically. The OpenTelemetrySdkAutoConfiguration detects this bean and wires it into the span processing pipeline. All Embabel operations generate spans automatically through the framework's internal instrumentation.
Can I use both Zipkin and Langfuse simultaneously?
Yes. The auto-configuration supports multiple SpanExporter beans on the classpath. If you include both the Zipkin and Langfuse dependencies and configure both endpoints, Embabel will route spans to both backends simultaneously. Each exporter gets its own BatchSpanProcessor instance to isolate transmission failures between systems.
How do I prevent specific spans from being exported to Zipkin or Langfuse?
Use the disabled-traces property in ObservabilityProperties to suppress specific observation names. Alternatively, set specific tier flags like trace-llm-calls: false to disable entire categories of spans. These filters apply regardless of which exporter (Zipkin, Langfuse, or OTLP) you have configured.
What OpenTelemetry components does Embabel use internally?
Embabel uses the SdkTracerProvider for span creation and BatchSpanProcessor for asynchronous export. The implementation resides in the embabel-agent-observability module and relies on standard OpenTelemetry Java SDK components (version 1.29.0+) rather than custom instrumentation agents.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →