mirror of
https://github.com/github/awesome-copilot.git
synced 2026-04-12 03:05:55 +00:00
183 lines
4.9 KiB
Markdown
183 lines
4.9 KiB
Markdown
# Manual Instrumentation (Python)
|
|
|
|
Add custom spans using decorators or context managers for fine-grained tracing control.
|
|
|
|
## Setup
|
|
|
|
```bash
|
|
pip install arize-phoenix-otel
|
|
```
|
|
|
|
```python
|
|
from phoenix.otel import register
|
|
tracer_provider = register(project_name="my-app")
|
|
tracer = tracer_provider.get_tracer(__name__)
|
|
```
|
|
|
|
## Quick Reference
|
|
|
|
| Span Kind | Decorator | Use Case |
|
|
|-----------|-----------|----------|
|
|
| CHAIN | `@tracer.chain` | Orchestration, workflows, pipelines |
|
|
| RETRIEVER | `@tracer.retriever` | Vector search, document retrieval |
|
|
| TOOL | `@tracer.tool` | External API calls, function execution |
|
|
| AGENT | `@tracer.agent` | Multi-step reasoning, planning |
|
|
| LLM | `@tracer.llm` | LLM API calls (manual only) |
|
|
| EMBEDDING | `@tracer.embedding` | Embedding generation |
|
|
| RERANKER | `@tracer.reranker` | Document re-ranking |
|
|
| GUARDRAIL | `@tracer.guardrail` | Safety checks, content moderation |
|
|
| EVALUATOR | `@tracer.evaluator` | LLM evaluation, quality checks |
|
|
|
|
## Decorator Approach (Recommended)
|
|
|
|
**Use for:** Full function instrumentation, automatic I/O capture
|
|
|
|
```python
|
|
@tracer.chain
|
|
def rag_pipeline(query: str) -> str:
|
|
docs = retrieve_documents(query)
|
|
ranked = rerank(docs, query)
|
|
return generate_response(ranked, query)
|
|
|
|
@tracer.retriever
|
|
def retrieve_documents(query: str) -> list[dict]:
|
|
results = vector_db.search(query, top_k=5)
|
|
return [{"content": doc.text, "score": doc.score} for doc in results]
|
|
|
|
@tracer.tool
|
|
def get_weather(city: str) -> str:
|
|
response = requests.get(f"https://api.weather.com/{city}")
|
|
return response.json()["weather"]
|
|
```
|
|
|
|
**Custom span names:**
|
|
|
|
```python
|
|
@tracer.chain(name="rag-pipeline-v2")
|
|
def my_workflow(query: str) -> str:
|
|
return process(query)
|
|
```
|
|
|
|
## Context Manager Approach
|
|
|
|
**Use for:** Partial function instrumentation, custom attributes, dynamic control
|
|
|
|
```python
|
|
from opentelemetry.trace import Status, StatusCode
|
|
import json
|
|
|
|
def retrieve_with_metadata(query: str):
|
|
with tracer.start_as_current_span(
|
|
"vector_search",
|
|
openinference_span_kind="retriever"
|
|
) as span:
|
|
span.set_attribute("input.value", query)
|
|
|
|
results = vector_db.search(query, top_k=5)
|
|
|
|
documents = [
|
|
{
|
|
"document.id": doc.id,
|
|
"document.content": doc.text,
|
|
"document.score": doc.score
|
|
}
|
|
for doc in results
|
|
]
|
|
span.set_attribute("retrieval.documents", json.dumps(documents))
|
|
span.set_status(Status(StatusCode.OK))
|
|
|
|
return documents
|
|
```
|
|
|
|
## Capturing Input/Output
|
|
|
|
**Always capture I/O for evaluation-ready spans.**
|
|
|
|
### Automatic I/O Capture (Decorators)
|
|
|
|
Decorators automatically capture input arguments and return values:
|
|
|
|
```python theme={null}
|
|
@tracer.chain
|
|
def handle_query(user_input: str) -> str:
|
|
result = agent.generate(user_input)
|
|
return result.text
|
|
|
|
# Automatically captures:
|
|
# - input.value: user_input
|
|
# - output.value: result.text
|
|
# - input.mime_type / output.mime_type: auto-detected
|
|
```
|
|
|
|
### Manual I/O Capture (Context Manager)
|
|
|
|
Use `set_input()` and `set_output()` for simple I/O capture:
|
|
|
|
```python theme={null}
|
|
from opentelemetry.trace import Status, StatusCode
|
|
|
|
def handle_query(user_input: str) -> str:
|
|
with tracer.start_as_current_span(
|
|
"query.handler",
|
|
openinference_span_kind="chain"
|
|
) as span:
|
|
span.set_input(user_input)
|
|
|
|
result = agent.generate(user_input)
|
|
|
|
span.set_output(result.text)
|
|
span.set_status(Status(StatusCode.OK))
|
|
|
|
return result.text
|
|
```
|
|
|
|
**What gets captured:**
|
|
|
|
```json
|
|
{
|
|
"input.value": "What is 2+2?",
|
|
"input.mime_type": "text/plain",
|
|
"output.value": "2+2 equals 4.",
|
|
"output.mime_type": "text/plain"
|
|
}
|
|
```
|
|
|
|
**Why this matters:**
|
|
- Phoenix evaluators require `input.value` and `output.value`
|
|
- Phoenix UI displays I/O prominently for debugging
|
|
- Enables exporting data for fine-tuning datasets
|
|
|
|
### Custom I/O with Additional Metadata
|
|
|
|
Use `set_attribute()` for custom attributes alongside I/O:
|
|
|
|
```python theme={null}
|
|
def process_query(query: str):
|
|
with tracer.start_as_current_span(
|
|
"query.process",
|
|
openinference_span_kind="chain"
|
|
) as span:
|
|
# Standard I/O
|
|
span.set_input(query)
|
|
|
|
# Custom metadata
|
|
span.set_attribute("input.length", len(query))
|
|
|
|
result = llm.generate(query)
|
|
|
|
# Standard output
|
|
span.set_output(result.text)
|
|
|
|
# Custom metadata
|
|
span.set_attribute("output.tokens", result.usage.total_tokens)
|
|
span.set_status(Status(StatusCode.OK))
|
|
|
|
return result
|
|
```
|
|
|
|
## See Also
|
|
|
|
- **Span attributes:** `span-chain.md`, `span-retriever.md`, `span-tool.md`, `span-llm.md`, `span-agent.md`, `span-embedding.md`, `span-reranker.md`, `span-guardrail.md`, `span-evaluator.md`
|
|
- **Auto-instrumentation:** `instrumentation-auto-python.md` for framework integrations
|
|
- **API docs:** https://docs.arize.com/phoenix/tracing/manual-instrumentation
|