OTEL Trace Ingestion
Publish OTEL Traces directly to your DBNL Deployment
Distributional is now Talaria Scientific. The DBNL product described in these docs has been sunset; this documentation is preserved for reference. Read the announcement.
OpenTelemetry (OTEL) Trace Ingestion allows for the richest data to be uploaded to your Project, but requires some off-platform coding and does not support backfilling data. This guide provides comprehensive instructions for instrumenting your AI agent application to send OpenTelemetry (OTEL) traces to DBNL.
Prerequisites
DBNL Credentials: You'll need:
DBNL API URL (e.g.,
http://localhost:8080/api)API Token (Bearer token for authentication which can be generated at
DBNL_API_URL/tokens)Project ID (your DBNL project identifier, typically starts with
proj_and is part of the URL for your project)
Implementation
Quick Start (DBNL SDK)
The simplest way to get tracing working is with dbnl.init_tracing(), which handles provider setup, exporter configuration, and auto-instrumentation of supported libraries in a single call.
pip install 'dbnl[instrumentation]'The instrumentation extra installs OpenInference instrumentors for popular libraries (OpenAI, LangChain, Anthropic, etc.) so that init_tracing() can auto-instrument them. If you only need the exporter without auto-instrumentation, pip install dbnl is sufficient.
import dbnl
dbnl.login()
dbnl.init_tracing(
project_id="{PROJECT_ID}",
service_name="my-agent",
)init_tracing() registers a global TracerProvider with a BatchSpanProcessor pointing at your DBNL deployment, and automatically instruments any installed OpenInference-compatible libraries. Pass auto_instrument=False to disable this and instrument manually.
To tag traces with an application version or experiment variants, see App Versioning & Experiments.
Advanced: Raw OpenTelemetry Setup
If you need full control over the TracerProvider (for example to add additional exporters, custom resources, or a non-default span processor), you can manage your own provider while still using the SDK to handle exporter configuration.
Pass your own TracerProvider to init_tracing() and it will attach the dbnl span processor and run auto-instrumentation on it, without replacing the global provider:
import dbnl
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.resources import Resource
dbnl.login()
resource = Resource.create({"service.name": "my-agent"})
tracer_provider = TracerProvider(resource=resource)
# Add your own processors/exporters here
# tracer_provider.add_span_processor(...)
dbnl.init_tracing(
project_id="{PROJECT_ID}",
tracer_provider=tracer_provider,
)
trace.set_tracer_provider(tracer_provider)Pass auto_instrument=False if you want to skip auto-instrumentation and instrument libraries yourself.
For even more control, dbnl.get_dbnl_span_processor() returns a pre-configured BatchSpanProcessor you can add to any provider directly, but note that it does not run auto-instrumentation.
Fully Manual Setup (no SDK)
If you prefer not to depend on the dbnl package at runtime, you can wire the OTLP exporter directly:
For LangChain applications, also install OpenInference instrumentation:
Create a telemetry initialization module (telemetry.py) in your application:
LangChain Integration
For LangChain applications, add OpenInference instrumentation:
Application Integration
Initialize telemetry early in your application startup:
FastAPI Example:
Standalone Script Example:
Message Content Capture
DBNL reads message content (prompts, completions, tool arguments) from span attributes only. There are two OTel instrumentor ecosystems for GenAI, and they handle content very differently:
OpenInference instrumentors (
openinference-instrumentation-*) always place message content on span attributes. This is a core design choice in the OpenInference spec, so DBNL ingests their content with no extra configuration.OTel GenAI semantic convention instrumentors (the
gen_ai.*namespace) are split: the spec allows content on either span attributes or separate OTel log records, and individual instrumentors pick different defaults. DBNL ingests traces, not logs, so any instrumentor that emits content as log events will produce traces with emptyinputandoutputcolumns.
When an OpenInference instrumentor exists for your framework, prefer it. If you must use an OTel GenAI instrumentor, the table below covers the common ones and how to ensure content lands on span attributes.
OpenInference instrumentors (no configuration needed)
LangChain
openinference-instrumentation-langchain
Google ADK
openinference-instrumentation-google-adk
Anthropic
openinference-instrumentation-anthropic
OpenAI (direct)
openinference-instrumentation-openai
See the OpenInference repo for the full list of supported frameworks.
OTel GenAI instrumentors (configuration required)
Pydantic AI
Native (InstrumentationSettings)
Span attrs (recent releases)
Use version=2 or higher; avoid version=1, which emits log events.
OpenAI Agents SDK
opentelemetry-instrumentation-openai-agents-v2
Off
Set OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true.
If traces are appearing in DBNL but input / output are blank, the instrumentor is almost certainly emitting content as log events. Pick one of the configurations above.
Pydantic AI
OpenAI Agents SDK
Quick Start
Install the required OpenTelemetry packages:
Create an instrumentation.ts file that configures the OTLP exporter to send traces to DBNL:
Use the --import flag to load instrumentation before your application code:
Auto-Instrumentation
For automatic tracing of LLM provider calls, add the relevant OpenInference JS instrumentation package and pass it to the NodeSDK. For example, to auto-instrument OpenAI calls:
Instrumentation packages are available for OpenAI, Anthropic, LangChain, Bedrock, and others. See the full list in the OpenInference JS packages.
Overview
If you already run an OpenTelemetry Collector, you can forward traces to DBNL by adding an OTLP/HTTP exporter to your collector configuration. This lets you centralize trace routing without changing application code.
Configuration
Add the following blocks to your collector YAML config:
The exporter endpoint is {DBNL_API_URL}/otel (without /v1/traces) because the otlphttp exporter appends /v1/traces automatically.
If you already have a collector config, merge these blocks into your existing receivers, exporters, and service.pipelines sections rather than replacing them. You can add otlphttp/dbnl alongside your other exporters in the traces pipeline.
Semantic Conventions
The collector forwards traces as-is; it does not transform span attributes. Your application's instrumentation must emit traces using OpenInference Semantic Conventions so that DBNL can parse the required fields (input, output, etc.) from span attributes.
Required Trace Fields
The following fields are required regardless of which ingestion method you are using:
input: The text input to the LLM as astringoutput: The text response from the LLM as astringtimestamp: The UTC timecode associated with the LLM call as atimestamptz
You may choose to track other attributes such as total_token_count or feedback_score which are part of the DBNL semantic convention.
Custom Attributes
Custom metadata should be added as span attributes using the OpenInference semantic convention. These attributes are available within the spans data for analysis. Note that only columns defined in the DBNL Semantic Convention are supported as top-level columns; arbitrary custom columns are not ingested.
Advanced Configuration
Batch Processing
DBNL uses BatchSpanProcessor by default for efficient trace export. This batches spans before sending, reducing network overhead:
For immediate export (useful for debugging), use SimpleSpanProcessor:
Verification
Test Trace Export
Create a test span to verify traces are being sent:
View Traces in DBNL
After sending traces, verify they appear in your DBNL dashboard. By default, traces are processed into logs nightly so you will not see them right away.
Log into your DBNL deployment and go to your project
Check the Status page to confirm that they have been processed
Navigate to the Explorer or Logs section
Filter by your project ID or service name
Verify traces are appearing with the expected attributes
Troubleshooting
Traces Not Appearing in DBNL
Check Environment Variables: Verify all required variables are set:
Verify API Endpoint: Test connectivity to DBNL:
Check Logs: Look for DBNL exporter configuration messages:
Verify URL Formatting: Ensure the endpoint is correctly formatted:
Format:
{DBNL_API_URL}/otel/v1/tracesExample:
http://localhost:8080/otel/v1/traces
Common Issues
Issue: "DBNL configuration incomplete"
Solution: Ensure
DBNL_API_URL,DBNL_API_TOKEN, andDBNL_PROJECT_IDare all set
Issue: "Failed to configure DBNL exporter"
Solution: Check that the API URL is valid and the token has proper permissions
Issue: Traces appear but missing attributes
Solution: Ensure you're using OpenInference semantic conventions or manually setting required attributes (
input,output,timestamp)
Issue: High latency or performance impact
Solution: Use
BatchSpanProcessor(default) instead ofSimpleSpanProcessorfor better performance
For issues or questions:
Check the troubleshooting section above
Review DBNL documentation
Verify your DBNL deployment has OTEL Trace Ingestion enabled
Contact DBNL support at support@distributional.com with your project ID and API endpoint
Best Practices
Use Batch Processing: Always use
BatchSpanProcessorin production for better performanceUse Semantic Conventions: Follow OpenInference conventions for automatic attribute mapping
Error Handling: Wrap exporter creation in try-except blocks to prevent application failures
Graceful Degradation: Allow your application to function even if DBNL configuration is incomplete
Additional Resources
DBNL Semantic Convention - Learn about semantic conventions for better analytics
OpenTelemetry Python Documentation - Official OpenTelemetry Python docs
OpenTelemetry JavaScript Documentation - Official OpenTelemetry JS docs
OpenTelemetry Collector Documentation - Official OpenTelemetry Collector docs
OpenInference Documentation - OpenInference semantic conventions