SigNoz Cloud - This page is relevant for SigNoz Cloud editions.
Self-Host - This page is relevant for self-hosted SigNoz editions.

Claude Agent SDK Monitoring & Observability with OpenTelemetry

Overview

This guide walks you through setting up monitoring and observability for Claude Agent SDK using OpenTelemetry and exporting logs, traces, and metrics to SigNoz. With this integration, you can observe the performance of various models, capture request/response details, and track system-level metrics in SigNoz, giving you real-time visibility into latency, error rates, and usage trends for your Claude Code SDK applications.

Instrumenting Claude Agent SDK in your AI applications with telemetry ensures full observability across your agent workflows, making it easier to debug issues, optimize performance, and understand user interactions. By leveraging SigNoz, you can analyze correlated traces, logs, and metrics in unified dashboards, configure alerts, and gain actionable insights to continuously improve reliability, responsiveness, and user experience.

Prerequisites

Monitoring Claude Agent SDK

No code auto-instrumentation is recommended for quick setup with minimal code changes. It's ideal when you want to get observability up and running without modifying your application code and are leveraging standard instrumentor libraries.

Step 1: Install the necessary packages in your Python environment.

pip install \
  opentelemetry-distro \
  opentelemetry-exporter-otlp \
  httpx \
  opentelemetry-instrumentation-httpx \
  opentelemetry-instrumentation-system-metrics \
  claude-agent-sdk \
  "langsmith[claude-agent-sdk]"

Step 2: Add Automatic Instrumentation

opentelemetry-bootstrap --action=install

Step 3: Configure logging level

To ensure logs are properly captured and exported, configure the root logger to emit logs at the DEBUG level or higher:

import logging

logging.getLogger().setLevel(logging.DEBUG)
logging.getLogger("httpx").setLevel(logging.DEBUG)

Step 4: Configure Langsmith OTel environment variables

import os

os.environ["LANGSMITH_OTEL_ENABLED"] = "true"
os.environ["LANGSMITH_OTEL_ONLY"] = "true"
os.environ["LANGSMITH_TRACING"] = "true"

Step 5: Enable OTel instrumentation

from langsmith.integrations.claude_agent_sdk import configure_claude_agent_sdk
 
configure_claude_agent_sdk()

Step 6: Enable token and cost attributes in traces (Optional)

In order to send token usage and cost related attributes in your OTel traces, add the following:

# ===== MONKEY PATCH: Fix token counting and cost tracking for OTEL export =====
# The LangSmith integration stores token counts and cost in metadata, but the OTEL exporter
# expects them as top-level fields (prompt_tokens, completion_tokens, total_tokens, total_cost)
from langsmith.integrations.claude_agent_sdk import _client

# Patch add_usage to set token and cost fields
def fixed_add_usage(self, metrics):
    """Attach token usage and cost details to the current run (with fix for OTEL export)."""
    if not (self.current_run and metrics):
        return

    # Set top-level token fields as object attributes
    if "input_tokens" in metrics:
        object.__setattr__(self.current_run, "prompt_tokens", int(metrics["input_tokens"]))
        self.current_run.extra["prompt_tokens"] = int(metrics["input_tokens"])
    if "output_tokens" in metrics:
        object.__setattr__(self.current_run, "completion_tokens", int(metrics["output_tokens"]))
        self.current_run.extra["completion_tokens"] = int(metrics["output_tokens"])
    if "total_tokens" in metrics:
        object.__setattr__(self.current_run, "total_tokens", int(metrics["total_tokens"]))
        self.current_run.extra["total_tokens"] = int(metrics["total_tokens"])

    # Set total_cost field if available
    if "total_cost" in metrics:
        object.__setattr__(self.current_run, "total_cost", float(metrics["total_cost"]))
        self.current_run.extra["total_cost"] = float(metrics["total_cost"])

    # Also store in metadata for backwards compatibility
    meta = self.current_run.extra.setdefault("metadata", {}).setdefault(
        "usage_metadata", {}
    )
    meta.update(metrics)

_client.TurnLifecycle.add_usage = fixed_add_usage

# Patch SerializedRunOperation.deserialize_run_info to move tokens and cost from extra to top level
from langsmith._internal._operations import SerializedRunOperation
original_deserialize = SerializedRunOperation.deserialize_run_info

def patched_deserialize_run_info(self):
    """Deserialize run info and move token and cost fields from extra to top level for OTEL."""
    run_info = original_deserialize(self)

    # If tokens and cost are in extra, move them to top level for OTEL exporter
    if "extra" in run_info:
        for field in ['prompt_tokens', 'completion_tokens', 'total_tokens', 'total_cost']:
            if field in run_info["extra"]:
                run_info[field] = run_info["extra"][field]

    return run_info

