Skip to main content
This module provides instrumentation for the OpenAI Go SDK (openai/openai-go) using the openinference-instrumentation-openai-go Go package, exporting OpenInference spans to Phoenix.

Install

Requires Go 1.25 or newer.

Setup

Configure an OTLP/HTTP exporter pointed at Phoenix. Create tracing.go:

Run OpenAI

Pass openaiotel.Middleware to the client via option.WithMiddleware. Session and user identifiers are stored on the Go context and applied to every LLM span descended from it.
To redact sensitive data, set OPENINFERENCE_HIDE_INPUTS=true or OPENINFERENCE_HIDE_OUTPUTS=true. See the openinference Go README for the full env-var matrix and the in-code WithTraceConfig override.

Observe

After setting up instrumentation and running your OpenAI application, traces will appear in the Phoenix UI for visualization and analysis. Chat completions (openai.chat.completions.create) and the Responses API (openai.responses.create) are traced as LLM spans, and the Decisions API (openai.decisions.create) as a DECISION span. Embeddings, completions, and image endpoints pass through to the next middleware without a span. Streaming responses pass through unchanged, and the span ends when your code closes or fully reads the body, so its duration reflects time-to-last-token. Streamed Responses calls also record their output and token counts; streamed chat completions do not yet.

Decisions API

The OpenAI Decisions API (client.Decisions.New) asks a decision model a fixed set of typed questions about text or images. It returns one typed, probabilistic answer per question instead of generated text, which makes it a good fit for routing, classification, and scoring inside your application. Requires openinference-instrumentation-openai-go >= v0.1.1. The typed Decisions client arrived in github.com/openai/openai-go/v3 v3.73.0, so install that major:
option.Middleware is a type alias in both major versions, so the same openaiotel.Middleware(...) value passes to a v3 client unchanged. This program replaces the main.go above and reuses the initTracer helper from Setup:
Each call shows up in Phoenix as a DECISION span named openai.decisions.create, rather than an LLM span, containing:
  • input.value: the request body (model, input, questions) as JSON
  • output.value: the response body (answers, model, usage) as JSON
  • decision.system: openai
  • decision.provider: inferred from the client’s host, so openai, or azure for Azure OpenAI
  • decision.request.model_name, decision.response.model_name, and decision.model_name
  • decision.token_count.input and decision.token_count.output, from the response’s usage
Phoenix names the decision model in the span’s input card. The model and its usage are recorded under decision.* rather than llm.*, so decision-model calls stay out of Phoenix’s LLM token and cost reporting. A non-2xx response sets the span status to Error and records only the request attributes. The Decisions API has no streaming mode. The questions and answers live only in input.value and output.value, so OPENINFERENCE_HIDE_INPUTS=true and OPENINFERENCE_HIDE_OUTPUTS=true redact them completely. OPENINFERENCE_HIDE_INPUT_IMAGES=true replaces the image_url of each inline input image with __REDACTED__.

Staying on openai-go v1

openai-go v1 has no Decisions client. Send the request with the generic client.Post, which goes through the same middleware and produces the same span:

Resources