Understanding Traces
Learn how traces work in Brokle and how they help you monitor your AI applications
Understanding Traces
A trace represents a single end-to-end request through your AI application. It captures the complete journey from user input to final response, including all LLM calls, retrievals, tool uses, and custom operations along the way.
What is a Trace?
Think of a trace as a detailed story of what happened during one interaction with your AI system. When a user asks a question, your application might:
- Retrieve relevant documents from a vector database
- Call an LLM to generate a response
- Use a tool to verify information
- Call the LLM again to refine the answer
A trace captures all of these steps, their relationships, timing, inputs, outputs, and any errors that occurred.
Trace Anatomy
Every trace consists of spans - individual operations that make up the complete request:
Trace: "answer_question"
├── Span: retrieve_documents (Retrieval)
│ ├── duration: 120ms
│ ├── input: "What is quantum computing?"
│ └── output: [3 documents retrieved]
├── Span: generate_response (LLM)
│ ├── duration: 1,200ms
│ ├── model: gpt-4
│ ├── tokens: 1,523
│ └── cost: $0.0456
└── Span: format_output (Generation)
├── duration: 5ms
└── output: "Quantum computing is..."Key Trace Properties
| Property | Description | Example |
|---|---|---|
trace_id | Unique identifier for this trace | trace_abc123xyz |
name | Human-readable name | "chat_completion" |
project_id | Project this trace belongs to | proj_456def |
start_time | When the trace began | 2025-01-15T12:00:00Z |
end_time | When the trace completed | 2025-01-15T12:00:02Z |
duration_ms | Total trace duration | 2,345 |
status | Success, error, or in-progress | "success" |
total_tokens | Sum of all token usage | 2,847 |
total_cost | Sum of all costs | $0.0892 |
metadata | Custom key-value pairs | {"user_id": "u_123"} |
Creating Traces
Using the Python SDK
from brokle import Brokle
client = Brokle(api_key="your-api-key")
# Using a context manager (recommended)
with client.trace("my-operation") as trace:
# All operations inside are automatically captured
response = openai.chat.completions.create(...)
# Add custom metadata
trace.set_metadata({
"user_id": "user_123",
"session_id": "session_456"
})Using the JavaScript SDK
import { Brokle } from '@brokle/sdk';
const client = new Brokle({ apiKey: 'your-api-key' });
// Using an async callback
await client.trace('my-operation', async (trace) => {
// All operations inside are automatically captured
const response = await openai.chat.completions.create(...);
// Add custom metadata
trace.setMetadata({
userId: 'user_123',
sessionId: 'session_456'
});
});Using Decorators (Python)
from brokle import Brokle, trace
client = Brokle(api_key="your-api-key")
@trace(name="process_query")
def process_query(query: str) -> str:
# This function is automatically traced
response = openai.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": query}]
)
return response.choices[0].message.contentTrace Hierarchy
Traces naturally form a tree structure. The root span represents the entire operation, while child spans represent individual steps:
Child spans inherit context from their parent, making it easy to track the complete flow of a request across multiple operations.
Viewing Traces
Once traces are captured, you can view them in the Brokle dashboard:
- Navigate to Traces in the sidebar
- Filter by project, time range, or status
- Click on any trace to see the full span tree
- Drill into individual spans to see inputs, outputs, and timing
Trace List View
The trace list shows all traces with key metrics at a glance:
- Duration
- Token usage
- Cost
- Status
- Timestamp
Trace Detail View
Click on a trace to see:
- Complete span tree with timing
- Input/output for each span
- Token counts and costs
- Error details if any occurred
- Custom metadata
Best Practices
1. Use Meaningful Names
# Good - descriptive name
with client.trace("answer_customer_question") as trace:
...
# Bad - generic name
with client.trace("operation") as trace:
...2. Add Relevant Metadata
with client.trace("chat") as trace:
trace.set_metadata({
"user_id": user.id,
"session_id": session.id,
"feature": "customer_support"
})3. Handle Errors Properly
with client.trace("risky_operation") as trace:
try:
result = process()
except Exception as e:
trace.set_error(str(e))
raiseRelated Concepts
- Spans - Individual operations within a trace
- Sessions - Group related traces together
- Distributed Tracing - Trace across services