Set up Tracing

There are several ways to log traces to Arize.

1. Use Tracing Integrations (Auto-Instrumentation)

Arize makes it easy to log traces with minimal changes by using our tracing integrations. These can then be further customized.

2. Manual Instrumentation

In some cases, you might want full control over what is being traced in your application. Arize supports OpenTelemetry (OTEL) which means that you can create and customize your spans using the OpenTelemetry Trace API.

Step 1: Install Prerequisities

pip install opentelemetry-api
pip install opentelemetry-sdk
pip install openinference-semantic-conventions

Step 2: Configuring a Tracer

Manually configuring an OTEL tracer involves some boilerplate code that Arize takes care of for you. We recommend using the register_otel helper method below to configure a tracer.

If you need more control over your tracer's configuration, see the Manually Configuring an OTEL Tracer section below.

import openai
import opentelemetry
import pandas as pd
from openai import OpenAI
from openinference.instrumentation.openai import OpenAIInstrumentor

# Import open-telemetry dependencies
from arize_otel import register_otel, Endpoints

# Setup OTEL via our convenience function.
register_otel(
    endpoints = Endpoints.ARIZE,
    space_id = "your-space-id", # in app space settings page
    api_key = "your-api-key", # in app space settings page
    model_id = "your-model-id", # name this to whatever you would like
)

Step 3: Creating Spans

If you're using a Tracing Integration, these will take care of automatically creating the spans for your application. You can then further customize those spans - for more information check out setting up hybrid instrumentation.

# Because we are using Open AI, we will use this along with our custom instrumentation
OpenAIInstrumentor().instrument()

If you want fully customize the spans, you can do that using manual instrumentation. You'll typically want it to be started as the current span.

def do_work():
    with tracer.start_as_current_span("span-name") as span:
        # do some work that 'span' will track
        print("doing some work...")
        # When the 'with' block goes out of scope, 'span' is closed for you

You can also use start_span to create a span without making it the current span. This is usually done to track concurrent or asynchronous operations.

Creating nested spans

If you have a distinct sub-operation you'd like to track as a part of another one, you can create span to represent the relationship:\

def do_work():
    with tracer.start_as_current_span("parent") as parent:
        # do some work that 'parent' tracks
        print("doing some work...")
        # Create a nested span to track nested work
        with tracer.start_as_current_span("child") as child:
            # do some work that 'child' tracks
            print("doing some nested work...")
            # the nested span is closed when it's out of scope

        # This span is also closed when it goes out of scope

When you view spans in a trace visualization tool, child will be tracked as a nested span under parent.

Creating spans with a decorator

It's common to have a single span track the execution of an entire function. In that scenario, there is a decorator you can use to reduce code:

@tracer.start_as_current_span("do_work")
def do_work():
    print("doing some work...")

Use of the decorator is equivalent to creating the span inside do_work() and ending it when do_work() is finished.

To use the decorator, you must have a tracer instance in scope for your function declaration.

If you need to add attributes or events then it's less convenient to use a decorator.

Last updated

Copyright © 2023 Arize AI, Inc