Track users and sessions
Attach a session id and a user id to each unit of work so that AIO groups related traces into one session.
Prerequisites
- The Python SDK is installed, and
aio.init()runs at startup. For setup steps, see Instrument your code.
Attach session and user ids in code
A session is every trace that shares one conversation id. Each trace in a session is a turn. To group traces into a session, wrap each unit of work in aio.root_span() and pass it the same conversation_id on every turn.
- Call
aio.init()once at startup, before you create any HTTP or model clients. - For each chat turn, workflow run, or scheduled job, open a
with aio.root_span(conversation_id, ...)block. - Pass the same
conversation_idfor every turn of one conversation. - Pass
user_idto record who the turn belongs to. - Pass
input_previewwith the user's message, so the UI can show it as the turn's message.
The following example sends two turns of one conversation. Before you run it, set the environment variables that Instrument your code describes, and replace the ids with your own values.
import acceldata_aio_tracer as aio
aio.init(service="support-bot")
def answer(message: str) -> str:
# Call your model here.
return f"You asked: {message}"
def handle_message(conversation_id: str, user_id: str, message: str) -> str:
with aio.root_span(
conversation_id,
user_id=user_id,
input_preview=message,
name="handle_message",
):
return answer(message)
handle_message("conv-1234", "user-42", "How do I reset my password?")
handle_message("conv-1234", "user-42", "And how do I change my email address?")
Both calls use conv-1234, so their traces appear as two turns of one session.
Every span you start inside the root_span block, including model and tool calls, carries the same conversation id and user id.
Parameters of aio.root_span
Parameter | What it does |
| The session id. Traces that share it group into one session. |
| The user id for the root span and every span inside it. |
| Text the UI shows as the turn's message. It's cut to 2000 characters. |
| The root span's name. The default is |
| Overrides the process-wide tenant for spans inside the block. |
| Overrides the process-wide project for spans inside the block. |
Use a fixed label for name, such as handle_message, rather than text that changes with each request.
When you nest root_span blocks, tenant_id, project_id, and user_id apply to the inner block only. The outer values come back when the inner block exits.
Important
AIO only understands the conversation id that root_span sets (gen_ai.conversation.id). If your app sets session.id or a vendor-specific session attribute instead, that value is dropped, and the traces don't group into a session.
Read the current session id
Call aio.current_conversation_id() inside a root_span block to get the active conversation id. Outside a block, it returns None.
import acceldata_aio_tracer as aio
aio.init(service="support-bot")
with aio.root_span("conv-1234", input_preview="Hello"):
print(aio.current_conversation_id()) # conv-1234
print(aio.current_conversation_id()) # None
How root_span behaves when something goes wrong
- If
aio.init()hasn't run,root_spandoes nothing, and your code runs as usual. - If
root_spanitself fails, it doesn't raise. The block runs, and the value it yields isNone. - If your own code raises an exception inside the block, the exception is raised again as usual.
Check the session in the UI
- In your project, go to the Sessions tab.
- Select the session's First message link.
The session page lists each trace as a turn. Each turn shows the input_preview you passed as its message. Without an input preview, it shows the root span's name, and without that, the trace id.
For more about reading sessions, see Explore traces.
Troubleshooting
The Sessions list says "No sessions in this window"
- Check that each unit of work runs inside
aio.root_span()with aconversation_id. Spans without a conversation id don't appear in any session. - Check that
aio.init()runs beforeroot_span. Otherwiseroot_spandoes nothing. - Widen the time range, in case the conversation ran earlier.
Turns of one conversation show up as separate sessions
- Check that you pass exactly the same
conversation_idon every turn.

Have a suggestion?