Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Arize ai Phoenix SpanQuery DSL

From Leeroopedia
Knowledge Sources
Domains AI_Observability, Client_SDK, Query_Language
Last Updated 2026-02-14 05:30 GMT

Overview

A span query DSL (Domain-Specific Language) with field selection, filtering, explosion, concatenation, renaming, and indexing operations for retrieving and reshaping span data from the Phoenix server.

Description

The SpanQuery DSL module provides a fluent, chainable interface for constructing queries against Phoenix span data. All query operations return new immutable SpanQuery instances, enabling a functional builder pattern.

The module includes five dataclass types:

  • Projection -- Represents a field selection. Wraps a single key string and validates that it is not empty.
  • SpanFilter -- Represents a filter condition as a string expression. On initialization, it automatically replaces legacy field names (e.g., context.span_id to span_id) for backward compatibility.
  • Explosion -- Represents an operation that expands a nested or repeated field into separate rows, similar to a SQL UNNEST. Tracks a primary_index_key (defaulting to context.span_id) and optional keyword arguments for mapping nested fields to columns.
  • Concatenation -- Represents an operation that joins values of a repeated field into a single string with a configurable separator (default "\n\n").
  • SpanQuery -- The main query builder. It holds optional references to _select, _filter, _explode, _concat, _rename, and _index components, and provides chainable methods to compose them.

The module also maintains backward compatibility mappings that translate legacy Phoenix field names (e.g., cumulative_token_count.completion) to their current equivalents (e.g., cumulative_llm_token_count_completion). A _normalize_field() function handles both alias expansion (e.g., span_id to context.span_id) and legacy name replacement.

The to_dict() method on SpanQuery serializes the entire query into a dictionary suitable for sending as a JSON request body. If no explicit index has been set, it defaults to context.span_id.

Usage

Use SpanQuery when programmatically querying span data from a Phoenix server through the client SDK. The fluent API allows constructing queries with field selection, filtering, expansion of nested structures, and column renaming, all without string manipulation.

Code Reference

Source Location

Signature

@dataclass
class Projection:
    key: str
    def to_dict(self) -> dict[str, Any]: ...

@dataclass
class SpanFilter:
    condition: str
    valid_eval_names: Optional[list[str]] = None
    def to_dict(self) -> dict[str, Any]: ...

@dataclass
class Explosion:
    key: str
    kwargs: dict[str, str] = field(default_factory=dict)
    primary_index_key: str = "context.span_id"
    def to_dict(self) -> dict[str, Any]: ...

@dataclass
class Concatenation:
    key: str
    kwargs: dict[str, str] = field(default_factory=dict)
    separator: str = "\n\n"
    def to_dict(self) -> dict[str, Any]: ...

@dataclass
class SpanQuery:
    def select(self, *fields: str) -> "SpanQuery": ...
    def where(self, condition: str) -> "SpanQuery": ...
    def explode(self, key: str, **kwargs: str) -> "SpanQuery": ...
    def concat(self, key: str, **kwargs: str) -> "SpanQuery": ...
    def rename(self, **kwargs: str) -> "SpanQuery": ...
    def with_index(self, key: str) -> "SpanQuery": ...
    def to_dict(self) -> dict[str, Any]: ...

Import

from phoenix.client.types.spans import SpanQuery, Projection, SpanFilter, Explosion, Concatenation

I/O Contract

SpanQuery Methods

Method Parameters Returns Description
select() *fields: str SpanQuery Select specific span fields to include in results
where() condition: str SpanQuery Apply a filter condition to restrict returned spans
explode() key: str, **kwargs: str SpanQuery Expand a nested/repeated field into separate rows
concat() key: str, **kwargs: str SpanQuery Concatenate a repeated field's values into a single string
rename() **kwargs: str SpanQuery Rename fields in the output (old_name=new_name)
with_index() key: str SpanQuery Set the index field for the result (default context.span_id)
to_dict() (none) dict[str, Any] Serialize the query to a dictionary for API requests

Serialized Output Structure

Key Type Description
select dict[str, dict] Mapping of field names to Projection dicts
filter dict Contains condition string
explode dict Contains key, primary_index_key, and optional kwargs
concat dict Contains key, separator, and optional kwargs
rename dict[str, str] Old-name to new-name mapping
index dict Contains key (defaults to context.span_id)

Usage Examples

from phoenix.client.types.spans import SpanQuery

# Simple field selection with a filter
query = (
    SpanQuery()
    .select("name", "status_code", "latency_ms", "llm.token_count.total")
    .where("status_code == 'ERROR'")
)
print(query.to_dict())
# {
#     "select": {"name": {"key": "name"}, "status_code": {"key": "status_code"}, ...},
#     "filter": {"condition": "status_code == 'ERROR'"},
#     "index": {"key": "context.span_id"}
# }

# Explode retrieval documents into separate rows
query = (
    SpanQuery()
    .select("name")
    .where("span_kind == 'RETRIEVER'")
    .explode("retrieval.documents", text="document.content", score="document.score")
)

# Concatenate document content into a single string
query = (
    SpanQuery()
    .select("name")
    .concat("retrieval.documents", text="document.content")
)

# Rename output columns and set custom index
query = (
    SpanQuery()
    .select("input.value", "output.value")
    .rename(input_value="prompt", output_value="response")
    .with_index("context.trace_id")
)

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment