OpenAI
Adds instrumentation for the OpenAI SDK.
Import name: Sentry.instrumentOpenAiClient
The instrumentOpenAiClient helper instruments the openai SDK by wrapping your client instance and recording LLM interactions with configurable input/output capture.
On Cloudflare Workers, enable tracing on the worker (for example with Sentry.withSentry and tracesSampleRate), then wrap every OpenAI client you use. Tracing alone is not enough — unwrapped clients produce no gen_ai.* spans.
import * as Sentry from "@sentry/cloudflare";
import OpenAI from "openai";
export default Sentry.withSentry(
(env) => ({
dsn: env.SENTRY_DSN,
tracesSampleRate: 1.0,
}),
{
async fetch(request, env) {
const openai = new OpenAI({
apiKey: env.OPENAI_API_KEY,
});
const client = Sentry.instrumentOpenAiClient(openai, {
recordInputs: true,
recordOutputs: true,
});
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello!" }],
});
return Response.json(response);
},
},
);
import * as Sentry from "@sentry/cloudflare";
import OpenAI from "openai";
export default Sentry.withSentry(
(env) => ({
dsn: env.SENTRY_DSN,
tracesSampleRate: 1.0,
}),
{
async fetch(request, env) {
const openai = new OpenAI({
apiKey: env.OPENAI_API_KEY,
});
const client = Sentry.instrumentOpenAiClient(openai, {
recordInputs: true,
recordOutputs: true,
});
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello!" }],
});
return Response.json(response);
},
},
);
If you call OpenAI from a Durable Object over RPC, set enableRpcTracePropagation: true on both the Worker (caller) and the DO (receiver). Wrap the DO with instrumentDurableObjectWithSentry. See RPC Trace Propagation.
For multi-turn Conversations and the User column, see Tracking Conversations (setConversationId / setUser).
To customize what data is captured (such as inputs and outputs), see the Options in the Configuration section.
The following options control what data is captured from OpenAI SDK calls:
Type: boolean (optional)
Records inputs to OpenAI SDK calls (such as prompts and messages).
Defaults to true if dataCollection.genAI.inputs is true (which is the default when using dataCollection), or if the deprecated sendDefaultPii is true.
Type: boolean (optional)
Records outputs from OpenAI SDK calls (such as generated text and responses).
Defaults to true if dataCollection.genAI.outputs is true (which is the default when using dataCollection), or if the deprecated sendDefaultPii is true.
Usage
Using the instrumentOpenAiClient wrapper:
const client = Sentry.instrumentOpenAiClient(openai, {
// your options here
});
const client = Sentry.instrumentOpenAiClient(openai, {
// your options here
});
By default, tracing support is added to the following OpenAI SDK calls:
chat.completions.create()- Chat completion requestsresponses.create()- Response SDK requests
Streaming and non-streaming requests are automatically detected and handled appropriately.
Both APIs produce the same span type in Sentry: op gen_ai.chat, name like chat <model>. There is no separate gen_ai.responses span — responses.create() is still a model chat request under the hood, so it uses the standard chat operation.
Instrumented calls record model, token usage, latency, and (when enabled) inputs/outputs on the LLM span. If you pass tools to the request, Sentry stores the tool definitions on the span and records any tool calls the model returns as span attributes.
The OpenAI SDK does not run your tools — your application does, after the model returns tool_calls. Because of that, instrumentOpenAiClient / openAIIntegration do not create gen_ai.execute_tool spans for local tool handlers.
To get the full agent tree (gen_ai.invoke_agent → gen_ai.chat + gen_ai.execute_tool), wrap your tool loop with manual instrumentation.
When using OpenAI's streaming API, you must also pass stream_options: { include_usage: true } to receive token usage data. Without this option, OpenAI does not include prompt_tokens or completion_tokens in streamed responses, and Sentry will be unable to capture gen_ai.usage.input_tokens / gen_ai.usage.output_tokens on the resulting span. This is an OpenAI API behavior, not a Sentry limitation. See OpenAI API reference.
const stream = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello!" }],
stream: true,
stream_options: { include_usage: true },
});
const stream = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello!" }],
stream: true,
stream_options: { include_usage: true },
});
openai:>=4.0.0 <7
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").