elastic / elastic/integrations
[litellm] ECS GenAI Field Support for detections
- 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
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