Setup Sentry Metrics in any project. Use this when asked to add Sentry metrics, track custom metrics, setup counters/gauges/distributions, or instrument application performance metrics. Supports JavaScript, TypeScript, Python, React, Next.js, and Node.js.
/plugin marketplace add getsentry/sentry-for-claude/plugin install sentry@sentry-plugin-marketplaceThis skill is limited to using the following tools:
This skill helps configure Sentry's custom metrics feature to track counters, gauges, and distributions across your applications.
Invoke this skill when:
Sentry.metrics or sentry_sdk.metricsSupported Platforms:
Note: Ruby does not currently have dedicated metrics support in the Sentry SDK.
Before setup, explain the three metric types to the user:
| Type | Purpose | Use Cases | Aggregations |
|---|---|---|---|
| Counter | Track cumulative occurrences | Button clicks, API calls, errors | sum, per_second, per_minute |
| Gauge | Point-in-time snapshots | Queue depth, memory usage, connections | min, max, avg |
| Distribution | Statistical analysis of values | Response times, cart amounts, query duration | p50, p75, p95, p99, avg, min, max |
Check for these files:
package.json - Read to identify framework and Sentry SDK version@sentry/nextjs, @sentry/react, @sentry/node, @sentry/browserCheck for:
requirements.txt, pyproject.toml, setup.py, or Pipfilesentry-sdk version 2.44.0+ (required for metrics)Ask the user:
I'll help you set up Sentry Metrics. First, let me check your project setup.
After detecting the platform:
1. **What metrics do you want to track?**
- Counters: Event counts (clicks, API calls, errors)
- Gauges: Point-in-time values (queue depth, memory)
- Distributions: Value analysis (response times, amounts)
2. **Do you need metric filtering?**
- Yes: Configure beforeSendMetric to filter/modify metrics
- No: Send all metrics as-is
10.25.0+grep -E '"@sentry/(nextjs|react|node|browser)"' package.json
If version is below 10.25.0, inform user to upgrade:
npm install @sentry/nextjs@latest # or appropriate package
Metrics are enabled by default in SDK 10.25.0+. No changes to Sentry.init() are required unless user wants to disable or filter.
Locate init files:
instrumentation-client.ts, sentry.server.config.ts, sentry.edge.config.tssrc/index.tsx, src/main.tsx, or dedicated sentry config fileOptional: Explicitly enable (not required):
import * as Sentry from "@sentry/nextjs"; // or @sentry/react, @sentry/node
Sentry.init({
dsn: "YOUR_DSN_HERE",
// Metrics enabled by default, but can be explicit
enableMetrics: true,
// ... other existing config
});
If user wants to filter metrics before sending:
Sentry.init({
dsn: "YOUR_DSN_HERE",
beforeSendMetric: (metric) => {
// Drop metrics with sensitive attributes
if (metric.attributes?.sensitive === true) {
return null;
}
// Remove specific attribute before sending
if (metric.attributes?.internal) {
delete metric.attributes.internal;
}
return metric;
},
});
If user explicitly wants to disable metrics:
Sentry.init({
dsn: "YOUR_DSN_HERE",
enableMetrics: false,
});
Provide these examples to the user based on their use case:
// Basic counter - increment by 1
Sentry.metrics.count("button_click", 1);
// Counter with attributes for filtering/grouping
Sentry.metrics.count("api_call", 1, {
attributes: {
endpoint: "/api/users",
method: "GET",
status_code: 200,
},
});
// Counter for errors
Sentry.metrics.count("checkout_error", 1, {
attributes: {
error_type: "payment_declined",
payment_provider: "stripe",
},
});
// Counter for business events
Sentry.metrics.count("email_sent", 1, {
attributes: {
template: "welcome",
recipient_type: "new_user",
},
});
// Basic gauge
Sentry.metrics.gauge("queue_depth", 42);
// Memory usage gauge
Sentry.metrics.gauge("memory_usage", process.memoryUsage().heapUsed, {
unit: "byte",
attributes: {
process: "main",
},
});
// Connection pool gauge
Sentry.metrics.gauge("db_connections", 15, {
attributes: {
pool: "primary",
max_connections: 100,
},
});
// Active users gauge
Sentry.metrics.gauge("active_users", currentUserCount, {
attributes: {
region: "us-east",
},
});
// Response time distribution
Sentry.metrics.distribution("response_time", 187.5, {
unit: "millisecond",
attributes: {
endpoint: "/api/products",
method: "GET",
},
});
// Cart value distribution
Sentry.metrics.distribution("cart_value", 149.99, {
unit: "usd",
attributes: {
customer_tier: "premium",
},
});
// Query duration distribution
Sentry.metrics.distribution("db_query_duration", 45.2, {
unit: "millisecond",
attributes: {
query_type: "select",
table: "users",
},
});
// File size distribution
Sentry.metrics.distribution("upload_size", 2048576, {
unit: "byte",
attributes: {
file_type: "image",
},
});
// Force pending metrics to send immediately
await Sentry.flush();
// Useful before process exit or after critical operations
process.on("beforeExit", async () => {
await Sentry.flush();
});
sentry-sdk version 2.44.0+pip show sentry-sdk | grep Version
If version is below 2.44.0:
pip install --upgrade sentry-sdk
Metrics are enabled by default in SDK 2.44.0+. No changes required unless filtering is needed.
Common init locations:
settings.pyapp.py or __init__.pymain.pyimport sentry_sdk
def before_send_metric(metric, hint):
# Drop metrics with specific attributes
if metric.get("attributes", {}).get("sensitive"):
return None
# Modify metric before sending
if metric.get("attributes", {}).get("internal"):
del metric["attributes"]["internal"]
return metric
sentry_sdk.init(
dsn="YOUR_DSN_HERE",
before_send_metric=before_send_metric,
)
import sentry_sdk
# Basic counter
sentry_sdk.metrics.count("button_click", 1)
# Counter with attributes
sentry_sdk.metrics.count(
"api_call",
1,
attributes={
"endpoint": "/api/users",
"method": "GET",
"status_code": 200,
}
)
# Counter for errors
sentry_sdk.metrics.count(
"checkout_error",
1,
attributes={
"error_type": "payment_declined",
"payment_provider": "stripe",
}
)
# Business event counter
sentry_sdk.metrics.count(
"email_sent",
5, # Can increment by more than 1
attributes={
"template": "newsletter",
"batch_id": "batch_123",
}
)
import sentry_sdk
import psutil
# Basic gauge
sentry_sdk.metrics.gauge("queue_depth", 42)
# Memory usage gauge
sentry_sdk.metrics.gauge(
"memory_usage",
psutil.virtual_memory().used,
unit="byte",
attributes={"host": "web-01"}
)
# Database connection gauge
sentry_sdk.metrics.gauge(
"db_connections",
connection_pool.size(),
attributes={
"pool": "primary",
"max": connection_pool.max_size,
}
)
# Cache hit rate gauge
sentry_sdk.metrics.gauge(
"cache_hit_rate",
0.85,
attributes={"cache": "redis"}
)
import sentry_sdk
import time
# Response time distribution
start = time.time()
# ... do work ...
duration_ms = (time.time() - start) * 1000
sentry_sdk.metrics.distribution(
"response_time",
duration_ms,
unit="millisecond",
attributes={
"endpoint": "/api/products",
"method": "GET",
}
)
# Order value distribution
sentry_sdk.metrics.distribution(
"order_value",
order.total,
unit="usd",
attributes={
"customer_tier": customer.tier,
"payment_method": order.payment_method,
}
)
# Query duration distribution
sentry_sdk.metrics.distribution(
"db_query_duration",
query_time_ms,
unit="millisecond",
attributes={
"query_type": "select",
"table": "orders",
}
)
Use these units for better readability in Sentry dashboard:
| Category | Units |
|---|---|
| Time | nanosecond, microsecond, millisecond, second, minute, hour, day, week |
| Size | bit, byte, kilobyte, megabyte, gigabyte, terabyte |
| Currency | usd, eur, gbp (or any ISO currency code) |
| Rate | ratio, percent |
| Other | none (default), or custom string |
# Good - descriptive, namespaced
api.request.duration
checkout.cart.value
user.signup.completed
# Avoid - vague, inconsistent
duration
value1
myMetric
async function withTiming(name, fn, attributes = {}) {
const start = performance.now();
try {
return await fn();
} finally {
const duration = performance.now() - start;
Sentry.metrics.distribution(name, duration, {
unit: "millisecond",
attributes,
});
}
}
// Usage
const result = await withTiming(
"api.external.duration",
() => fetch("https://api.example.com/data"),
{ service: "example-api" }
);
import functools
import time
import sentry_sdk
def track_duration(metric_name, **extra_attrs):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
try:
return func(*args, **kwargs)
finally:
duration_ms = (time.time() - start) * 1000
sentry_sdk.metrics.distribution(
metric_name,
duration_ms,
unit="millisecond",
attributes=extra_attrs,
)
return wrapper
return decorator
# Usage
@track_duration("db.query.duration", query_type="user_lookup")
def get_user_by_id(user_id):
return db.query(User).filter(User.id == user_id).first()
function metricsMiddleware(req, res, next) {
const start = performance.now();
res.on("finish", () => {
const duration = performance.now() - start;
Sentry.metrics.distribution("http.request.duration", duration, {
unit: "millisecond",
attributes: {
method: req.method,
route: req.route?.path || req.path,
status_code: res.statusCode,
},
});
Sentry.metrics.count("http.request.count", 1, {
attributes: {
method: req.method,
status_code: res.statusCode,
},
});
});
next();
}
app.use(metricsMiddleware);
import time
import sentry_sdk
class SentryMetricsMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start = time.time()
response = self.get_response(request)
duration_ms = (time.time() - start) * 1000
sentry_sdk.metrics.distribution(
"http.request.duration",
duration_ms,
unit="millisecond",
attributes={
"method": request.method,
"path": request.path,
"status_code": response.status_code,
},
)
return response
# Add to MIDDLEWARE in settings.py
After setup, provide these verification instructions:
// Add this temporarily to test
Sentry.metrics.count("test_metric", 1, {
attributes: { test: true },
});
Sentry.metrics.gauge("test_gauge", 42);
Sentry.metrics.distribution("test_distribution", 100, {
unit: "millisecond",
});
// Force flush to send immediately
await Sentry.flush();
import sentry_sdk
sentry_sdk.metrics.count("test_metric", 1, attributes={"test": True})
sentry_sdk.metrics.gauge("test_gauge", 42)
sentry_sdk.metrics.distribution("test_distribution", 100, unit="millisecond")
Tell user to check their Sentry dashboard under Metrics section to verify metrics are arriving.
Solutions:
enableMetrics: false)await Sentry.flush() or check aggregation windowSolutions:
beforeSendMetric to filter unnecessary metricsSolutions:
Solutions:
Provide this checklist after setup:
## Sentry Metrics Setup Complete
### Configuration Applied:
- [ ] SDK version verified (JS: 10.25.0+, Python: 2.44.0+)
- [ ] Metrics enabled (default) or explicitly configured
- [ ] Metric filtering configured (if requested)
### Instrumentation Added:
- [ ] Counter metrics for events/actions
- [ ] Gauge metrics for point-in-time values
- [ ] Distribution metrics for timing/values
- [ ] Appropriate units specified
- [ ] Meaningful attributes added
### Next Steps:
1. Run your application
2. Trigger actions that emit metrics
3. Check Sentry dashboard > Metrics section
4. Create dashboards and alerts based on metrics
| Platform | SDK Version | API Namespace |
|---|---|---|
| JavaScript | 10.25.0+ | Sentry.metrics.* |
| Python | 2.44.0+ | sentry_sdk.metrics.* |
| Method | JavaScript | Python |
|---|---|---|
| Counter | Sentry.metrics.count(name, value, options) | sentry_sdk.metrics.count(name, value, **kwargs) |
| Gauge | Sentry.metrics.gauge(name, value, options) | sentry_sdk.metrics.gauge(name, value, **kwargs) |
| Distribution | Sentry.metrics.distribution(name, value, options) | sentry_sdk.metrics.distribution(name, value, **kwargs) |
| Option | JavaScript | Python |
|---|---|---|
| Unit | { unit: "millisecond" } | unit="millisecond" |
| Attributes | { attributes: { key: "value" } } | attributes={"key": "value"} |