elastic / elastic/integrations
[azure_openai] ECS GenAI Field Support for detections
- Dominant language
- Handlebars
- Stars
- 333
- Forks
- 647
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 209
Description
**Related issue:**
- https://github.com/elastic/integrations/issues/20737
TRaDE is requesting that the following fields be added to this integration for security detections:
## Requested fields
| Field | Availability | Status |
|---|---|---|
| `gen_ai.provider.name` | ✅ Can be hardcoded as `"az.ai.openai"` (the OTel standard value for this provider) | ❌ Not implemented — no `gen_ai.*` fields exist in this integration |
| `gen_ai.request.model` | ✅ `properties.backend_request_body.model` (deployment name) and `properties.model_name` (actual model ID, e.g., `gpt-35-turbo`) present in GatewayLogs | ❌ Not implemented — stored as `azure.open_ai.properties.backend_request_body.model` and `azure.open_ai.properties.model_deployment_name` |
| `gen_ai.response.model` | ✅ `backend_response_body.model` contains the actual model ID (e.g., `gpt-35-turbo`) — GatewayLogs only | ❌ Not implemented — stored as `azure.open_ai.properties.backend_response_body.model` |
| `gen_ai.request.max_tokens` | ⚠️ Only present in `backend_request_body` if the client explicitly sets it; not a guaranteed field in the logs | ❌ Not implemented |
| `gen_ai.request.temperature` | ⚠️ Same as `max_tokens` — only in `backend_request_body` if the client explicitly sets it | ❌ Not implemented |
| `gen_ai.request.seed` | ⚠️ Only in `backend_request_body` if explicitly set by the client; Azure OpenAI supports it but it's not always logged | ❌ Not implemented |
| `gen_ai.request.stop_sequences` | ⚠️ Only in `backend_request_body` if explicitly set by the client | ❌ Not implemented |
| `gen_ai.operation.name` | ✅ `azure.open_ai.operation_name` present (e.g., `ChatCompletions_Create`) across all log categories | ❌ Not implemented — stored as `azure.open_ai.operation_name` only |
| `gen_ai.usage.input_tokens` | ✅ `backend_response_body.usage.input_tokens` present in GatewayLogs (pipeline already renames `prompt_tokens` → `input_tokens`); aggregate counts also available in `metrics` datastream | ❌ Not implemented in `gen_ai.*` namespace — stored as `azure.open_ai.properties.backend_response_body.usage.input_tokens` |
| `gen_ai.usage.output_tokens` | ✅ `backend_response_body.usage.output_tokens` present in GatewayLogs (pipeline renames `completion_tokens` → `output_tokens`); aggregate also in `metrics` datastream | ❌ Not implemented in `gen_ai.*` namespace — stored as `azure.open_ai.properties.backend_response_body.usage.output_tokens` |
| `gen_ai.response.finish_reasons` | ✅ `backend_response_body.choices[].finish_reason` present in GatewayLogs (e.g., `"stop"`) | ❌ Not implemented — stored as `azure.open_ai.properties.backend_response_body.choices[].finish_reason` |
| `gen_ai.input.messages` | ✅ `backend_request_body.messages[]` with `role` and `content` fully captured in GatewayLogs | ❌ Not implemented — stored as `azure.open_ai.properties.backend_request_body.messages` |
| `gen_ai.output.messages` | ✅ `backend_response_body.choices[].message` with `role` and `content` fully captured in GatewayLogs | ❌ Not implemented — stored as `azure.open_ai.properties.backend_response_body.choices` |
| `gen_ai.response.id` | ✅ `backend_response_body.id` (e.g., `chatcmpl-...`) present in GatewayLogs | ❌ Not implemented — stored as `azure.open_ai.properties.backend_response_body.id` |
| `gen_ai.system_instructions` | ⚠️ Not a discrete field; system instructions are embedded in `backend_request_body.messages[]` as entries with `role: "system"` — requires extraction from the messages array | ❌ Not implemented |
| `gen_ai.tool.definitions` | ⚠️ Would appear in `backend_request_body.tools[]` if the client sends tool definitions; present in GatewayLogs when used, but not in sample events | ❌ Not implemented |
| `gen_ai.tool.call.id` | ⚠️ Would appear in `backend_response_body.choices[].message.tool_calls[].id` when tool calls are made; captured in GatewayLogs when present | ❌ Not implemented |
| `gen_ai.tool.name` | ⚠️ Would appear in `backend_response_body.choices[].message.tool_calls[].function.name`; captured in GatewayLogs when present | ❌ Not implemented |
| `gen_ai.tool.type` | ⚠️ Would be `"function"` in `backend_response_body.choices[].message.tool_calls[].type`; captured in GatewayLogs when present | ❌ Not implemented |
| `gen_ai.tool.call.result` | ⚠️ Would appear in `backend_request_body.messages[]` as messages with `role: "tool"`; captured in GatewayLogs when present | ❌ Not implemented |
| `gen_ai.tool.call.arguments` | ⚠️ Would appear in `backend_response_body.choices[].message.tool_calls[].function.arguments`; captured in GatewayLogs when present | ❌ Not implemented |
## Likely not possible (verify on development)
| Field | Availability | Status |
|---|---|---|
| `gen_ai.output.type` | ⚠️ `azure.open_ai.properties.stream_type` is available but indicates streaming mode, not output content type; not a direct equivalent | ❌ Not implemented |
| `gen_ai.conversation.id` (OTel) | ❌ No native conversation/session ID in Azure OpenAI logs; `correlation_id` is per-request, not per-conversation | ❌ Not implemented |
| `gen_ai.token.type` | ❌ Not a discrete field in Azure OpenAI logs; token counts are aggregated per invocation | ❌ Not implemented |
## Thinking Block Collection — End-to-End Configuration Guide
**Provider config:**
- Enable diagnostic settings → route "Request and Response Logs" + "Logs related to generative AI gateway" categories to Log Analytics/Storage
- Caller must set `display: "summarized"` on Claude requests
- Stay under 200 KB if using Event Hub routing
**What lands in raw data:**
- `BackendResponseBody` (string) — full Claude response JSON including thinking blocks
- `ResponseMessages` in `ApiManagementGatewayLlmLog` — structured content array
**Integration gap:** The integration already parses `properties.backend_response_body`. Thinking blocks would be inside `backend_response_body.content[]` the same as Bedrock. Same pipeline processor needed.
Contributor guide
Research direction
Start by reading the existing Azure OpenAI integration pipeline that parses properties.backend_response_body and compare its processor with the Bedrock pipeline. Map the requested ECS GenAI fields, including thinking blocks in content[], and verify which fields are available in GatewayLogs versus optional or unavailable fields. Done means supported fields are populated and unsupported fields are verified on development.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure
- Domain
- ai
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100