Instrumentation API¶
Auto-instrumentation for popular LLM SDKs and frameworks.
Base Instrumentor¶
prela.instrumentation.base.Instrumentor
¶
Bases: ABC
Abstract base class for library instrumentors.
Instrumentors provide automatic tracing for external libraries by monkey-patching their functions to create spans around operations.
Example
class OpenAIInstrumentor(Instrumentor):
def instrument(self, tracer: Tracer) -> None:
# Wrap OpenAI API calls
wrap_function(openai, "create", wrapper)
def uninstrument(self) -> None:
# Restore original functions
unwrap_function(openai, "create")
@property
def is_instrumented(self) -> bool:
return hasattr(openai, _ORIGINALS_ATTR)
Attributes¶
is_instrumented
abstractmethod
property
¶
Check if this library is currently instrumented.
Returns:
| Type | Description |
|---|---|
bool
|
True if instrumentation is active, False otherwise |
Functions¶
instrument(tracer)
abstractmethod
¶
Enable instrumentation for this library.
This method should wrap the library's functions to create spans automatically. It should be idempotent - calling it multiple times should not create multiple layers of wrapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tracer
|
Tracer
|
The tracer to use for creating spans |
required |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If instrumentation fails |
uninstrument()
abstractmethod
¶
Disable instrumentation and restore original functions.
This method should unwrap all previously wrapped functions and restore the library to its original state. It should be idempotent - calling it when not instrumented should be a no-op.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If uninstrumentation fails |
Auto-Instrumentation¶
prela.instrumentation.auto.auto_instrument(tracer)
¶
Automatically instrument all detected libraries.
This function: 1. Checks which supported LLM SDKs are installed 2. Imports and initializes their instrumentors 3. Calls instrument(tracer) on each 4. Returns list of successfully instrumented libraries
The function is designed to be safe: - Missing libraries are skipped (not an error) - Instrumentation failures are logged but don't crash - Returns empty list if nothing was instrumented
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tracer
|
Tracer
|
The tracer instance to use for instrumentation |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
List of library names that were successfully instrumented |
list[str]
|
(e.g., ["anthropic", "openai"]) |
Example
from prela.core.tracer import Tracer
from prela.instrumentation.auto import auto_instrument
tracer = Tracer(service_name="my-app")
instrumented = auto_instrument(tracer)
print(f"Auto-instrumented: {instrumented}")
# Output: Auto-instrumented: ['anthropic', 'openai']
# Now all calls to these SDKs are automatically traced
from anthropic import Anthropic
client = Anthropic()
response = client.messages.create(...) # Automatically traced!
OpenAI Instrumentor¶
prela.instrumentation.openai.OpenAIInstrumentor
¶
Bases: Instrumentor
Instrumentor for OpenAI SDK.
Patches the following methods: - openai.OpenAI.chat.completions.create (sync) - openai.AsyncOpenAI.chat.completions.create (async) - openai.OpenAI.completions.create (sync, legacy) - openai.OpenAI.embeddings.create (sync)
Captures detailed information about requests, responses, tool usage, and streaming events.
Attributes¶
is_instrumented
property
¶
Check if OpenAI SDK is currently instrumented.
Functions¶
__init__()
¶
Initialize the OpenAI instrumentor.
instrument(tracer)
¶
Enable instrumentation for OpenAI SDK.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tracer
|
Tracer
|
The tracer to use for creating spans |
required |
Raises:
| Type | Description |
|---|---|
ImportError
|
If openai package is not installed |
RuntimeError
|
If instrumentation fails |
uninstrument()
¶
Disable instrumentation and restore original functions.
Anthropic Instrumentor¶
prela.instrumentation.anthropic.AnthropicInstrumentor
¶
Bases: Instrumentor
Instrumentor for Anthropic SDK.
Patches the following methods: - anthropic.Anthropic.messages.create (sync) - anthropic.AsyncAnthropic.messages.create (async) - anthropic.Anthropic.messages.stream (sync) - anthropic.AsyncAnthropic.messages.stream (async)
Captures detailed information about requests, responses, tool usage, and streaming events.
Attributes¶
is_instrumented
property
¶
Check if Anthropic SDK is currently instrumented.
Functions¶
__init__()
¶
Initialize the Anthropic instrumentor.
instrument(tracer)
¶
Enable instrumentation for Anthropic SDK.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tracer
|
Tracer
|
The tracer to use for creating spans |
required |
Raises:
| Type | Description |
|---|---|
ImportError
|
If anthropic package is not installed |
RuntimeError
|
If instrumentation fails |
uninstrument()
¶
Disable instrumentation and restore original functions.
LangChain Instrumentor¶
prela.instrumentation.langchain.LangChainInstrumentor
¶
Bases: Instrumentor
Instrumentor for LangChain framework.
This instrumentor injects a PrelaCallbackHandler into LangChain's global callback system, which automatically traces all LangChain operations including LLM calls, chains, tools, retrievers, and agent actions.
Unlike other instrumentors that use function wrapping, this uses LangChain's built-in callback mechanism for more robust and comprehensive tracing.
Attributes¶
is_instrumented
property
¶
Check if LangChain is currently instrumented.
Returns:
| Type | Description |
|---|---|
bool
|
True if instrumentation is active, False otherwise |
Functions¶
__init__()
¶
Initialize the LangChain instrumentor.
instrument(tracer)
¶
Enable instrumentation for LangChain.
This adds a PrelaCallbackHandler to LangChain's global callback manager, which will receive events for all LangChain operations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tracer
|
Tracer
|
The tracer to use for creating spans |
required |
Raises:
| Type | Description |
|---|---|
ImportError
|
If langchain-core package is not installed |
RuntimeError
|
If instrumentation fails |
uninstrument()
¶
Disable instrumentation and remove callback handler.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If uninstrumentation fails |
PrelaCallbackHandler¶
prela.instrumentation.langchain.PrelaCallbackHandler
¶
LangChain callback handler that creates Prela spans.
This handler implements LangChain's BaseCallbackHandler interface and creates spans for all major LangChain operations. It maintains a mapping from run_id to span to properly handle concurrent executions and nested operations.
The handler tracks: - LLM calls: Model invocations with prompts and responses - Chains: Sequential operations and workflows - Tools: External tool invocations - Retrievers: Document retrieval operations - Agents: Agent reasoning and actions
Functions¶
__init__(tracer)
¶
Initialize the callback handler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tracer
|
Tracer
|
The tracer to use for creating spans |
required |
on_llm_start(serialized, prompts, *, run_id, parent_run_id=None, tags=None, metadata=None, **kwargs)
¶
Called when an LLM starts running.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serialized
|
dict[str, Any]
|
Serialized LLM configuration |
required |
prompts
|
list[str]
|
Input prompts to the LLM |
required |
run_id
|
UUID
|
Unique identifier for this LLM run |
required |
parent_run_id
|
UUID | None
|
ID of parent operation (if nested) |
None
|
tags
|
list[str] | None
|
Optional tags for categorization |
None
|
metadata
|
dict[str, Any] | None
|
Optional metadata |
None
|
**kwargs
|
Any
|
Additional LLM parameters |
{}
|
on_llm_end(response, *, run_id, parent_run_id=None, **kwargs)
¶
Called when an LLM finishes running.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Any
|
LLM response object |
required |
run_id
|
UUID
|
Unique identifier for this LLM run |
required |
parent_run_id
|
UUID | None
|
ID of parent operation |
None
|
**kwargs
|
Any
|
Additional parameters |
{}
|
on_llm_error(error, *, run_id, parent_run_id=None, **kwargs)
¶
Called when an LLM errors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
error
|
BaseException
|
The error that occurred |
required |
run_id
|
UUID
|
Unique identifier for this LLM run |
required |
parent_run_id
|
UUID | None
|
ID of parent operation |
None
|
**kwargs
|
Any
|
Additional parameters |
{}
|
on_chain_start(serialized, inputs, *, run_id, parent_run_id=None, tags=None, metadata=None, **kwargs)
¶
Called when a chain starts running.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serialized
|
dict[str, Any]
|
Serialized chain configuration |
required |
inputs
|
dict[str, Any]
|
Input values to the chain |
required |
run_id
|
UUID
|
Unique identifier for this chain run |
required |
parent_run_id
|
UUID | None
|
ID of parent operation |
None
|
tags
|
list[str] | None
|
Optional tags |
None
|
metadata
|
dict[str, Any] | None
|
Optional metadata |
None
|
**kwargs
|
Any
|
Additional parameters |
{}
|
on_chain_end(outputs, *, run_id, parent_run_id=None, **kwargs)
¶
Called when a chain finishes running.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
outputs
|
dict[str, Any]
|
Output values from the chain |
required |
run_id
|
UUID
|
Unique identifier for this chain run |
required |
parent_run_id
|
UUID | None
|
ID of parent operation |
None
|
**kwargs
|
Any
|
Additional parameters |
{}
|
on_chain_error(error, *, run_id, parent_run_id=None, **kwargs)
¶
Called when a chain errors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
error
|
BaseException
|
The error that occurred |
required |
run_id
|
UUID
|
Unique identifier for this chain run |
required |
parent_run_id
|
UUID | None
|
ID of parent operation |
None
|
**kwargs
|
Any
|
Additional parameters |
{}
|
on_tool_start(serialized, input_str, *, run_id, parent_run_id=None, tags=None, metadata=None, **kwargs)
¶
Called when a tool starts running.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serialized
|
dict[str, Any]
|
Serialized tool configuration |
required |
input_str
|
str
|
Input string to the tool |
required |
run_id
|
UUID
|
Unique identifier for this tool run |
required |
parent_run_id
|
UUID | None
|
ID of parent operation |
None
|
tags
|
list[str] | None
|
Optional tags |
None
|
metadata
|
dict[str, Any] | None
|
Optional metadata |
None
|
**kwargs
|
Any
|
Additional parameters |
{}
|
on_tool_end(output, *, run_id, parent_run_id=None, **kwargs)
¶
Called when a tool finishes running.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output
|
str
|
Output from the tool |
required |
run_id
|
UUID
|
Unique identifier for this tool run |
required |
parent_run_id
|
UUID | None
|
ID of parent operation |
None
|
**kwargs
|
Any
|
Additional parameters |
{}
|
on_tool_error(error, *, run_id, parent_run_id=None, **kwargs)
¶
Called when a tool errors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
error
|
BaseException
|
The error that occurred |
required |
run_id
|
UUID
|
Unique identifier for this tool run |
required |
parent_run_id
|
UUID | None
|
ID of parent operation |
None
|
**kwargs
|
Any
|
Additional parameters |
{}
|
on_retriever_start(serialized, query, *, run_id, parent_run_id=None, tags=None, metadata=None, **kwargs)
¶
Called when a retriever starts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serialized
|
dict[str, Any]
|
Serialized retriever configuration |
required |
query
|
str
|
Query string for retrieval |
required |
run_id
|
UUID
|
Unique identifier for this retriever run |
required |
parent_run_id
|
UUID | None
|
ID of parent operation |
None
|
tags
|
list[str] | None
|
Optional tags |
None
|
metadata
|
dict[str, Any] | None
|
Optional metadata |
None
|
**kwargs
|
Any
|
Additional parameters |
{}
|
on_retriever_end(documents, *, run_id, parent_run_id=None, **kwargs)
¶
Called when a retriever finishes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
documents
|
list[Any]
|
Retrieved documents |
required |
run_id
|
UUID
|
Unique identifier for this retriever run |
required |
parent_run_id
|
UUID | None
|
ID of parent operation |
None
|
**kwargs
|
Any
|
Additional parameters |
{}
|
LlamaIndex Instrumentor¶
prela.instrumentation.llamaindex.LlamaIndexInstrumentor
¶
Bases: Instrumentor
Instrumentor for LlamaIndex framework.
This instrumentor adds automatic tracing to LlamaIndex operations by injecting a callback handler into the global callback manager.
Example
Attributes¶
is_instrumented
property
¶
Check if LlamaIndex is currently instrumented.
Returns:
| Type | Description |
|---|---|
bool
|
True if instrumented, False otherwise |
Functions¶
__init__()
¶
Initialize the instrumentor.
instrument(tracer)
¶
Enable instrumentation for LlamaIndex.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tracer
|
Tracer
|
The tracer to use for creating spans |
required |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If llama-index-core is not installed |
uninstrument()
¶
Disable instrumentation and remove callback handler.
PrelaHandler¶
prela.instrumentation.llamaindex.PrelaHandler
¶
LlamaIndex callback handler that creates Prela spans.
This handler implements LlamaIndex's BaseCallbackHandler interface and creates spans for all major LlamaIndex operations. It maintains a mapping from event_id to span to properly handle concurrent executions and nested operations.
The handler tracks: - LLM calls: Model invocations with prompts and responses - Embeddings: Vector generation operations - Retrieval: Document retrieval with similarity scores - Query: Query engine operations - Synthesis: Response synthesis from retrieved documents
Functions¶
__init__(tracer)
¶
Initialize the callback handler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tracer
|
Tracer
|
The tracer to use for creating spans |
required |
on_event_start(event_type, payload=None, event_id='', parent_id='', **kwargs)
¶
Called when an event starts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
str
|
Type of event (LLM, EMBEDDING, RETRIEVE, etc.) |
required |
payload
|
Optional[dict[str, Any]]
|
Event-specific data |
None
|
event_id
|
str
|
Unique identifier for this event |
''
|
parent_id
|
str
|
ID of parent event (if nested) |
''
|
**kwargs
|
Any
|
Additional arguments |
{}
|
Returns:
| Type | Description |
|---|---|
str
|
The event_id for tracking |
on_event_end(event_type, payload=None, event_id='', **kwargs)
¶
Called when an event ends.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
str
|
Type of event (LLM, EMBEDDING, RETRIEVE, etc.) |
required |
payload
|
Optional[dict[str, Any]]
|
Event-specific response data |
None
|
event_id
|
str
|
Unique identifier for this event |
''
|
**kwargs
|
Any
|
Additional arguments |
{}
|
N8N Webhook Handler¶
prela.instrumentation.n8n.webhook.N8nWebhookHandler
¶
HTTP server for receiving n8n webhook traces locally.
This handler runs a lightweight HTTP server that receives webhook POST requests from n8n workflows and automatically converts them into Prela spans.
Example
from prela import init
from prela.instrumentation.n8n.webhook import N8nWebhookHandler
tracer = init(service_name="n8n-workflows")
handler = N8nWebhookHandler(tracer, port=8787)
handler.start()
# Configure n8n webhook node to POST to http://localhost:8787/webhook
# Handler will automatically trace all workflow executions
Functions¶
__init__(tracer, port=8787, host='0.0.0.0')
¶
Initialize the webhook handler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tracer
|
Tracer
|
Prela tracer instance for creating spans |
required |
port
|
int
|
Port to listen on (default: 8787) |
8787
|
host
|
str
|
Host to bind to (default: 0.0.0.0) |
'0.0.0.0'
|
start()
¶
Start the HTTP server.
This method starts an aiohttp server on the configured host and port. It runs in the current event loop, so it should be called from an async context or run in a separate thread.
start_background()
¶
Start the HTTP server in a background thread.
This method creates a new event loop and runs the server in it. Designed to be called from a background thread via threading.Thread.
stop()
¶
Stop the HTTP server.
N8N Code Node Context¶
prela.instrumentation.n8n.code_node.PrelaN8nContext
¶
Context manager for tracing custom Python code within n8n Code nodes.
This class creates a workflow-level span and node-level span that properly integrate with Prela's tracing infrastructure. It provides helper methods for logging LLM calls, tool calls, and retrieval operations.
Example
# Inside n8n Code node
from prela.instrumentation.n8n import PrelaN8nContext
ctx = PrelaN8nContext(
workflow_id=$workflow.id,
workflow_name=$workflow.name,
execution_id=$execution.id,
node_name=$node.name
)
with ctx:
# Your custom code
response = call_my_llm(prompt)
ctx.log_llm_call(
model="gpt-4",
prompt=prompt,
response=response,
tokens={"prompt": 100, "completion": 50}
)
return [{"json": {"result": response}}]
Functions¶
__init__(workflow_id, workflow_name, execution_id, node_name, node_type='n8n-nodes-base.code', tracer=None, api_key=None, endpoint=None)
¶
Initialize n8n Code node tracing context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
workflow_id
|
str
|
Unique workflow identifier |
required |
workflow_name
|
str
|
Human-readable workflow name |
required |
execution_id
|
str
|
Unique execution identifier |
required |
node_name
|
str
|
Name of the Code node |
required |
node_type
|
str
|
Node type identifier (default: n8n-nodes-base.code) |
'n8n-nodes-base.code'
|
tracer
|
Optional[Tracer]
|
Prela tracer instance (defaults to global tracer) |
None
|
api_key
|
Optional[str]
|
Optional API key for remote export |
None
|
endpoint
|
Optional[str]
|
Optional endpoint URL for remote export |
None
|
__enter__()
¶
Start tracing context.
__exit__(exc_type, exc_val, exc_tb)
¶
End tracing context and export spans.
log_llm_call(model, prompt, response, tokens=None, provider=None, temperature=None, **kwargs)
¶
Log an LLM call within the Code node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
str
|
Model identifier (e.g., "gpt-4", "claude-3-opus") |
required |
prompt
|
str
|
Input prompt text |
required |
response
|
str
|
Model response text |
required |
tokens
|
Optional[dict]
|
Token usage dict with "prompt", "completion", "total" keys |
None
|
provider
|
Optional[str]
|
AI provider (openai, anthropic, etc.) |
None
|
temperature
|
Optional[float]
|
Temperature parameter used |
None
|
**kwargs
|
Additional attributes to attach to the span |
{}
|
log_tool_call(tool_name, input, output, error=None, **kwargs)
¶
Log a tool call within the Code node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tool_name
|
str
|
Name of the tool/function called |
required |
input
|
Any
|
Input parameters to the tool |
required |
output
|
Any
|
Output result from the tool |
required |
error
|
Optional[str]
|
Optional error message if tool failed |
None
|
**kwargs
|
Additional attributes to attach to the span |
{}
|
log_retrieval(query, documents, retriever_type=None, similarity_top_k=None, **kwargs)
¶
Log a retrieval/search operation within the Code node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
str
|
Search query text |
required |
documents
|
list[dict]
|
Retrieved documents (list of dicts with text/score/metadata) |
required |
retriever_type
|
Optional[str]
|
Type of retriever used (vector, keyword, hybrid) |
None
|
similarity_top_k
|
Optional[int]
|
Number of documents requested |
None
|
**kwargs
|
Additional attributes to attach to the span |
{}
|
N8N Models¶
N8nWorkflowExecution¶
prela.instrumentation.n8n.models.N8nWorkflowExecution
¶
Bases: BaseModel
Represents a complete n8n workflow execution.
Captures high-level metadata about a workflow run, including timing, status, node counts, and aggregate token/cost metrics.
Functions¶
validate_non_negative(v)
classmethod
¶
Ensure counts are non-negative.
validate_cost(v)
classmethod
¶
Ensure cost is non-negative.
validate_completed_at(v, info)
classmethod
¶
Ensure completed_at is after started_at if both exist.
duration_ms()
¶
Calculate execution duration in milliseconds.
to_span_attributes()
¶
Convert to Prela span attributes.
N8nNodeExecution¶
prela.instrumentation.n8n.models.N8nNodeExecution
¶
Bases: BaseModel
Represents execution of a single node within a workflow.
Captures node-level telemetry including input/output data, timing, status, and error information.
Functions¶
validate_non_negative(v)
classmethod
¶
Ensure counts are non-negative.
validate_completed_at(v, info)
classmethod
¶
Ensure completed_at is after started_at if both exist.
duration_ms()
¶
Calculate node execution duration in milliseconds.
to_span_attributes()
¶
Convert to Prela span attributes.
N8nAINodeExecution¶
prela.instrumentation.n8n.models.N8nAINodeExecution
¶
Bases: N8nNodeExecution
Represents execution of an AI-specific node (LLM, agent, vector store, etc.).
Extends N8nNodeExecution with AI-specific telemetry including model info, token usage, costs, prompts, and retrieval data.
Functions¶
validate_non_negative_tokens(v)
classmethod
¶
Ensure token counts are non-negative.
validate_cost(v)
classmethod
¶
Ensure cost is non-negative.
validate_temperature(v)
classmethod
¶
Ensure temperature is in valid range.
to_span_attributes()
¶
Convert to Prela span attributes with AI-specific fields.
infer_span_type()
¶
Infer the appropriate span type based on node characteristics.
Returns:
| Type | Description |
|---|---|
N8nSpanType
|
N8nSpanType appropriate for this node's function |