SerializedRunOperation.deserialize_run_info = patched_deserialize_run_info

# Patch OTEL exporter to also export total_cost
from langsmith._internal.otel import _otel_exporter

original_set_span_attributes = _otel_exporter.OTELExporter._set_span_attributes

def patched_set_span_attributes(self, span, run_info, op):
    """Set span attributes including total_cost."""
    # Call original method to set all standard attributes
    original_set_span_attributes(self, span, run_info, op)

    # Add total_cost as a custom attribute if available
    if run_info.get("total_cost") is not None:
        total_cost = run_info["total_cost"]
        span.set_attribute("gen_ai.usage.cost", float(total_cost))

_otel_exporter.OTELExporter._set_span_attributes = patched_set_span_attributes
# ===== END MONKEY PATCH =====

Step 7: Create an example Claude Agent SDK workflow

main.py
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ClaudeSDKClient


async def main():
    options = ClaudeAgentOptions(
        model="claude-sonnet-4-6",
        system_prompt="You are a friendly assistant who helps with answering questions by searching the web for up-to-date information.",
        allowed_tools=["WebSearch"],
    )
 
    async with ClaudeSDKClient(options=options) as client:
        await client.query("What is SigNoz and how does it compare to other observability tools?")

        async for message in client.receive_response():
            print(message)
 
asyncio.run(main())

๐Ÿ“Œ Note: Before running this code, ensure that you have set the environment variable ANTHROPIC_API_KEY with your generated API key.

Step 8: Run your application with auto-instrumentation

Run your application with the following environment variables set. This configures OpenTelemetry to export traces, logs, and metrics to SigNoz Cloud and enables automatic log correlation:

OTEL_RESOURCE_ATTRIBUTES="service.name=<service_name>" \
OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443" \
OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>" \
OTEL_EXPORTER_OTLP_PROTOCOL=grpc \
OTEL_TRACES_EXPORTER=otlp \
OTEL_METRICS_EXPORTER=otlp \
OTEL_LOGS_EXPORTER=otlp \
OTEL_PYTHON_LOG_CORRELATION=true \
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true \
opentelemetry-instrument <your_run_command>
  • <service_name>ย is the name of your service
  • <region>: Your SigNoz Cloud region
  • <your-ingestion-key>: Your SigNoz ingestion key
  • Replace <your_run_command> with the actual command you would use to run your application. In this case we would use: python main.py
โœ… Info

Using self-hosted SigNoz? Most steps are identical. To adapt this guide, update the endpoint and remove the ingestion key header as shown in Cloud โ†’ Self-Hosted.

View Traces, Logs, and Metrics in SigNoz

Your Claude Agent SDK usage should now automatically emit traces, logs, and metrics.

You should be able to view traces in Signoz Cloud under the traces tab:

Claude Agent SDK Trace View
Claude Agent SDK Trace View

When you click on a trace in SigNoz, you'll see a detailed view of the trace, including all associated spans, along with their events and attributes.

Claude Agent SDK Detailed Trace View
Claude Agent SDK Detailed Trace View

You should be able to view logs in Signoz Cloud under the logs tab. You can also view logs by clicking on the โ€œRelated Logsโ€ button in the trace view to see correlated logs:

Related logs
Related logs button
Claude Agent SDK Logs View
Claude Agent SDK Logs View

When you click on any of these logs in SigNoz, you'll see a detailed view of the log, including attributes:

Claude Agent SDK Detailed Log View
Claude Agent SDK Detailed Logs View

You should be able to see Claude Agent SDK related metrics in Signoz Cloud under the metrics tab:

Claude Agent SDK Metrics View
Claude Agent SDK Metrics View

When you click on any of these metrics in SigNoz, you'll see a detailed view of the metric, including attributes:

Claude Agent SDK Detailed Metrics View
Claude Agent SDK Detailed Metrics View

Troubleshooting

If you don't see your telemetry data:

  1. Verify network connectivity - Ensure your application can reach SigNoz Cloud endpoints
  2. Check ingestion key - Verify your SigNoz ingestion key is correct
  3. Wait for data - OpenTelemetry batches data before sending, so wait 10-30 seconds after making API calls
  4. Try a console exporter โ€” Enable a console exporter locally to confirm that your application is generating telemetry data before itโ€™s sent to SigNoz

Next Steps

You can also check out our custom Claude Agent SDK dashboardย here which provides specialized visualizations for monitoring your Claude Agent SDK usage in applications. The dashboard includes pre-built charts specifically tailored for LLM usage, along with import instructions to get started quickly.

Claude Agent SDK Dashboard
Claude Agent SDK Dashboard Template

Additional resources:

Last updated: March 6, 2026

Edit on GitHub