elastic / elastic/integrations

[litellm] ECS GenAI Field Support for detections

Open
#20,745 1 comment 0 reactions 0 assignees View on GitHub
Team:Security-Service Integrations
Dominant language
Handlebars
Stars
333
Forks
647
Avg merge
2d 17h
Merged PRs (30d)
225

Description

**Related issue:**
- https://github.com/elastic/integrations/issues/20737
- https://github.com/elastic/integrations/issues/19412

TRaDE is requesting that the following fields be added to this integration for security detections:

## Requested fields
| Field | Availability | Status |
|---|---|---|
| `gen_ai.provider.name` | ✅ `custom_llm_provider` in `/spend/logs/v2` | ⚠️ Mapped to non-standard `gen_ai.system` instead of `gen_ai.provider.name` |
| `gen_ai.request.model` | ✅ `model` in `/spend/logs/v2` | ✅ Implemented |
| `gen_ai.operation.name` | ✅ `call_type` in `/spend/logs/v2` (e.g. `acompletion`, `embedding`) | ✅ Implemented |
| `gen_ai.conversation.id` | ✅ `session_id` in `/spend/logs/v2` | ❌ Not implemented — field in schema, no gen_ai mapping in pipeline |
| `gen_ai.usage.input_tokens` | ✅ `prompt_tokens` in `/spend/logs/v2` | ✅ Implemented |
| `gen_ai.usage.output_tokens` | ✅ `completion_tokens` in `/spend/logs/v2` | ✅ Implemented |
| `gen_ai.usage.cache_read.input_tokens` | ✅ `metadata.additional_usage_values.prompt_tokens_details.cached_tokens` (in `metadata` JSONB returned by `/spend/logs/v2`) | ❌ Not implemented — field defined in schema, no gen_ai mapping |
| `gen_ai.response.finish_reasons` | ⚠️ Available via S3 transport only (full `StandardLoggingPayload` includes `choices[].finish_reason`); `/spend/logs/v2` excludes `response` body | ❌ Not implemented |
| `gen_ai.input.messages` | ⚠️ Available via S3 transport only; `/spend/logs/v2` deliberately excludes `messages` as a heavy column | ❌ Not implemented — `lite_llm.spend_tracking.messages` field defined in schema but no gen_ai mapping and no pipeline parsing |
| `gen_ai.output.type` | ⚠️ Derivable from `response` body via S3 transport only | ❌ Not implemented |
| `gen_ai.output.messages` | ⚠️ Available via S3 transport only; `/spend/logs/v2` deliberately excludes `response` as a heavy column | ❌ Not implemented — `lite_llm.spend_tracking.response` field defined in schema but no gen_ai mapping and no pipeline parsing |
| `gen_ai.response.id` | ✅ `request_id` in `/spend/logs/v2` | ✅ Implemented |
| `gen_ai.tool.name` | ✅ `mcp_namespaced_tool_name` in `/spend/logs/v2` (MCP tool calls only) | ✅ Implemented |
| `destination.address` | ✅ `api_base` in `/spend/logs/v2` (backend provider URL) | ❌ Not implemented |

## Likely not possible (verify on development)
| Field | Availability | Status |
|---|---|---|
| `gen_ai.response.model` | ❌ Not separately tracked — LiteLLM uses one `model` field for both request and response | ❌ Not implemented |
| `gen_ai.request.max_tokens` | ❌ Not in `/spend/logs/v2`; original request params are not persisted to `LiteLLM_SpendLogs` | ❌ Not implemented |
| `gen_ai.request.temperature` | ❌ Not in `/spend/logs/v2` | ❌ Not implemented |
| `gen_ai.request.seed` | ❌ Not in `/spend/logs/v2` | ❌ Not implemented |
| `gen_ai.request.stop_sequences` | ❌ Not in `/spend/logs/v2` | ❌ Not implemented |
| `gen_ai.token.type` | ❌ Not applicable — per-request log, not a token classification event | ❌ Not applicable |
| `gen_ai.system_instructions` | ❌ Not in `StandardLoggingPayload` | ❌ Not implemented |
| `gen_ai.tool.definitions` | ❌ Not in `StandardLoggingPayload` | ❌ Not implemented |
| `gen_ai.tool.call.id` | ❌ Not in `StandardLoggingPayload` | ❌ Not implemented |
| `gen_ai.tool.type` | ❌ Not in `StandardLoggingPayload` | ❌ Not implemented |
| `gen_ai.tool.call.result` | ❌ Not in `StandardLoggingPayload` | ❌ Not implemented |
| `gen_ai.tool.call.arguments` | ❌ Not in `StandardLoggingPayload` | ❌ Not implemented |
| `file.*` | ❌ Not applicable — LiteLLM is a network proxy, not a file-operation source | ❌ Not applicable |

## Thinking Block Collection — End-to-End Configuration Guide

**Provider config:** None at the LiteLLM level. The upstream caller controls `display: "summarized"` on Claude requests. LiteLLM passes through whatever it receives.

**What lands in raw data:**
- Via **S3 transport** (full `StandardLoggingPayload`): `response.provider_specific_fields.thinking_blocks[]` and `response.choices[].message.provider_specific_fields.thinking_blocks[]`
- Via **`/spend/logs/v2` API** (default integration transport): `messages` and `response` are deliberately excluded as "heavy columns" — thinking blocks are not available via this path

**Integration gap:** The current integration uses `/spend/logs/v2` which doesn't expose the response body at all. To get thinking blocks, the integration would need to use the S3 transport. That is a transport change, not just a field mapping change.

Contributor guide

Open the contributing guide

Research direction

Start by inspecting the current /spend/logs/v2 integration pipeline and the LiteLLM schema fields mentioned in the issue. Compare its mappings with the full StandardLoggingPayload available through S3 transport, especially messages, response, and thinking_blocks. Done means the feasible ECS GenAI fields are mapped and the transport limitations are verified for the remaining fields.

Written by the indexing model from the issue text.

Assessment

Domain
observability
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.