Sending Span Metrics
Learn how to add attributes to spans in Sentry to monitor performance and debug applications
Looking for standalone counters, gauges, or distributions?
Span metrics are great for enriching your existing traces with custom data. If you need metrics that are independent of tracing — such as business event counters, success/failure rates, or aggregates that aren't affected by trace sampling — use Application Metrics instead.
To use span metrics, you must first configure tracing in your application.
Span metrics allow you to extend the default metrics that are collected by tracing and track custom performance data and debugging information within your application's traces. There are two main approaches to instrumenting metrics:
This page covers both transaction mode (default) and stream mode. See Streamed Spans to learn more.
You can enhance existing spans with custom metrics by adding data. This is useful when you want to augment automatic instrumentation or add contextual data to spans you've already created.
span = sentry_sdk.get_current_span()
if span:
# Add individual metrics
span.set_data("database.rows_affected", 42)
span.set_data("cache.hit_rate", 0.85)
span.set_data("memory.heap_used", 1024000)
span.set_data("queue.length", 15)
span.set_data("processing.duration_ms", 127)
span = sentry_sdk.get_current_span()
if span:
# Add individual metrics
span.set_data("database.rows_affected", 42)
span.set_data("cache.hit_rate", 0.85)
span.set_data("memory.heap_used", 1024000)
span.set_data("queue.length", 15)
span.set_data("processing.duration_ms", 127)
span = sentry_sdk.traces.get_current_span()
if span:
# Add individual metrics
span.set_attribute("database.rows_affected", 42)
span.set_attribute("cache.hit_rate", 0.85)
span.set_attribute("memory.heap_used", 1024000)
span.set_attribute("queue.length", 15)
span.set_attribute("processing.duration_ms", 127)
When adding metrics as span data:
- Use consistent naming conventions (for example,
category.metric_name) - Keep attribute names concise but descriptive
- Use appropriate data types (string, number, boolean, or an array containing only one of these types)
For more detailed operations, tasks, or process tracking, you can create custom dedicated spans that focus on specific metrics or attributes that you want to track. This approach provides better discoverability and more precise span configurations, however it can also create more noise in your trace waterfall.
with sentry_sdk.start_span(
op="db.metrics",
name="Database Query Metrics"
) as span:
# Set metrics after creating the span
span.set_data("db.query_type", "SELECT")
span.set_data("db.table", "users")
span.set_data("db.execution_time_ms", 45)
span.set_data("db.rows_returned", 100)
span.set_data("db.connection_pool_size", 5)
# Your database operation here
pass
with sentry_sdk.start_span(
op="db.metrics",
name="Database Query Metrics"
) as span:
# Set metrics after creating the span
span.set_data("db.query_type", "SELECT")
span.set_data("db.table", "users")
span.set_data("db.execution_time_ms", 45)
span.set_data("db.rows_returned", 100)
span.set_data("db.connection_pool_size", 5)
# Your database operation here
pass
with sentry_sdk.traces.start_span(
name="Database Query Metrics",
attributes={"sentry.op": "db.metrics"},
) as span:
# Set metrics after creating the span
span.set_attributes({
"db.query_type": "SELECT",
"db.table": "users",
"db.execution_time_ms": 45,
"db.rows_returned": 100,
"db.connection_pool_size": 5,
})
# Your database operation here
pass
For detailed examples of how to implement span metrics in common scenarios, see our Span Metrics Examples guide.
How you add data to every span depends on your tracing mode:
import sentry_sdk
from sentry_sdk.types import Event, Hint
def before_send_transaction(event: Event, hint: Hint) -> Event | None:
# Add attributes to the root span (transaction)
if "trace" in event.get("contexts", {}):
if "data" not in event["contexts"]["trace"]:
event["contexts"]["trace"]["data"] = {}
event["contexts"]["trace"]["data"].update({
"app_version": "1.2.3",
"environment_region": "us-west-2"
})
# Add attributes to all child spans
for span in event.get("spans", []):
if "data" not in span:
span["data"] = {}
span["data"].update({
"component_version": "2.0.0",
"deployment_stage": "production"
})
return event
sentry_sdk.init(
# ...
before_send_transaction=before_send_transaction
)
import sentry_sdk
from sentry_sdk.types import Event, Hint
def before_send_transaction(event: Event, hint: Hint) -> Event | None:
# Add attributes to the root span (transaction)
if "trace" in event.get("contexts", {}):
if "data" not in event["contexts"]["trace"]:
event["contexts"]["trace"]["data"] = {}
event["contexts"]["trace"]["data"].update({
"app_version": "1.2.3",
"environment_region": "us-west-2"
})
# Add attributes to all child spans
for span in event.get("spans", []):
if "data" not in span:
span["data"] = {}
span["data"].update({
"component_version": "2.0.0",
"deployment_stage": "production"
})
return event
sentry_sdk.init(
# ...
before_send_transaction=before_send_transaction
)
import sentry_sdk
def before_send_span(span, hint):
# Runs once per span, as it's flushed.
if "attributes" not in span:
span["attributes"] = {}
span["attributes"].update({
"component_version": "2.0.0",
"deployment_stage": "production",
})
return span
sentry_sdk.init(
# ...
trace_lifecycle="stream",
before_send_span=before_send_span,
)
For detailed examples of how to implement span metrics in common scenarios, see our Span Metrics Examples guide.
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").