# `Impact.Instrumentation.OpenAI`

Auto-instrumentation for OpenAI-compatible Chat Completions endpoints via
`Req`. Works for OpenAI proper (`api.openai.com`), Azure OpenAI, and the
OpenAI-compatible AWS Bedrock endpoint (`bedrock-*.api.aws`).

Wraps a `Req` request in an OpenTelemetry LLM span tagged with GenAI
semantic-convention attributes. No span code at the call site.

## Usage

    Req.new(
      method: :post,
      url: "https://api.openai.com/v1/chat/completions",
      json: %{model: "gpt-4", messages: [...], tools: [...]},
      headers: [{"authorization", "Bearer ..."}]
    )
    |> Impact.Instrumentation.OpenAI.request()

Detects the path `/chat/completions` (with or without a leading version
segment). Non-matching URLs fall through to plain `Req.request/1`.

## What's captured

Request:
  * `gen_ai.system`            — "openai" / "aws.bedrock" / "azure" depending on host
  * `gen_ai.provider.name`     — same
  * `gen_ai.operation.name`    — "chat"
  * `gen_ai.request.model`
  * `gen_ai.request.max_tokens` / `temperature` / `top_p`
  * `gen_ai.input.messages`     — JSON of `[{role, content}, ...]`
  * `gen_ai.system_instructions` — JSON of system message contents

Response:
  * `gen_ai.response.id` / `gen_ai.response.model`
  * `gen_ai.usage.input_tokens` / `output_tokens` / `total_tokens`
  * `gen_ai.response.finish_reasons`
  * `gen_ai.output.messages`    — JSON of `[{role, content}]`
  * `gen_ai.tool.names`         — csv of names when `finish_reason="tool_calls"`

# `request`

```elixir
@spec request(Req.Request.t()) :: {:ok, Req.Response.t()} | {:error, term()}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
