The Tracing capabilities in Portkey empowers you to monitor the lifecycle of your LLM requests in a unified, chronological view.
This is perfect for agentic workflows, chatbots, or multi-step LLM calls, by helping you understand and optimize your AI application's performance.
How Tracing Works
Portkey implements OpenTelemetry-compliant tracing. When you include a trace ID with your requests, all related LLM calls are grouped together in the Traces View, appearing as "spans" within that trace.
"Span" is another word for subgrouping of LLM calls. Based on how you instrument, it can refer to another group within your trace or to a single LLM call.
Trace Tree Structure
Portkey uses a tree data structure for tracing, similar to OTel.
Each node in the tree is a span with a unique spanId and optional spanName. Child spans link to a parent via the parentSpanId. Parentless spans become root nodes.
traceId
├─ parentSpanId
│ ├─ spanId
│ ├─ spanName
Key - Node
Key - Python
Expected Value
Required?
traceId
trace_id
Unique string
YES
spanId
span_id
Unique string
NO
spanName
span_name
string
NO
parentSpanId
parent_span_id
Unique string
NO
Enabling Tracing
You can enable tracing by passing the trace tree values while making your request (or while instantiating your client).
Based on these values, Portkey will instrument your requests, and will show the exact trace with its spans on the "Traces" view in Logs page.
Add tracing details to a single request (recommended)
constrequestOptions= { traceId:"1729", spanId:"11", spanName:"LLM Call"}constchatCompletion=awaitportkey.chat.completions.create({ messages: [{ role:'user', content:'Say this is a test' }], model:'gpt-4o',}, requestOptions);
Or, add trace details while instantiating your client
import { createHeaders } from'portkey-ai'constrequestOptions= { traceId:"1729", spanId:"11", spanName:"LLM Call"}constchatCompletion=awaitopenai.chat.completions.create({ messages: [{ role:'user', content:'Say this is a test' }], model:'gpt-3.5-turbo',}, requestOptions);
from portkey_ai import createHeadersreq_headers =createHeaders( trace_id="1729", span_id="11", span_name="LLM Call)chat_complete = client.with_options(headers=req_headers).chat.completions.create( model="gpt-4", messages=[{"role": "user", "content": "Say this is a test"}],)
If you are only passing trace ID and not the span details, you can set the trace ID while making your request or while instantiating your client.
constrequestOptions= {traceID:"YOUR_TRACE_ID"}constchatCompletion=awaitportkey.chat.completions.create({ messages: [{ role:'user', content:'Say this is a test' }], model:'gpt-4o',}, requestOptions);console.log(chatCompletion.choices);
completion = portkey.with_options( trace_id ="TRACE_ID").chat.completions.create( messages = [{ "role": 'user', "content": 'Say this is a test' }], model ='gpt-3.5-turbo')
Pass Trace ID while instantiating your client
from portkey_ai import Portkeyportkey =Portkey( api_key="PORTKEY_API_KEY", virtual_key="VIRTUAL_KEY", trace_id="TRACE_ID")
import { createHeaders } from'portkey-ai'constreqHeaders= {headers:createHeaders({"traceID":"TRACE_ID"})}constchatCompletion=awaitopenai.chat.completions.create({ messages: [{ role:'user', content:'Say this is a test' }], model:'gpt-3.5-turbo',}, reqHeaders);
from portkey_ai import createHeadersreq_headers =createHeaders(trace_id="TRACE_ID")chat_complete = client.with_options(headers=req_headers).chat.completions.create( model="gpt-4", messages=[{"role": "user", "content": "Say this is a test"}],)
In Llama Index, you can also set the callback at a global level
from llama_index.core import Settingsfrom llama_index.core.callbacks import CallbackManagerSettings.callback_manager =CallbackManager([portkey_handler])Settings.llm = llm
Inserting Logs
If you are using the Insert Log API to add logs to Portkey, your traceId, spanId etc. will become part of the metadata object in your log, and Portkey will instrument your requests to take those values into account.
The logger endpoint supports inserting a single log as well as log array, and helps you build traces of any depth or complexity. For more, check here:
Tracing also works very well to capture the Gateway behavior on retries, fallbacks, and other routing mechanisms on Portkey Gateway.
Portkey automatically groups all the requests that were part of a single fallback or retry config and shows the failed and succeeded requests chronologically as "spans" inside a "trace".
This is especially useful when you want to understand the total latency and behavior of your app when retry or fallbacks were triggered.
Cost Insights: View aggregate LLM costs at the trace level.
Debugging: Easily browse all requests in a single trace and identify failures.
Performance Analysis: Understand your entire request lifecycle and total trace duration.
User Feedback Integration: Link user feedback to specific traces for targeted improvements.
Capturing User Feedback
Trace IDs can also be used to link user feedback to specific generations. This can be used in a system where users provide feedback, like a thumbs up or thumbs down, or something more complex via our feedback APIs. This feedback can be linked to traces which can span over a single generation or multiple ones. Read more here: