How do I trace the OpenAI API in Python?
Rius traces the OpenAI API in Python with one install command and one init call, and you keep using your OpenAI client exactly as before. Install glassflow-rius[openai], call rius.init() once at startup, and every chat completion from your process arrives as a span with the model, token counts, messages and cost. You can confirm it by running one call and opening the trace in the console.
How it works
The openai extra installs the Rius instrumentation for the OpenAI client library. When you call rius.init(), it detects that extra and instruments the client library process-wide. Every call from anywhere in your process is traced, so you change nothing at your call sites.
A few details are worth knowing:
- The extra installs the instrumentation, not
openaiitself. A project that already calls OpenAI has the library, and pip leaves it untouched. In a fresh environment, nameopenaiin the install command as shown below. - If the extra is installed without
openai,init()logs aDependencyConflictand the OpenAI integration stays off. - With a default global
init(), every installed integration turns on automatically.rius.init(instruments=["openai"])restricts tracing to OpenAI, andrius.init(instruments=[])turns all integrations off. - Cost is computed by Rius from the model and the token counts. You never send a cost value.
The OpenAI integration page covers setup and blind spots in full, and the Integrations page lists every library and framework Rius traces the same way.
Set it up
- Check that you run Python 3.10 or newer, then install the SDK with the OpenAI extra. Add
openaiif your environment does not have it yet.
pip install "glassflow-rius[openai]" openai- Call
init()once, as early as possible in your process, before you make a request. Setservice_nameexplicitly, because it is how you find your agent in trace filters and cost breakdowns. It defaults tounknown_service. The installation page lists every argument and its environment variable, such asRIUS_API_KEYandRIUS_SERVICE_NAME.
import rius
from openai import OpenAI
rius.init(api_key="ri_...", service_name="my-agent")
client = OpenAI() # use the client exactly as before- Make a call. This minimal example wraps a function in
@rius.observe, so the OpenAI call shows nested inside your agent’s run instead of as a standalone trace. Replace the model and message with your own.
@rius.observe
def handle(query: str) -> str:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": query}],
)
return response.choices[0].message.content
handle("What should I check when a collector drops spans?")- If you stream responses, ask OpenAI to send usage with the final chunk. Without it, streamed spans have no token counts, and no tokens means no cost.
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
stream=True,
stream_options={"include_usage": True},
)- Open the trace in the console and check the span, as described next.
What you get
Each chat completion becomes an LLM-kind span. In the console you see:
- The resolved model, for example
gpt-4o-mini-2024-07-18. - Input and output token counts.
- A cost for the call. Costs are list-price estimates in US dollars, not billed amounts.
- Input and output messages, plus request parameters, finish reasons, the completion id and tool definitions, mapped onto the canonical GenAI keys.
- Time to first token on streamed calls, recorded by the Python integration without any manual code.
- Failures as ERROR spans. A call OpenAI rejects, such as a 404 for an unknown model, a 429 or a timeout, carries
error.typenaming the error class, for exampleopenai.NotFoundError.
Prompt and response content follows your privacy controls. Set capture_content=False in init() and prompt and response content is stripped at export while metadata still flows. A mask callable redacts content attributes the same way, and both apply to instrumented calls exactly like manual ones.
When something else fits
- If your OpenAI calls run through a framework such as the OpenAI Agents SDK, LangChain or LiteLLM, start from that framework’s page under Integrations, because each page shows what lands in the trace.
- If you work in TypeScript, the OpenAI integration page has the npm setup, which differs from the Python steps here.
- If you need to trace a model call no integration covers, use manual generations with
observeinstead.