elastic / elastic/integrations
[claude_code] ECS GenAI Field Support for detections
- Dominant language
- Handlebars
- Stars
- 333
- Forks
- 647
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 182
Description
**Related issue:**
- https://github.com/elastic/integrations/issues/20737
Note: for this integration, it should be documented how to turn on `OTEL_LOG_RAW_API_BODIES=1` to collect input/output messages.
TRaDE is requesting that the following fields be added to this integration for security detections:
## Requested fields
| Field | Availability | Status |
|---|---|---|
| `gen_ai.operation.name` | ✅ `attributes.query_source` in `api_request` events (e.g., `"repl_main_thread"`, `"generate_session_title"`) | ⚠️ Semantically mismatched — `query_source` describes the internal Claude Code thread origin, not the LLM operation type; ECS/OTel expects values like `"chat"` or `"text_completion"` |
| `gen_ai.conversation.id` (OTel) | ✅ `attributes.session.id` (UUID) is emitted on all event types and represents a conversation session | ❌ Not implemented — `session.id` is stored as `claude_code.events.session.id` and not mapped to `gen_ai.conversation.id` |
| `gen_ai.input.messages` | ✅ Available via `OTEL_LOG_RAW_API_BODIES=1` | ❌ Not implemented |
| `gen_ai.output.messages` | ✅ Available via `OTEL_LOG_RAW_API_BODIES=1` | ❌ Not implemented |
| `gen_ai.tool.name` | ✅ `attributes.tool_name` for native tools; `mcp_tool_name` extracted from parsed `tool_parameters` JSON for MCP tools (raw `tool_name` is just `"mcp_tool"` for those) | ⚠️ Possibly partially implemented — pipeline correctly resolves MCP tool names from within the `tool_parameters` blob |
| `gen_ai.tool.call.result` | ⚠️ Result content is not logged; only `tool_result_size_bytes` is captured | ❌ Not implemented |
| `destination.address` | ⚠️ `url.full` is extracted from `tool_parameters_flattened.url` for URL-fetching tool calls, but `destination.address` (the hostname) is not separately parsed from it | ❌ Not implemented — `url.full` is populated but `destination.address` is not derived |
## Likely already implemented (verify on development)
| Field | Availability | Status |
|---|---|---|
| `gen_ai.provider.name` | ✅ Hardcoded as `"anthropic"` | ✅ Implemented — defined as `constant_keyword` with value `"anthropic"` |
| `gen_ai.request.model` | ✅ `attributes.model` in `api_request` events (e.g., `"claude-sonnet-4-6"`) | ✅ Implemented — copied from `gen_ai.response.model`; both map to the same source field |
| `gen_ai.response.model` | ✅ `attributes.model` in `api_request` events | ✅ Implemented — note: request and response model are always identical since Claude Code logs a single `model` attribute per API call |
| `gen_ai.usage.input_tokens` | ✅ `attributes.input_tokens` in `api_request` events | ✅ Implemented |
| `gen_ai.usage.output_tokens` | ✅ `attributes.output_tokens` in `api_request` events | ✅ Implemented |
| `gen_ai.response.id` | ✅ `attributes.request_id` in `api_request` events (Anthropic `req_*` identifier) | ✅ Implemented |
| `gen_ai.tool.call.id` | ✅ `attributes.tool_use_id` in `tool_result` and `tool_decision` events | ✅ Implemented |
| `gen_ai.tool.call.arguments` | ✅ `attributes.tool_input` (JSON string) for `tool_result` events; `attributes.tool_parameters` for `tool_decision` events | ✅ Implemented — note: on `tool_decision` events the fallback source is `tool_parameters`, which includes internal Claude Code metadata beyond the model's raw arguments |
| `file.path` | ✅ `file.path` extracted from `tool_parameters_flattened.file_path` (or `.path`) for file-related tool calls | ✅ Implemented — ECS `file.path` is populated from tool parameters |
## Likely not possible (verify on development)
| Field | Availability | Status |
|---|---|---|
| `gen_ai.request.max_tokens` | ❌ Not emitted by the Claude Code CLI; request parameters are not included in telemetry | ❌ Not implemented |
| `gen_ai.request.temperature` | ❌ Not emitted by the Claude Code CLI | ❌ Not implemented |
| `gen_ai.request.seed` | ❌ Not emitted by the Claude Code CLI | ❌ Not implemented |
| `gen_ai.request.stop_sequences` | ❌ Not emitted by the Claude Code CLI | ❌ Not implemented |
| `gen_ai.response.finish_reasons` | ❌ Stop reason is not emitted by the Claude Code CLI | ❌ Not implemented |
| `gen_ai.token.type` | ❌ Not a discrete field in Claude Code telemetry | ❌ Not implemented |
| `gen_ai.output.type` | ❌ Not logged | ❌ Not implemented |
| `gen_ai.system_instructions` | ❌ Not logged in Claude Code telemetry | ❌ Not implemented |
| `gen_ai.tool.definitions` | ❌ Tool schemas and descriptions are not emitted in Claude Code telemetry | ❌ Not implemented |
| `gen_ai.tool.type` | ❌ Not a discrete field; could be inferred (native vs. MCP) but is not logged | ❌ Not implemented |
Contributor guide
Research direction
Start with related issue #20737 and the existing claude_code integration mappings, then verify the listed ECS GenAI fields against development telemetry. Document how to enable OTEL_LOG_RAW_API_BODIES=1, map the feasible fields, and clearly record fields that Claude Code does not emit as out of scope.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- handlebars
- Domain
- observability, security
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100