Skip to content

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
from prela.instrumentation.llamaindex import LlamaIndexInstrumentor
from prela.core.tracer import Tracer

tracer = Tracer()
instrumentor = LlamaIndexInstrumentor()
instrumentor.instrument(tracer)

# All LlamaIndex operations now traced

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