Skip to main content

Application metrics

Metrics are the numbers your app produces that aren't errors: orders placed, queue depth, checkout latency, unique visitors. Errora accepts both wire formats Sentry SDKs emit.

Metric types​

TypeUse it forAggregates
counter (c)Things that happensum, count
distribution (d)Measured values (latency, size)avg, min, max, p50–p99
gauge (g)A level at a point in timelast, min, max, avg
set (s)Distinct thingscount_unique

Setup — SDK​

Sentry.metrics.increment("checkout.attempt", 1, { tags: { plan: "pro" } });
Sentry.metrics.distribution("checkout.latency", 421, { unit: "millisecond", tags: { route: "/pay" } });
Sentry.metrics.gauge("queue.depth", 128, { tags: { queue: "ingest" } });
Sentry.metrics.set("visitors", userId);
sentry_sdk.metrics.incr("orders.created", 1, tags={"plan": "pro"})
sentry_sdk.metrics.distribution("orders.total", order.total, unit="none")
sentry_sdk.metrics.gauge("queue.depth", depth, tags={"queue": "ingest"})
sentry_sdk.metrics.set("visitors", user_id)

SDKs pre-aggregate before sending: what arrives is a bucket per metric per time window, not one message per call. Distributions keep a sample of the raw values, so percentiles stay answerable, and sets count distinct members as a union across buckets rather than a sum.

Setup — raw wire formats​

1. trace_metric items (current SDKs) — the same batch container as logs:

{"items":[{"timestamp":1767225600.0,"name":"checkout.latency","type":"distribution",
"value":42.0,"unit":"millisecond","trace_id":"7b3f…",
"attributes":{"route":{"value":"/pay","type":"string"}}}]}

2. statsd text (the original protocol), newline-delimited:

<name>[@<unit>]:<v1>[:<v2>…]|<type>|#<tag>:<value>,…|T<unix_seconds>

endpoint.response_time@millisecond:57:92|d|#route:/pay,method:POST|T1615889449
button_click@none:1|c|#browser:firefox

A statsd gauge with exactly five values is the pre-aggregated last:min:max:sum:count form, not five readings.

Limits per batch: 1000 items, 30 tags per metric, 200 characters per name or tag value.

Querying​

Metrics in the sidebar lists the metric names a project has sent. Pick one and choose:

  • an aggregate — sum, avg, min, max, p50, p75, p90, p95, p99, count_unique
  • a group-by tag, to split the series
  • an environment and a time period

avg is always the true sum / count over the window, never the average of per-bucket averages.

GET /api/v1/projects/{project_id}/metrics?q=&stats_period=24h
GET /api/v1/projects/{project_id}/metrics/series?name=&op=&group_by=&environment=&stats_period=24h
GET /api/v1/projects/{project_id}/metrics/summary?name=&environment=&stats_period=24h
GET /api/v1/projects/{project_id}/metrics/tags?name=&stats_period=24h

Naming that stays useful​

  • domain.thing.measure — checkout.latency, queue.depth, sms.sent.
  • Put varying values in tags, never in the name. orders.created tagged plan:pro beats orders.created.pro.
  • Keep tag cardinality low: route yes, user_id no. Every distinct tag combination is its own bucket, and you are billed per metric bucket.

Dashboards​

Metrics are a dashboard dataset — put a metric series next to your error counts and transaction latency on the same board.

Troubleshooting​

SymptomCause / fix
Metric name missing from the listNothing has arrived in the selected period — widen it
Percentiles look approximateA bucket kept a bounded sample (100 values); that is by design
count_unique lower than expectedSet members are hashed and bounded per bucket (500)
Tag missingIt exceeded the 30-tag or 200-character limit and was dropped
Costs climbingTag cardinality — one high-cardinality tag multiplies your bucket count