Metadata is arbitrary structured JSON data attached to traces or observations. Unlike tags (simple string labels), metadata is key-value data that enables precise filtering and rich analysis.
Understand Metadata Structure
Metadata is a JSON object with string keys and arbitrary values (strings, numbers, booleans, nested objects, arrays).Example metadata:
Nested objects: Group related data (model config, user details)
Merged on update: Adding new keys preserves existing metadata
Queryable: Filter traces using SQL-like queries on metadata fields
Avoid overwriting the same top-level key multiple times within a single trace. Metadata updates merge based on top-level keys, and rewriting a key produces undefined behavior. Add keys incrementally instead.
Add Metadata to Traces
Attach metadata when creating traces or update it dynamically as your code executes.Python (decorator pattern):
from abvdev import observe, ABVabv = ABV(api_key="sk-abv-...", host="https://app.abv.dev")@observe()def process_request(user_id, tenant_id): # Add metadata to the current trace abv.update_current_trace( metadata={ "tenant_id": tenant_id, "feature": "query-processing", "version": "1.2.3" } ) # Process the request result = handle_query(user_id) return resultprocess_request(user_id="user-456", tenant_id="acme-corp")
Python (manual span creation):
with abv.start_as_current_span(name="process-order") as root_span: # Add metadata to the trace root_span.update_trace(metadata={"order_id": "order-123", "region": "us-west"}) # Add metadata to the current span root_span.update(metadata={"stage": "validation"}) # Create child span with metadata with root_span.start_as_current_generation( name="generate-summary", model="gpt-4o", metadata={"temperature": 0.7, "max_tokens": 500} ) as gen: # Update metadata later if needed gen.update(metadata={"completion_reason": "stop"})
JavaScript/TypeScript:
import { startActiveObservation, updateActiveTrace } from '@abvdev/tracing';await startActiveObservation('process-request', async (span) => { // Add metadata to the trace updateActiveTrace({ metadata: { tenant_id: 'acme-corp', feature: 'summarization', version: '1.2.3' } }); // Add metadata to the observation span.update({ metadata: { stage: 'processing' } }); // Process request...});
Update Metadata Incrementally
Metadata updates merge based on top-level keys. You can add new keys throughout the trace lifecycle without overwriting existing data.Example: Incremental updates
with abv.start_as_current_span(name="workflow") as span: # First update: Add initial context span.update_trace(metadata={"status": "started", "user_id": "user-123"}) # Second update: Add more context (merges with existing) span.update_trace(metadata={"feature": "summarization", "model": "gpt-4"}) # Third update: Add error details if something fails try: result = process_data() except Exception as e: span.update_trace(metadata={"error_type": "timeout", "error_message": str(e)}) raise# Final metadata: {"status": "started", "user_id": "user-123", "feature": "summarization", "model": "gpt-4", "error_type": "timeout", "error_message": "..."}
Do not write the same top-level key multiple times:
# GOOD: Different keys for each stagespan.update_trace(metadata={"stage_1": "started"})span.update_trace(metadata={"stage_2": "processing"})span.update_trace(metadata={"stage_3": "completed"})
Query Traces by Metadata
In the ABV Dashboard, filter traces using SQL-like queries on metadata fields.Query examples:
metadata.tenant_id = "acme-corp" → All traces for tenant “acme-corp”
metadata.feature = "summarization" → All traces for the summarization feature
metadata.version = "v2.3" AND environment = "production" → Traces for specific version in production
metadata.user_tier = "enterprise" → Traces for enterprise users only
metadata.model_config.temperature > 0.5 → Traces with high temperature settings
Dashboard workflow:
Navigate to the Traces view
Click “Add Filter”
Select “Metadata” and enter your query
Results update instantly
Export filtered traces:
Export to CSV for analysis
Create datasets for evaluations
Generate reports for stakeholders
Aggregate Metrics by Metadata
Use metadata dimensions to aggregate costs, latency, and quality metrics for business analysis.Example analyses:
Cost by tenant: Group traces by metadata.tenant_id to calculate per-tenant LLM costs
Latency by feature: Filter by metadata.feature to identify slow features
Quality by experiment: Compare metadata.experiment_version to measure A/B test results
Error rate by region: Analyze metadata.region to detect regional issues
Dashboard aggregations:
Navigate to Metrics → Custom Dashboards
Create charts grouped by metadata fields
Track trends over time for specific dimensions
Set alerts based on metadata filters (e.g., “alert when enterprise tier costs exceed threshold”)
Create spans manually and attach metadata at the trace or span level.Trace-level metadata:
from abvdev import ABVabv = ABV(api_key="sk-abv-...", host="https://app.abv.dev")# Add metadata to the tracewith abv.start_as_current_span(name="process-request") as root_span: # Set trace metadata root_span.update_trace(metadata={ "request_id": "req_12345", "tenant_id": "acme-corp", "feature": "document-processing" }) # Set span metadata root_span.update(metadata={"stage": "parsing"}) # Your code here result = process_document()
Span-level metadata:
with abv.start_as_current_span(name="workflow") as root_span: root_span.update_trace(metadata={"workflow_id": "wf-123"}) # Child span with its own metadata with root_span.start_as_current_generation( name="generate-summary", model="gpt-4o", metadata={"temperature": 0.7, "max_tokens": 1000} ) as gen: # Update generation metadata gen.update(metadata={"completion_reason": "stop", "tokens_used": 850})
JavaScript/TypeScript: Context Managers
Use the @abvdev/tracing package to add metadata to traces and observations.Setup: