Add attributes to a span
Attributes are key/value pairs that provide more information about the operation being traced. They help paint a complete picture of what’s happening in your application.
To avoid naming conflicts with semantic conventions, it’s recommended to prefix your custom attributes with your company name (e.g., mycompany.).
from opentelemetry import trace
current_span = trace.get_current_span()
current_span.set_attribute("operation.value", 1)
current_span.set_attribute("operation.name", "Saying hello!")
current_span.set_attribute("operation.other-stuff", [1, 2])
Leveraging Semantic Convention Attributes
Semantic Conventions provides a structured schema to represent common LLM application attributes. These are well known names for items like messages, prompt templates, metadata, and more. We’ve built a set of semantic conventions as part of the traceAI package.
Defining attributes is vital for comprehending the data and message flow within your LLM application and helps in debugging and analysis. By defining attributes like OUTPUT_VALUE
and OUTPUT_MESSAGES
, you can capture essential output information and interaction messages within a span’s context. This enables you to log the response and systematically categorize and store messages exchanged by components.
To use traceAI Semantic Attributes, ensure you have the appropriate FI Instrumentation Package installed:
pip install fi-instrumentation-otel
Then run the following to set semantic attributes:
from opentelemetry import trace # Assuming span is current_span or obtained otherwise
from fi_instrumentation.fi_types import SpanAttributes, MessageAttributes # Assuming these constants and 'response' are defined
span = trace.get_current_span() # Example: get current span
if span.is_recording(): # Check if span is recording before setting attributes
span.set_attribute(SpanAttributes.OUTPUT_VALUE, response)
# This shows up under `output_messages` tab on the span page
span.set_attribute(
f"{SpanAttributes.LLM_OUTPUT_MESSAGES}.0.{MessageAttributes.MESSAGE_ROLE}",
"user",
)
span.set_attribute(
f"{SpanAttributes.LLM_OUTPUT_MESSAGES}.0.{MessageAttributes.MESSAGE_CONTENT}",
response,
)
Adding attributes to multiple spans at once
Our tracing system allows you to set attributes at the OpenTelemetry Context level, which automatically propagates to child spans within a parent trace. In OpenTelemetry, this is often achieved using Baggage. Attributes set in Baggage can be picked up by instrumentation (like traceAI’s auto-instrumentation) and added to spans.
Key Context Attributes include:
- Metadata: Metadata associated with a span.
- Tags: List of tags to give the span a category.
- Session ID: Unique identifier for a session.
- User ID: Unique identifier for a user.
- Prompt Template:
- Template: Used to generate prompts as Python f-strings.
- Version: The version of the prompt template.
- Variables: key-value pairs applied to the prompt template.
Below are examples showing how to manage these attributes. The Python examples use helpers from fi_instrumentation
. The Typescript examples use standard OpenTelemetry JS API (context
and propagation
for Baggage).
This context manager enriches the current OpenTelemetry Context with metadata. Our auto-instrumentators will apply this metadata as span attributes following traceAI semantic conventions. The metadata must be provided as a string-keyed dictionary, which will be JSON-serialized in the context.
from fi_instrumentation import using_metadata
# Assuming value_1, value_2 are defined
# value_1 = "some data"; value_2 = 123
metadata = {
"key-1": value_1,
"key-2": value_2,
}
with using_metadata(metadata):
# Calls within this block will generate spans with the attributes:
# "metadata" = "{"key-1": value_1, "key-2": value_2, ... }" # JSON serialized
pass # Your code here
It can also be used as a decorator:
from fi_instrumentation import using_metadata
# Assuming metadata is defined as above
@using_metadata(metadata)
def call_fn(*args, **kwargs):
# Calls within this function will generate spans with the attributes:
# "metadata" = "{"key-1": value_1, "key-2": value_2, ... }" # JSON serialized
pass # Your function code here
Enhance spans with categorical information using this context manager. It adds tags to the OpenTelemetry Context, which our auto-instrumentators will apply following traceAI conventions. Tags must be provided as a list of strings.
from fi_instrumentation import using_tags
# Assuming tags list is defined
# tags = ["tag_1", "tag_2"]
with using_tags(tags):
# Calls within this block will generate spans with the attributes:
# "tag.tags" = "["tag_1","tag_2",...]"
pass # Your code here
It can also be used as a decorator:
from fi_instrumentation import using_tags
# Assuming tags is defined as above
@using_tags(tags)
def call_fn(*args, **kwargs):
# Calls within this function will generate spans with the attributes:
# "tag.tags" = "["tag_1","tag_2",...]"
pass # Your function code here
using_session
Set a session identifier for all spans within the context. This is useful for grouping related operations under a common session.
from fi_instrumentation import using_session
# Assuming session_id is defined
# session_id = "session_123"
with using_session(session_id):
# Calls within this block will generate spans with the attributes:
# "session.id" = "session_123"
pass # Your code here
It can also be used as a decorator:
from fi_instrumentation import using_session
# Assuming session_id is defined as above
@using_session(session_id)
def call_fn(*args, **kwargs):
# Calls within this function will generate spans with the attributes:
# "session.id" = "session_123"
pass # Your function code here
using_user
Set a user identifier for all spans within the context. This helps in tracking operations performed by specific users.
from fi_instrumentation import using_user
# Assuming user_id is defined
# user_id = "user_456"
with using_user(user_id):
# Calls within this block will generate spans with the attributes:
# "user.id" = "user_456"
pass # Your code here
It can also be used as a decorator:
from fi_instrumentation import using_user
# Assuming user_id is defined as above
@using_user(user_id)
def call_fn(*args, **kwargs):
# Calls within this function will generate spans with the attributes:
# "user.id" = "user_456"
pass # Your function code here
using_prompt_template
This context manager is used to enrich spans with prompt template information. It’s particularly useful when you want to track how prompts are constructed and which variables are used.
from fi_instrumentation import using_prompt_template
# Assuming template, version, and variables are defined
# template = "Hello {name}, your age is {age}"
# version = "v1.0"
# variables = {"name": "Alice", "age": 30}
with using_prompt_template(
template=template,
version=version,
variables=variables
):
# Calls within this block will generate spans with the attributes:
# "llm.prompt_template.template" = "Hello {name}, your age is {age}"
# "llm.prompt_template.version" = "v1.0"
# "llm.prompt_template.variables" = '{"name": "Alice", "age": 30}'
pass # Your code here
It can also be used as a decorator:
from fi_instrumentation import using_prompt_template
# Assuming template, version, and variables are defined as above
@using_prompt_template(
template=template,
version=version,
variables=variables
)
def call_fn(*args, **kwargs):
# Calls within this function will generate spans with the attributes:
# "llm.prompt_template.template" = "Hello {name}, your age is {age}"
# "llm.prompt_template.version" = "v1.0"
# "llm.prompt_template.variables" = '{"name": "Alice", "age": 30}'
pass # Your function code here
Combining Multiple Context Managers
You can combine multiple context managers to set various attributes simultaneously:
from fi_instrumentation import using_metadata, using_tags, using_session, using_user
metadata = {"experiment": "A/B test", "version": "2.1"}
tags = ["production", "critical"]
session_id = "session_789"
user_id = "user_101"
with using_metadata(metadata), \
using_tags(tags), \
using_session(session_id), \
using_user(user_id):
# All spans created within this block will have:
# - metadata attributes
# - tag attributes
# - session.id attribute
# - user.id attribute
pass # Your code here