In some situations, you may need to modify the observability level of your tracing. For instance, you may want to keep sensitive information from being logged for security reasons, or you may want to limit the size of the base64 encoded images logged to reduced payload size.
The OpenInference Specification defines a set of environment variables you can configure to suit your observability needs. In addition, the OpenInference auto-instrumentors accept a trace config which allows you to set these value in code without having to set environment variables, if that's what you prefer
The possible settings are:
OPENINFERENCE_HIDE_INPUTS
Hides input value, all input messages & embedding input text
bool
False
OPENINFERENCE_HIDE_OUTPUTS
Hides output value & all output messages
bool
False
OPENINFERENCE_HIDE_INPUT_MESSAGES
Hides all input messages & embedding input text
bool
False
OPENINFERENCE_HIDE_OUTPUT_MESSAGES
Hides all output messages
bool
False
PENINFERENCE_HIDE_INPUT_IMAGES
Hides images from input messages
bool
False
OPENINFERENCE_HIDE_INPUT_TEXT
Hides text from input messages & input embeddings
bool
False
OPENINFERENCE_HIDE_OUTPUT_TEXT
Hides text from output messages
bool
False
OPENINFERENCE_HIDE_EMBEDDING_VECTORS
Hides returned embedding vectors
bool
False
OPENINFERENCE_HIDE_LLM_INVOCATION_PARAMETERS
Hides LLM invocation parameters
bool
False
OPENINFERENCE_BASE64_IMAGE_MAX_LENGTH
Limits characters of a base64 encoding of an image
int
32,000
To set up this configuration you can either:
Set environment variables as specified above
Define the configuration in code as shown below
Do nothing and fall back to the default values
Use a combination of the three, the order of precedence is:
Values set in the TraceConfig
in code
Environment variables
default values
Below is an example of how to set these values in code using our OpenAI Python and JavaScript instrumentors, however, the config is respected by all of our auto-instrumentors.
from openinference.instrumentation import TraceConfig
config = TraceConfig(
hide_inputs=...,
hide_outputs=...,
hide_input_messages=...,
hide_output_messages=...,
hide_input_images=...,
hide_input_text=...,
hide_output_text=...,
hide_embedding_vectors=...,
hide_llm_invocation_parameters=...,
base64_image_max_length=...,
)
from openinference.instrumentation.openai import OpenAIInstrumentor
OpenAIInstrumentor().instrument(
tracer_provider=tracer_provider,
config=config,
)
/**
* Everything left out of here will fallback to
* environment variables then defaults
*/
const traceConfig = { hideInputs: true }
const instrumentation = new OpenAIInstrumentation({ traceConfig })
Learn how to block PII from logging to Phoenix
Learn how to selectively block or turn off tracing
Learn how to send only certain spans to Phoenix
Learn how to trace images
Sometimes while instrumenting your application, you may want to filter out or modify certain spans from being sent to Phoenix. For example, you may want to filter out spans that are that contain sensitive information or contain redundant information.
To do this, you can use a custom SpanProcessor
and attach it to the OpenTelemetry TracerProvider
.
In this example, we're filtering out any spans that have the name "secret_span" by bypassing the on_start
and on_end
hooks of the inherited BatchSpanProcessor
.
Notice that this logic can be extended to modify a span and redact sensitive information if preserving the span is preferred.
Tracing can be paused temporarily or disabled permanently.
If there is a section of your code for which tracing is not desired, e.g. the document chunking process, it can be put inside the suppress_tracing
context manager as shown below.
Calling .uninstrument()
on the auto-instrumentors will remove tracing permanently. Below is the examples for LangChain, LlamaIndex and OpenAI, respectively.
from phoenix.trace import suppress_tracing
with suppress_tracing():
# Code running inside this block doesn't generate traces.
# For example, running LLM evals here won't generate additional traces.
...
# Tracing will resume outside the block.
...
LangChainInstrumentor().uninstrument()
LlamaIndexInstrumentor().uninstrument()
OpenAIInstrumentor().uninstrument()
# etc.
Phoenix supports displaying images that are included in LLM traces.
Instrument your application
Include either a base64 UTF-8 encoded image or an image url in the call made to your LLM
pip install -q "arize-phoenix>=4.29.0" openinference-instrumentation-openai openai
# Check if PHOENIX_API_KEY is present in the environment variables.
# If it is, we'll use the cloud instance of Phoenix. If it's not, we'll start a local instance.
# A third option is to connect to a docker or locally hosted instance.
# See https://arize.com/docs/phoenix/setup/environments for more information.
# Launch Phoenix
import os
if "PHOENIX_API_KEY" in os.environ:
os.environ["PHOENIX_CLIENT_HEADERS"] = f"api_key={os.environ['PHOENIX_API_KEY']}"
os.environ["PHOENIX_COLLECTOR_ENDPOINT"] = "https://app.phoenix.arize.com"
else:
import phoenix as px
px.launch_app().view()
# Connect to Phoenix
from phoenix.otel import register
tracer_provider = register()
# Instrument OpenAI calls in your application
from openinference.instrumentation.openai import OpenAIInstrumentor
OpenAIInstrumentor().instrument(tracer_provider=tracer_provider, skip_dep_check=True)
# Make a call to OpenAI with an image provided
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "What’s in this image?"},
{
"type": "image_url",
"image_url": {
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg",
},
},
],
}
],
max_tokens=300,
)
You should see your image appear in Phoenix:
from phoenix.otel import register
from phoenix.otel import BatchSpanProcessor
from opentelemetry.context import Context
from opentelemetry.sdk.trace import ReadableSpan, Span
class FilteringSpanProcessor(BatchSpanProcessor):
def _filter_condition(self, span: Span) -> bool:
# returns True if the span should be filtered out
return span.name == "secret_span"
def on_start(self, span: Span, parent_context: Context) -> None:
if self._filter_condition(span):
return
super().on_start(span, parent_context)
def on_end(self, span: ReadableSpan) -> None:
if self._filter_condition(span):
logger.info("Filtering span: %s", span.name)
return
super().on_end(span)
tracer_provider = register()
tracer_provider.add_span_processor(
FilteringSpanProcessor(
endpoint="http://localhost:6006/v1/traces",
protocol="http/protobuf",
)
)