Install the OpenInference instrumentor for your provider, register a tracer provider with your Arize credentials, and attach the instrumentor — .instrument() in Python, registerInstrumentations({...}) / package-specific setup in JS/TS, or option.WithMiddleware(...) on the SDK client in Go.Register and instrument
from arize.otel import register
from openinference.instrumentation.openai import OpenAIInstrumentor
tracer_provider = register(
space_id="YOUR_SPACE_ID", # Settings > API Keys in Arize AX
api_key="YOUR_API_KEY", # Settings > API Keys > + New API Key
project_name="my-project",
)
OpenAIInstrumentor().instrument(tracer_provider=tracer_provider)
import { NodeTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-node";
import { registerInstrumentations } from "@opentelemetry/instrumentation";
import { resourceFromAttributes } from "@opentelemetry/resources";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import OpenAI from "openai";
import { OpenAIInstrumentation } from "@arizeai/openinference-instrumentation-openai";
const provider = new NodeTracerProvider({
resource: resourceFromAttributes({
["openinference.project.name"]: "my-project",
}),
spanProcessors: [
new SimpleSpanProcessor(
new OTLPTraceExporter({
url: "https://otlp.arize.com/v1/traces",
headers: {
'arize-space-id': 'YOUR_SPACE_ID',
'arize-api-key': 'YOUR_API_KEY',
},
}),
),
],
});
const instrumentation = new OpenAIInstrumentation();
instrumentation.manuallyInstrument(OpenAI);
registerInstrumentations({ instrumentations: [instrumentation] });
provider.register();
arizeotel.Register returns a configured *sdktrace.TracerProvider, installs it as the global, and reads ARIZE_SPACE_ID / ARIZE_API_KEY from the environment when the matching Options fields are unset. Attach the OpenAI middleware via option.WithMiddleware:import (
"context"
"log"
"os"
"time"
arizeotel "github.com/Arize-ai/arize-otel-go"
openaiotel "github.com/Arize-ai/openinference/go/openinference-instrumentation-openai-go"
"github.com/openai/openai-go"
"github.com/openai/openai-go/option"
"go.opentelemetry.io/otel"
)
tp, err := arizeotel.Register(ctx, arizeotel.Options{
ProjectName: "my-project",
})
if err != nil { log.Printf("register tracer: %v", err); return }
defer func() {
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = tp.Shutdown(shutdownCtx)
}()
client := openai.NewClient(
option.WithAPIKey(os.Getenv("OPENAI_API_KEY")),
option.WithMiddleware(openaiotel.Middleware(otel.Tracer("my-project"))),
)
Run your app
Every OpenAI call is now traced automatically:import openai
client = openai.OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "What is observability?"}],
)
const client = new OpenAI();
const response = await client.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "What is observability?" }],
});
The middleware auto-emits an LLM-kind span around every /v1/chat/completions request — prompt, response, token counts, and finish reason are all set for you.import (
"github.com/openai/openai-go"
"github.com/openai/openai-go/shared"
)
resp, err := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{
Model: shared.ChatModel("gpt-5"),
Messages: []openai.ChatCompletionMessageParamUnion{
openai.UserMessage("What is observability?"),
},
})
This example uses OpenAI, but the same pattern works for any provider — install the instrumentor and attach it (.instrument() in Python, registerInstrumentations({...}) in JS/TS, or option.WithMiddleware(...) in Go).For some frameworks (CrewAI, LangChain, AutoGen, LlamaIndex), .instrument() must run before importing the library — they patch methods at runtime, so objects created earlier will not emit spans. See each integration page for specifics.