Dash0 acquires Polar Signals
Monitor and observe LangChain applications with OpenTelemetry.
LangChain is a framework for building applications powered by large language models (LLMs). It enables developers to create sophisticated AI applications by chaining together LLM calls, tools, and data sources. Monitoring LangChain applications is essential for understanding LLM performance, tracking token usage, identifying bottlenecks in chain executions, and troubleshooting errors in production.
LangChain applications can be instrumented with OpenTelemetry to automatically capture traces, metrics, and logs. This provides visibility into LLM calls, chain executions, token usage, latency, and errors. OpenTelemetry's auto-instrumentation approach (recommended) requires zero code changes, while manual instrumentation offers full control for custom spans and attributes.
For a complete working example, see the LangChain observability example in the dash0-examples repository.
Before setting up LangChain monitoring, ensure:
You'll need an OpenTelemetry Collector deployed to receive telemetry from your LangChain application. Consider using:
Helm Chart for The OpenTelemetry Collector
For local development, see the LangChain observability example for a complete setup with docker-compose.
Auto-instrumentation automatically captures telemetry from LangChain with zero code changes.
Install the OpenTelemetry distribution and LangChain instrumentation:
pip install opentelemetry-distro \
opentelemetry-exporter-otlp \
opentelemetry-instrumentation-langchainRun the bootstrap command to install instrumentation packages for your installed libraries:
opentelemetry-bootstrap -a installSet the following environment variables to send telemetry to an OpenTelemetry Collector:
export OTEL_SERVICE_NAME="my-langchain-app"
export OTEL_SERVICE_VERSION="1.0.0"
export OTEL_DEPLOYMENT_ENVIRONMENT="production"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"Execute your application with the opentelemetry-instrument wrapper:
opentelemetry-instrument python your_app.pyFor frameworks like Flask or FastAPI:
opentelemetry-instrument flask --app myapp run
opentelemetry-instrument uvicorn main:app --reloadYour LangChain application now exports telemetry automatically with no code changes required.
Auto-instrumentation does not prevent you from adding custom spans - you can always reference the global tracer using trace.get_tracer(__name__) to add business-specific context.
Manual instrumentation provides full control and allows custom spans and attributes.
pip install opentelemetry-api \
opentelemetry-sdk \
opentelemetry-exporter-otlp \
opentelemetry-instrumentation-langchainAdd the following setup code to your application:
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.semconv.resource import ResourceAttributes
from opentelemetry.instrumentation.langchain import LangchainInstrumentor
def setup_telemetry():
"""Configure OpenTelemetry for LangChain."""
# Define service resource
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "my-langchain-app",
ResourceAttributes.SERVICE_VERSION: "1.0.0",
ResourceAttributes.DEPLOYMENT_ENVIRONMENT: "production",
})
# Create tracer provider
provider = TracerProvider(resource=resource)
# Configure OTLP exporter to send to collector
otlp_exporter = OTLPSpanExporter(
endpoint="http://localhost:4317",
insecure=True,
)
# Add span processor
provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
# Set global tracer provider
trace.set_tracer_provider(provider)
# Instrument LangChain
LangchainInstrumentor().instrument()
# Call once at application startup
setup_telemetry()You can add custom spans to capture business logic:
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("process_user_query") as span:
span.set_attribute("user.id", "user123")
span.set_attribute("query.type", "qa")
# Your LangChain code here
response = chain.invoke({"question": "What is OpenTelemetry?"})The LangChain instrumentation automatically captures comprehensive telemetry following the OpenTelemetry Semantic Conventions for GenAI, including full conversation context, token usage metrics, and chain execution flows.
Example captured attributes include gen_ai.usage.input_tokens and gen_ai.usage.output_tokens for cost tracking, gen_ai.prompt.0.content and gen_ai.completion.0.content for debugging conversations, and gen_ai.request.model for tracking which models are being used.
After running your instrumented application:
my-langchain-app)ChatAnthropic.invokeRunnableSequence.invokeChatPromptTemplate.invokeStrOutputParser.parse