elastic / elastic/integrations

[azure_openai] ECS GenAI Field Support for detections

Open
#20,739 1 comment 0 reactions 0 assignees View on GitHub
Integration:azure_openai Team:Security-Service Integrations
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.