Overview
Claude Code is Anthropic’s CLI coding agent. It emits OpenTelemetry traces that Fiddler natively ingests and maps to the Fiddler schema, giving you observability over coding agent sessions — including user prompts, LLM calls, tool invocations, token usage, and permission decisions.
No Fiddler SDK is required. Claude Code’s built-in OTel instrumentation sends traces directly to Fiddler’s OTLP ingestion endpoint.
Beta telemetry. Claude Code’s OpenTelemetry tracing requires the CLAUDE_CODE_ENHANCED_TELEMETRY_BETA flag and is subject to change between versions. Several content attributes (LLM responses, tool input/output) are not available in trace spans. See Known Limitations for full details.
| Capability | Support |
|---|
| User prompt capture | ✅ Requires OTEL_LOG_USER_PROMPTS=1 |
| LLM response capture | ❌ Not available in traces |
| Tool name tracking | ✅ Always available |
| Tool input/output | ❌ Not emitted in trace spans |
| Token counts | ✅ Input, output, cache read, cache creation |
| Session correlation | ✅ Via session.id |
| Permission decision tracking | ✅ Accept/deny on tool invocations |
| Cost tracking | ❌ Not emitted by Claude Code |
| Enrichment (FTL Prompt Safety) | ✅ Via Fiddler evaluator rules |
Prerequisites
- Claude Code v2.1.138 or later
- A Fiddler application with a valid
application.id
Quick Start
Step 1 — Enable Claude Code telemetry
Set the following environment variables before launching Claude Code:
# Required — enable OTel tracing (beta)
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
export OTEL_TRACES_EXPORTER=otlp
# Required — point at Fiddler's OTLP ingestion endpoint
export OTEL_EXPORTER_OTLP_ENDPOINT="https://<your-fiddler-url>"
export OTEL_EXPORTER_OTLP_HEADERS="fiddler-application-id=<your-application-id>,Authorization=Bearer <your-api-key>"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
# Required — tag traces with your Fiddler application
export OTEL_RESOURCE_ATTRIBUTES="application.id=<your-application-id>"
# Recommended — enable content capture
export OTEL_LOG_USER_PROMPTS=1
export OTEL_LOG_TOOL_DETAILS=1
export OTEL_LOG_TOOL_CONTENT=1
Step 2 — Launch Claude Code
Use Claude Code normally. Every interaction generates OTel traces that flow to Fiddler.
Step 3 — Verify traces in Fiddler
Navigate to your application in the Fiddler UI. You should see traces appearing within 30 seconds, with:
- Agent spans for each user interaction (prompt → reasoning → tool calls → response)
- LLM spans for each model call (Sonnet, Haiku) with token counts and latency
- Tool spans for each tool invocation (Bash, Read, Write, MCP tools, WebSearch)
Managed Deployment via Settings File
For enterprise or managed deployments, you can configure telemetry via Claude Code’s settings file instead of environment variables. This ensures consistent telemetry across all developers without requiring them to set env vars manually.
Create or update .claude/settings.json (project-level) or ~/.claude/settings.json (user-level):
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1",
"OTEL_TRACES_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_ENDPOINT": "https://<your-fiddler-url>",
"OTEL_EXPORTER_OTLP_HEADERS": "fiddler-application-id=<your-application-id>,Authorization=Bearer <your-api-key>",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_RESOURCE_ATTRIBUTES": "application.id=<your-application-id>",
"OTEL_LOG_USER_PROMPTS": "1",
"OTEL_LOG_TOOL_DETAILS": "1",
"OTEL_LOG_TOOL_CONTENT": "1"
}
}
Do not commit API keys to version control. The OTEL_EXPORTER_OTLP_HEADERS value contains your Fiddler API key. If using project-level .claude/settings.json, add it to .gitignore to prevent accidental exposure. For CI/CD or shared environments, prefer setting credentials via environment variables instead of the settings file.
Settings in .claude/settings.json (project-level) take precedence over environment variables. Settings in the user-level ~/.claude/settings.json apply to all projects unless overridden.
What Gets Captured
Span Hierarchy
Each user interaction produces a trace with the following span structure:
claude_code.interaction (agent — root span, one per user prompt)
├── claude_code.llm_request (llm — LLM API call, e.g., Sonnet or Haiku)
├── claude_code.llm_request (llm — parallel model call, e.g., Haiku for routing)
├── claude_code.tool (tool — tool invocation wrapper)
│ ├── claude_code.tool.blocked_on_user (chain — permission prompt wait)
│ └── claude_code.tool.execution (chain — actual tool execution)
├── claude_code.tool (tool — second tool invocation)
│ └── claude_code.tool.execution (chain)
└── claude_code.llm_request (llm — follow-up LLM call with tool results)
Span Type Mapping
| Claude Code Span | Fiddler Span Type | Description |
|---|
claude_code.interaction | agent | Root span for a user interaction. Contains the user prompt and interaction-level metadata. |
claude_code.llm_request | llm | Individual LLM API call. Contains model name, token counts, latency, and success/error status. |
claude_code.tool | tool | Tool invocation wrapper. Contains the tool name and total duration (including permission wait). |
claude_code.tool.blocked_on_user | chain | Time spent waiting for the user to accept or deny a tool permission prompt. Contains the user’s decision. |
claude_code.tool.execution | chain | Actual tool execution after permission is granted. Contains success status and execution duration. |
Captured Attributes by Span Type
Agent Spans (claude_code.interaction)
| Attribute | Fiddler Mapping | Requires Env Var | Description |
|---|
user_prompt | fiddler.contents.gen_ai.llm.input.user | OTEL_LOG_USER_PROMPTS=1 | The user’s prompt text. Shows <REDACTED> when env var is not set. |
user_prompt_length | fiddler.span.user.user_prompt_length | No | Character count of the user prompt (always available, even when content is redacted). |
interaction.sequence | fiddler.span.user.interaction.sequence | No | Sequence number within the session (1 for first interaction, 2 for second, etc.). |
interaction.duration_ms | fiddler.span.user.interaction.duration_ms | No | Total duration of the interaction in milliseconds. |
session.id | fiddler.metadata.gen_ai.conversation.id | No | Claude Code session UUID. Used for session correlation. |
LLM Spans (claude_code.llm_request)
| Attribute | Fiddler Mapping | Description |
|---|
input_tokens | fiddler.span.system.gen_ai.usage.input_tokens | Number of input tokens (excluding cache). |
output_tokens | fiddler.span.system.gen_ai.usage.output_tokens | Number of output tokens. |
cache_read_tokens | fiddler.span.user.cache_read_tokens | Tokens read from Anthropic’s prompt cache. |
cache_creation_tokens | fiddler.span.user.cache_creation_tokens | Tokens written to Anthropic’s prompt cache. |
model | Passthrough | Model identifier (e.g., claude-sonnet-4-5@20250929). |
gen_ai.request.model | Passthrough | Same as model, following OTel GenAI semantic conventions. |
gen_ai.system | Passthrough | LLM provider (always anthropic for Claude Code). |
ttft_ms | fiddler.span.user.ttft_ms | Time to first token in milliseconds. |
stop_reason | fiddler.span.user.stop_reason | Why the LLM stopped: end_turn, tool_use, max_tokens. |
success | fiddler.span.user.success | Whether the LLM call succeeded (true/false). |
error | fiddler.span.user.error | Error message when success is false. |
attempt | fiddler.span.user.attempt | Retry attempt number (1 for first try). |
llm_request.context | fiddler.span.user.llm_request.context | Call context: interaction (top-level) or tool (nested in a tool span). |
LLM response content is not available in traces. Claude Code emits LLM output via OTel log records, not trace span attributes. This mapper processes trace spans only. See Known Limitations.
| Attribute | Fiddler Mapping | Description |
|---|
tool_name | fiddler.span.system.gen_ai.tool.name | Tool identifier (e.g., Bash, Read, Write, Edit, WebSearch, mcp__server__tool). |
duration_ms | fiddler.span.user.duration_ms | Total tool duration including permission wait. |
Tool input/output content is not available in traces. Despite the OTEL_LOG_TOOL_CONTENT=1 env var, Claude Code does not currently emit tool.output span events on tool spans. See Known Limitations.
| Attribute | Fiddler Mapping | Description |
|---|
decision | fiddler.span.user.decision | User’s permission decision: accept or deny. |
source | fiddler.span.user.source | How the decision was made: user_temporary, user_permanent, settings. |
duration_ms | fiddler.span.user.duration_ms | Time spent waiting for the user to respond. |
Session Grouping
Claude Code assigns a session.id to each coding session. Fiddler maps this to gen_ai.conversation.id, enabling session-level grouping in the UI. All spans within a session share the same session.id, allowing you to:
- View the full timeline of a coding session
- Correlate LLM calls with tool invocations
- Track interaction sequences within a session
When session.id is absent (rare), Fiddler falls back to using the OTel trace_id as the conversation ID.
Enrichment Setup
Fiddler can automatically score Claude Code user prompts using FTL Prompt Safety or other evaluators. To configure:
- Navigate to your application in the Fiddler UI.
- Create an evaluator rule with:
- Span type:
agent
- Text field:
user_prompt
- Evaluator: FTL Prompt Safety (or any custom evaluator)
- New
claude_code.interaction spans will be scored automatically as they arrive.
Enrichment requires the user_prompt attribute to be populated. Set OTEL_LOG_USER_PROMPTS=1 to enable content capture. When disabled, user_prompt contains <REDACTED> and enrichment will score the redaction placeholder instead of the actual prompt.
Configuration Reference
Environment Variables
Required
| Variable | Description |
|---|
CLAUDE_CODE_ENABLE_TELEMETRY | Set to 1 to enable telemetry. |
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA | Set to 1 to enable OTel trace export (beta). |
OTEL_TRACES_EXPORTER | Set to otlp to enable OTLP trace export. |
OTEL_EXPORTER_OTLP_ENDPOINT | Fiddler’s OTLP ingestion endpoint base URL (e.g., https://your-fiddler-instance.com). The OTel SDK appends /v1/traces automatically. |
OTEL_EXPORTER_OTLP_HEADERS | Must include fiddler-application-id=<uuid> and Authorization=Bearer <api-key>. |
OTEL_EXPORTER_OTLP_PROTOCOL | Set to http/protobuf. |
OTEL_RESOURCE_ATTRIBUTES | Must include application.id=<uuid> matching the header above. |
Content Logging
| Variable | Default | Description |
|---|
OTEL_LOG_USER_PROMPTS | 0 | Set to 1 to include user prompt text in traces. When disabled, user_prompt shows <REDACTED>. |
OTEL_LOG_TOOL_DETAILS | 0 | Set to 1 to include additional tool metadata (file_path for Read/Edit/Write, full_command for Bash). |
OTEL_LOG_TOOL_CONTENT | 0 | Set to 1 to include tool input/output content. Currently not functioning as documented — see Known Limitations. |
Optional
| Variable | Default | Description |
|---|
OTEL_SERVICE_NAME | claude-code | Override the service name. Must remain claude-code for Fiddler to detect and map the traces correctly. |
Troubleshooting
Traces not appearing in Fiddler
-
Verify telemetry is enabled:
echo $CLAUDE_CODE_ENABLE_TELEMETRY # should be 1
echo $CLAUDE_CODE_ENHANCED_TELEMETRY_BETA # should be 1
echo $OTEL_TRACES_EXPORTER # should be otlp
-
Verify the OTLP endpoint, protocol, and headers are set:
echo $OTEL_EXPORTER_OTLP_ENDPOINT # should be the base URL (no /v1/traces)
echo $OTEL_EXPORTER_OTLP_PROTOCOL # should be http/protobuf
echo $OTEL_EXPORTER_OTLP_HEADERS # should contain fiddler-application-id
echo $OTEL_RESOURCE_ATTRIBUTES # should contain application.id
-
Verify
application.id in OTEL_RESOURCE_ATTRIBUTES is a valid UUID for an existing Fiddler application. Spans with an invalid or missing application.id are dropped during ingestion.
-
Verify the endpoint URL is the base URL (the SDK appends
/v1/traces automatically) and OTEL_EXPORTER_OTLP_PROTOCOL is set to http/protobuf.
User prompts showing as <REDACTED>
Set OTEL_LOG_USER_PROMPTS=1 in the environment before launching Claude Code. This is disabled by default for privacy.
Tool spans only include tool_name and duration_ms by default. Setting OTEL_LOG_TOOL_DETAILS=1 adds file_path (for Read/Edit/Write tools) and full_command (for Bash tools). However, tool input/output content is not currently available in trace spans — see Known Limitations.
Enrichment worker skipping spans
If you see warnings like Missing fiddler.span.system.gen_ai.agent.name in span.attributes, the Fiddler mapper automatically sets this to "claude-code" on all spans. Ensure you are running the latest version of the external OTel consumer that includes the Claude Code mapper.
Spans classified as chain instead of expected types
Only three span types have specific classifications: claude_code.interaction (agent), claude_code.llm_request (llm), and claude_code.tool (tool). All other spans — including tool.blocked_on_user and tool.execution — are classified as chain. This is expected behavior.
Known Claude Code Upstream Limitations
Claude Code’s OpenTelemetry tracing is currently in beta and has several limitations that affect what data is available in Fiddler. These are not Fiddler issues — they are limitations of Claude Code’s OTel instrumentation. Fiddler captures and maps every attribute that Claude Code emits.
LLM response content not available in traces
Claude Code does not emit LLM response text as a trace span attribute. Response content is only available via OTel log records (controlled by OTEL_LOGS_EXPORTER and OTEL_LOG_RAW_API_BODIES), not trace spans. Additionally, OTel log records are currently emitted without trace_id or span_id, making log-to-trace correlation impossible.
Impact: Session views in Fiddler show user prompts (input) but not Claude’s responses (output). Evaluators that require both input and output (e.g., response faithfulness) cannot run on Claude Code traces.
Claude Code’s documentation states that OTEL_LOG_TOOL_CONTENT=1 records a tool.output span event with tool input and output bodies. In practice, tool spans have empty event arrays — the tool.output event is not emitted. Tool spans only carry tool_name and duration_ms.
Impact: Cannot see what arguments were passed to tools or what they returned. This limits visibility into MCP tool interactions and debugging tool failures.
Tracing is beta and requires opt-in
Claude Code’s OTel tracing requires the CLAUDE_CODE_ENHANCED_TELEMETRY_BETA flag. The trace schema (span names, attribute names, hierarchy) may change between Claude Code versions without notice.
Impact: Fiddler’s mapper may need updates when Claude Code’s trace schema changes. Pin Claude Code versions in managed deployments to avoid unexpected schema changes.
No distributed tracing to LLM providers
Claude Code does not send W3C traceparent headers when making LLM API calls. If Claude Code is routed through a proxy (e.g., LiteLLM), the proxy creates a new trace root rather than continuing Claude Code’s trace. Claude Code traces and proxy traces are separate trace trees.
Claude Code does propagate TRACEPARENT to Bash subprocesses (e.g., when running shell commands), enabling trace correlation for subprocess-initiated LLM calls in non-interactive mode.
Impact: End-to-end distributed traces (user → coding agent → LLM proxy → LLM provider) require joining on session.id or x-claude-code-session-id at query time rather than native trace propagation.
Content redaction is all-or-nothing per category
Content capture is controlled by three separate env vars (OTEL_LOG_USER_PROMPTS, OTEL_LOG_TOOL_DETAILS, OTEL_LOG_TOOL_CONTENT). Each controls an entire category — there is no per-attribute or per-tool-type granularity. You cannot, for example, capture user prompts while keeping tool content redacted within a single category.
Thinking and reasoning content not available
There is no env var to export Claude’s extended thinking or reasoning steps in OTel telemetry. Only metadata (token counts, model, latency) is available for the reasoning process, not the content.
ScopeName and ScopeVersion empty in collected traces
Despite using instrumentation scope com.anthropic.claude_code.tracing 1.0.0, traces may show empty ScopeName and ScopeVersion fields. This does not affect span routing or processing — service.name and span name prefixes are used for detection.
Summary
| Limitation | Severity | Description |
|---|
| No LLM response in traces | High | Output content available only via OTel log records (with broken trace correlation). |
| No tool input/output | High | OTEL_LOG_TOOL_CONTENT=1 does not emit tool.output span events as documented. |
| Beta tracing | Medium | Schema may change between versions. Requires CLAUDE_CODE_ENHANCED_TELEMETRY_BETA. |
| No traceparent to LLM providers | Medium | Separate trace trees for agent and proxy. Join on session ID. |
| All-or-nothing redaction | Low | Cannot selectively control content capture per attribute. |
| No thinking content | Medium | Reasoning steps not available in any telemetry signal. |
| Empty ScopeName/ScopeVersion | Low | Does not affect functionality. |