diff --git a/docs/guides/custom-spans.mdx b/docs/guides/custom-spans.mdx new file mode 100644 index 00000000000000..7bf53290f01cba --- /dev/null +++ b/docs/guides/custom-spans.mdx @@ -0,0 +1,766 @@ +--- +title: "Adding Custom Spans" +sidebar_order: 30 +description: "Add custom instrumentation for visibility beyond auto-instrumentation and set up alerts." +--- + +You've got your Sentry SDK [auto-instrumentation](/product/explore/trace-explorer/) running. Now what? + +Auto-instrumentation captures HTTP, database, and framework operations. But it can't see business logic, third-party APIs without auto-instrumentation, or background jobs. This guide shows you where to add custom spans to fill in those gaps. + +## Anatomy of a Span + +```javascript {tabTitle: JavaScript} +Sentry.startSpan({ name: "operation-name", op: "category" }, async (span) => { + span.setAttribute("key", value); + // ... your code ... +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +with sentry_sdk.start_span(name="operation-name", op="category") as span: + span.set_data("key", value) + # ... your code ... +``` + +```php {tabTitle: PHP} +$spanContext = \Sentry\Tracing\SpanContext::make() + ->setOp('category') + ->setDescription('operation-name') + ->setData(['key' => $value]); + +\Sentry\trace(function () { + // ... your code ... +}, $spanContext); +``` + +```csharp {tabTitle: .NET} +using Sentry; + +var transaction = SentrySdk.StartTransaction("operation-name", "category"); +var span = transaction.StartChild("category", "operation-name"); +span.SetExtra("key", value); +// ... your code ... +span.Finish(); +transaction.Finish(); +``` + +```ruby {tabTitle: Ruby} +Sentry.with_child_span(op: :category, description: 'operation-name') do |span| + span.set_data(:key, value) + # ... your code ... +end +``` + +```dart {tabTitle: Flutter} +import 'package:sentry/sentry.dart'; + +final transaction = Sentry.startTransaction('operation-name', 'category'); +final span = transaction.startChild('category', description: 'operation-name'); +span.setData('key', value); +// ... your code ... +await span.finish(); +await transaction.finish(); +``` + +```swift {tabTitle: Swift} +import Sentry + +let transaction = SentrySDK.startTransaction(name: "operation-name", operation: "category") +let span = transaction.startChild(operation: "category", description: "operation-name") +span.setData(value: value, key: "key") +// ... your code ... +span.finish() +transaction.finish() +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +val transaction = Sentry.startTransaction("operation-name", "category") +val span = transaction.startChild("category", "operation-name") +span.setData("key", value) +// ... your code ... +span.finish() +transaction.finish() +``` + +Numeric attributes become metrics you can aggregate with `sum()`, `avg()`, `p90()` in [Trace Explorer](https://sentry.io/orgredirect/organizations/:orgslug/explore/traces/). + +## Where to Add Spans + +Start with these five areas and you'll have visibility into the operations that matter most. + +### 1. Business-Critical User Flows + +Track the full journey through critical paths. When checkout is slow, you need to know which step is responsible. + +```javascript {tabTitle: JavaScript} +Sentry.startSpan({ name: "checkout-flow", op: "user.action" }, async (span) => { + span.setAttribute("cart.itemCount", 3); + span.setAttribute("user.tier", "premium"); + + await validateCart(); + await processPayment(); + await createOrder(); +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +with sentry_sdk.start_span(name="checkout-flow", op="user.action") as span: + span.set_data("cart.itemCount", 3) + span.set_data("user.tier", "premium") + + validate_cart() + process_payment() + create_order() +``` + +```php {tabTitle: PHP} +$spanContext = \Sentry\Tracing\SpanContext::make() + ->setOp('user.action') + ->setDescription('checkout-flow') + ->setData([ + 'cart.itemCount' => 3, + 'user.tier' => 'premium', + ]); + +\Sentry\trace(function () { + $this->validateCart(); + $this->processPayment(); + $this->createOrder(); +}, $spanContext); +``` + +```csharp {tabTitle: .NET} +var transaction = SentrySdk.StartTransaction("checkout-flow", "user.action"); +SentrySdk.ConfigureScope(scope => scope.Transaction = transaction); + +transaction.SetExtra("cart.itemCount", 3); +transaction.SetExtra("user.tier", "premium"); + +await ValidateCart(); +await ProcessPayment(); +await CreateOrder(); + +transaction.Finish(); +``` + +```ruby {tabTitle: Ruby} +Sentry.with_child_span(op: 'user.action', description: 'checkout-flow') do |span| + span.set_data('cart.itemCount', 3) + span.set_data('user.tier', 'premium') + + validate_cart + process_payment + create_order +end +``` + +```dart {tabTitle: Flutter} +final transaction = Sentry.startTransaction('checkout-flow', 'user.action'); +transaction.setData('cart.itemCount', 3); +transaction.setData('user.tier', 'premium'); + +await validateCart(); +await processPayment(); +await createOrder(); + +await transaction.finish(); +``` + +```swift {tabTitle: Swift} +import Sentry + +let transaction = SentrySDK.startTransaction(name: "checkout-flow", operation: "user.action") +transaction.setData(value: 3, key: "cart.itemCount") +transaction.setData(value: "premium", key: "user.tier") + +validateCart() +processPayment() +createOrder() + +transaction.finish() +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +val transaction = Sentry.startTransaction("checkout-flow", "user.action") +transaction.setData("cart.itemCount", 3) +transaction.setData("user.tier", "premium") + +validateCart() +processPayment() +createOrder() + +transaction.finish() +``` + +**Query in [Explore > Traces](https://sentry.io/orgredirect/organizations/:orgslug/explore/traces/):** `span.op:user.action` grouped by `user.tier`, visualize `p90(span.duration)`. + +**Alert idea:** `p90(span.duration) > 10s` for checkout flows. + +### 2. Third-Party API Calls + +Measure dependencies you don't control. They're often the source of slowdowns. + +```javascript {tabTitle: JavaScript} +Sentry.startSpan( + { name: "shipping-rates-api", op: "http.client" }, + async (span) => { + span.setAttribute("http.url", "api.shipper.com/rates"); + span.setAttribute("request.itemCount", items.length); + + const start = Date.now(); + const response = await fetch("https://api.shipper.com/rates"); + + span.setAttribute("http.status_code", response.status); + span.setAttribute("response.timeMs", Date.now() - start); + + return response.json(); + } +); +``` + +```python {tabTitle: Python} +import time +import sentry_sdk + +with sentry_sdk.start_span(name="shipping-rates-api", op="http.client") as span: + span.set_data("http.url", "api.shipper.com/rates") + span.set_data("request.itemCount", len(items)) + + start = time.time() + response = requests.get("https://api.shipper.com/rates") + + span.set_data("http.status_code", response.status_code) + span.set_data("response.timeMs", int((time.time() - start) * 1000)) +``` + +```php {tabTitle: PHP} +$spanContext = \Sentry\Tracing\SpanContext::make() + ->setOp('http.client') + ->setDescription('shipping-rates-api') + ->setData([ + 'http.url' => 'api.shipper.com/rates', + 'request.itemCount' => count($items), + ]); + +\Sentry\trace(function () use ($spanContext) { + $start = microtime(true); + $response = $this->httpClient->get('https://api.shipper.com/rates'); + + $span = \Sentry\SentrySdk::getCurrentHub()->getSpan(); + $span->setData([ + 'http.status_code' => $response->getStatusCode(), + 'response.timeMs' => (int)((microtime(true) - $start) * 1000), + ]); + + return $response; +}, $spanContext); +``` + +```csharp {tabTitle: .NET} +var transaction = SentrySdk.StartTransaction("shipping-rates-api", "http.client"); +SentrySdk.ConfigureScope(scope => scope.Transaction = transaction); + +transaction.SetExtra("http.url", "api.shipper.com/rates"); +transaction.SetExtra("request.itemCount", items.Count); + +var stopwatch = Stopwatch.StartNew(); +var response = await httpClient.GetAsync("https://api.shipper.com/rates"); + +transaction.SetExtra("http.status_code", (int)response.StatusCode); +transaction.SetExtra("response.timeMs", stopwatch.ElapsedMilliseconds); +transaction.Finish(); +``` + +```ruby {tabTitle: Ruby} +Sentry.with_child_span(op: 'http.client', description: 'shipping-rates-api') do |span| + span.set_data('http.url', 'api.shipper.com/rates') + span.set_data('request.itemCount', items.length) + + start = Process.clock_gettime(Process::CLOCK_MONOTONIC) + response = HTTParty.get('https://api.shipper.com/rates') + + span.set_data('http.status_code', response.code) + span.set_data('response.timeMs', ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).to_i) +end +``` + +```dart {tabTitle: Flutter} +final transaction = Sentry.startTransaction('shipping-rates-api', 'http.client'); +transaction.setData('http.url', 'api.shipper.com/rates'); +transaction.setData('request.itemCount', items.length); + +final stopwatch = Stopwatch()..start(); +final response = await http.get(Uri.parse('https://api.shipper.com/rates')); + +transaction.setData('http.status_code', response.statusCode); +transaction.setData('response.timeMs', stopwatch.elapsedMilliseconds); +await transaction.finish(); +``` + +```swift {tabTitle: Swift} +import Sentry + +let transaction = SentrySDK.startTransaction(name: "shipping-rates-api", operation: "http.client") +transaction.setData(value: "api.shipper.com/rates", key: "http.url") +transaction.setData(value: items.count, key: "request.itemCount") + +let start = Date() +let response = try await fetchShippingRates() + +transaction.setData(value: response.statusCode, key: "http.status_code") +transaction.setData(value: Int(Date().timeIntervalSince(start) * 1000), key: "response.timeMs") +transaction.finish() +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +val transaction = Sentry.startTransaction("shipping-rates-api", "http.client") +transaction.setData("http.url", "api.shipper.com/rates") +transaction.setData("request.itemCount", items.size) + +val start = System.currentTimeMillis() +val response = fetchShippingRates() + +transaction.setData("http.status_code", response.code) +transaction.setData("response.timeMs", System.currentTimeMillis() - start) +transaction.finish() +``` + +**Query in [Explore > Traces](https://sentry.io/orgredirect/organizations/:orgslug/explore/traces/):** `span.op:http.client response.timeMs:>2000` to find slow external calls. + +**Alert idea:** `p95(span.duration) > 3s` where `http.url` contains your critical dependencies. + +### 3. Database Queries with Business Context + +Auto-instrumentation catches queries, but custom spans let you add context that explains why a query matters. + +```javascript {tabTitle: JavaScript} +Sentry.startSpan( + { name: "load-user-dashboard", op: "db.query" }, + async (span) => { + span.setAttribute("db.system", "postgres"); + span.setAttribute("query.type", "aggregation"); + span.setAttribute("query.dateRange", "30d"); + + const results = await db.query(dashboardQuery); + span.setAttribute("result.rowCount", results.length); + + return results; + } +); +``` + +```python {tabTitle: Python} +import sentry_sdk + +with sentry_sdk.start_span(name="load-user-dashboard", op="db.query") as span: + span.set_data("db.system", "postgres") + span.set_data("query.type", "aggregation") + span.set_data("query.dateRange", "30d") + + results = db.execute(dashboard_query).fetchall() + span.set_data("result.rowCount", len(results)) +``` + +```php {tabTitle: PHP} +$spanContext = \Sentry\Tracing\SpanContext::make() + ->setOp('db.query') + ->setDescription('load-user-dashboard') + ->setData([ + 'db.system' => 'postgres', + 'query.type' => 'aggregation', + 'query.dateRange' => '30d', + ]); + +$results = \Sentry\trace(function () use ($dashboardQuery) { + $results = $this->db->query($dashboardQuery)->fetchAll(); + + $span = \Sentry\SentrySdk::getCurrentHub()->getSpan(); + $span->setData(['result.rowCount' => count($results)]); + + return $results; +}, $spanContext); +``` + +```csharp {tabTitle: .NET} +var transaction = SentrySdk.StartTransaction("load-user-dashboard", "db.query"); +SentrySdk.ConfigureScope(scope => scope.Transaction = transaction); + +transaction.SetExtra("db.system", "postgres"); +transaction.SetExtra("query.type", "aggregation"); +transaction.SetExtra("query.dateRange", "30d"); + +var results = await database.QueryAsync(dashboardQuery); +transaction.SetExtra("result.rowCount", results.Count); +transaction.Finish(); +``` + +```ruby {tabTitle: Ruby} +Sentry.with_child_span(op: 'db.query', description: 'load-user-dashboard') do |span| + span.set_data('db.system', 'postgres') + span.set_data('query.type', 'aggregation') + span.set_data('query.dateRange', '30d') + + results = database.execute(dashboard_query) + span.set_data('result.rowCount', results.length) +end +``` + +```dart {tabTitle: Flutter} +final transaction = Sentry.startTransaction('load-user-dashboard', 'db.query'); +transaction.setData('db.system', 'postgres'); +transaction.setData('query.type', 'aggregation'); +transaction.setData('query.dateRange', '30d'); + +final results = await database.query(dashboardQuery); +transaction.setData('result.rowCount', results.length); +await transaction.finish(); +``` + +```swift {tabTitle: Swift} +import Sentry + +let transaction = SentrySDK.startTransaction(name: "load-user-dashboard", operation: "db.query") +transaction.setData(value: "postgres", key: "db.system") +transaction.setData(value: "aggregation", key: "query.type") +transaction.setData(value: "30d", key: "query.dateRange") + +let results = try database.execute(dashboardQuery) +transaction.setData(value: results.count, key: "result.rowCount") +transaction.finish() +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +val transaction = Sentry.startTransaction("load-user-dashboard", "db.query") +transaction.setData("db.system", "postgres") +transaction.setData("query.type", "aggregation") +transaction.setData("query.dateRange", "30d") + +val results = database.query(dashboardQuery) +transaction.setData("result.rowCount", results.size) +transaction.finish() +``` + +**Why this matters:** Without these attributes, you see "a database query took 2 seconds." With them, you know it was aggregating 30 days of data and returned 50,000 rows. That's actionable. + +**Query ideas in [Explore > Traces](https://sentry.io/orgredirect/organizations/:orgslug/explore/traces/):** + +- "Which aggregation queries are slowest?" Group by `query.type`, sort by `p90(span.duration)` +- "Does date range affect performance?" Filter by name, group by `query.dateRange` + +### 4. Background Jobs + +Jobs run outside of request context. Custom spans make them visible. + +```javascript {tabTitle: JavaScript} +async function processEmailDigest(job) { + return Sentry.startSpan( + { name: `job:${job.type}`, op: "queue.process" }, + async (span) => { + span.setAttribute("job.id", job.id); + span.setAttribute("job.type", "email-digest"); + span.setAttribute("queue.name", "notifications"); + + const users = await getDigestRecipients(); + span.setAttribute("job.recipientCount", users.length); + + for (const user of users) { + await sendDigest(user); + } + + span.setAttribute("job.status", "completed"); + } + ); +} +``` + +```python {tabTitle: Python} +import sentry_sdk + +def process_email_digest(job): + with sentry_sdk.start_span(name=f"job:{job.type}", op="queue.process") as span: + span.set_data("job.id", job.id) + span.set_data("job.type", "email-digest") + span.set_data("queue.name", "notifications") + + users = get_digest_recipients() + span.set_data("job.recipientCount", len(users)) + + for user in users: + send_digest(user) + + span.set_data("job.status", "completed") +``` + +```php {tabTitle: PHP} +public function processEmailDigest($job) +{ + $spanContext = \Sentry\Tracing\SpanContext::make() + ->setOp('queue.process') + ->setDescription("job:{$job->type}") + ->setData([ + 'job.id' => $job->id, + 'job.type' => 'email-digest', + 'queue.name' => 'notifications', + ]); + + \Sentry\trace(function () use ($job) { + $users = $this->getDigestRecipients(); + + $span = \Sentry\SentrySdk::getCurrentHub()->getSpan(); + $span->setData(['job.recipientCount' => count($users)]); + + foreach ($users as $user) { + $this->sendDigest($user); + } + + $span->setData(['job.status' => 'completed']); + }, $spanContext); +} +``` + +```csharp {tabTitle: .NET} +public async Task ProcessEmailDigest(Job job) +{ + var transaction = SentrySdk.StartTransaction($"job:{job.Type}", "queue.process"); + SentrySdk.ConfigureScope(scope => scope.Transaction = transaction); + + transaction.SetExtra("job.id", job.Id); + transaction.SetExtra("job.type", "email-digest"); + transaction.SetExtra("queue.name", "notifications"); + + var users = await GetDigestRecipients(); + transaction.SetExtra("job.recipientCount", users.Count); + + foreach (var user in users) + { + await SendDigest(user); + } + + transaction.SetExtra("job.status", "completed"); + transaction.Finish(); +} +``` + +```ruby {tabTitle: Ruby} +def process_email_digest(job) + Sentry.with_child_span(op: 'queue.process', description: "job:#{job.type}") do |span| + span.set_data('job.id', job.id) + span.set_data('job.type', 'email-digest') + span.set_data('queue.name', 'notifications') + + users = get_digest_recipients + span.set_data('job.recipientCount', users.length) + + users.each { |user| send_digest(user) } + + span.set_data('job.status', 'completed') + end +end +``` + +```dart {tabTitle: Flutter} +Future processEmailDigest(Job job) async { + final transaction = Sentry.startTransaction('job:${job.type}', 'queue.process'); + transaction.setData('job.id', job.id); + transaction.setData('job.type', 'email-digest'); + transaction.setData('queue.name', 'notifications'); + + final users = await getDigestRecipients(); + transaction.setData('job.recipientCount', users.length); + + for (final user in users) { + await sendDigest(user); + } + + transaction.setData('job.status', 'completed'); + await transaction.finish(); +} +``` + +```swift {tabTitle: Swift} +import Sentry + +func processEmailDigest(job: Job) { + let transaction = SentrySDK.startTransaction(name: "job:\(job.type)", operation: "queue.process") + transaction.setData(value: job.id, key: "job.id") + transaction.setData(value: "email-digest", key: "job.type") + transaction.setData(value: "notifications", key: "queue.name") + + let users = getDigestRecipients() + transaction.setData(value: users.count, key: "job.recipientCount") + + for user in users { + sendDigest(to: user) + } + + transaction.setData(value: "completed", key: "job.status") + transaction.finish() +} +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +fun processEmailDigest(job: Job) { + val transaction = Sentry.startTransaction("job:${job.type}", "queue.process") + transaction.setData("job.id", job.id) + transaction.setData("job.type", "email-digest") + transaction.setData("queue.name", "notifications") + + val users = getDigestRecipients() + transaction.setData("job.recipientCount", users.size) + + users.forEach { user -> + sendDigest(user) + } + + transaction.setData("job.status", "completed") + transaction.finish() +} +``` + +**Query in [Explore > Traces](https://sentry.io/orgredirect/organizations/:orgslug/explore/traces/):** `span.op:queue.process` grouped by `job.type`, visualize `p90(span.duration)`. + +**Alert idea:** `p90(span.duration) > 60s` for queue processing. + +### 5. AI/LLM Operations + +For AI workloads, use [Sentry Agent Monitoring](/product/insights/ai/agents/) instead of manual instrumentation when possible. It automatically captures agent workflows, tool calls, and token usage. + +If you're not using a supported framework or need custom attributes: + +```javascript {tabTitle: JavaScript} +Sentry.startSpan( + { name: "generate-summary", op: "ai.inference" }, + async (span) => { + span.setAttribute("ai.model", "gpt-4"); + span.setAttribute("ai.feature", "document-summary"); + + const response = await openai.chat.completions.create({...}); + + span.setAttribute("ai.tokens.total", response.usage.total_tokens); + return response; + } +); +``` + +```python {tabTitle: Python} +import sentry_sdk + +with sentry_sdk.start_span(name="generate-summary", op="ai.inference") as span: + span.set_data("ai.model", "gpt-4") + span.set_data("ai.feature", "document-summary") + + response = openai.chat.completions.create(...) + + span.set_data("ai.tokens.total", response.usage.total_tokens) +``` + +```php {tabTitle: PHP} +$spanContext = \Sentry\Tracing\SpanContext::make() + ->setOp('ai.inference') + ->setDescription('generate-summary') + ->setData([ + 'ai.model' => 'gpt-4', + 'ai.feature' => 'document-summary', + ]); + +$response = \Sentry\trace(function () { + $response = $this->openai->chat()->completions()->create([...]); + + $span = \Sentry\SentrySdk::getCurrentHub()->getSpan(); + $span->setData(['ai.tokens.total' => $response->usage->totalTokens]); + + return $response; +}, $spanContext); +``` + +```csharp {tabTitle: .NET} +var transaction = SentrySdk.StartTransaction("generate-summary", "ai.inference"); +SentrySdk.ConfigureScope(scope => scope.Transaction = transaction); + +transaction.SetExtra("ai.model", "gpt-4"); +transaction.SetExtra("ai.feature", "document-summary"); + +var response = await openai.ChatCompletion.CreateAsync(...); + +transaction.SetExtra("ai.tokens.total", response.Usage.TotalTokens); +transaction.Finish(); +``` + +```ruby {tabTitle: Ruby} +Sentry.with_child_span(op: 'ai.inference', description: 'generate-summary') do |span| + span.set_data('ai.model', 'gpt-4') + span.set_data('ai.feature', 'document-summary') + + response = openai.chat(...) + + span.set_data('ai.tokens.total', response.dig('usage', 'total_tokens')) +end +``` + +```dart {tabTitle: Flutter} +final transaction = Sentry.startTransaction('generate-summary', 'ai.inference'); +transaction.setData('ai.model', 'gpt-4'); +transaction.setData('ai.feature', 'document-summary'); + +final response = await openai.chat.completions.create(...); + +transaction.setData('ai.tokens.total', response.usage.totalTokens); +await transaction.finish(); +``` + +```swift {tabTitle: Swift} +import Sentry + +let transaction = SentrySDK.startTransaction(name: "generate-summary", operation: "ai.inference") +transaction.setData(value: "gpt-4", key: "ai.model") +transaction.setData(value: "document-summary", key: "ai.feature") + +let response = try await openai.chat.completions.create(...) + +transaction.setData(value: response.usage.totalTokens, key: "ai.tokens.total") +transaction.finish() +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +val transaction = Sentry.startTransaction("generate-summary", "ai.inference") +transaction.setData("ai.model", "gpt-4") +transaction.setData("ai.feature", "document-summary") + +val response = openai.chat.completions.create(...) + +transaction.setData("ai.tokens.total", response.usage.totalTokens) +transaction.finish() +``` + +**Alert idea:** `p95(span.duration) > 5s` for AI inference. + +## Quick Reference + +| Category | `op` Value | Example Attributes | +| --------------- | --------------- | ---------------------------- | +| User flows | `user.action` | cart.itemCount, user.tier | +| External APIs | `http.client` | http.url, response.timeMs | +| Database | `db.query` | query.type, result.rowCount | +| Background jobs | `queue.process` | job.type, job.id, queue.name | +| AI/LLM | `ai.inference` | ai.model, ai.tokens.total | + +## Next Steps + +Explore the [product walkthrough guides](/product/) to learn more about the Sentry interface and discover additional tips. diff --git a/docs/guides/index.mdx b/docs/guides/index.mdx new file mode 100644 index 00000000000000..e1499b3c891902 --- /dev/null +++ b/docs/guides/index.mdx @@ -0,0 +1,11 @@ +--- +title: Guides +sidebar_order: 15 +description: "Practical guidance on what to instrument, what to query, and how to get value from Sentry after setup." +--- + +You've set up Sentry. Now what? + +These guides help you move from "Sentry is configured" to "Sentry is helping me find and fix problems." Each covers what to instrument, what queries to run, and what alerts to create. + + diff --git a/docs/guides/issues-errors.mdx b/docs/guides/issues-errors.mdx new file mode 100644 index 00000000000000..27f87685e825f8 --- /dev/null +++ b/docs/guides/issues-errors.mdx @@ -0,0 +1,643 @@ +--- +title: "What to Watch" +sidebar_order: 5 +description: "Practical guidance on what errors to catch, how to search issues, and when to set alerts." +--- + +Your Sentry SDK is sending errors to [Sentry Issues](/product/issues/) out of the box. Now what? This guide covers the high-value error patterns that help you catch problems before they impact users and fix issues faster. + +## Anatomy of an Error + +Sentry automatically captures unhandled errors. For handled errors, use `captureException()` and add context: + +```javascript {tabTitle: JavaScript} +try { + await processOrder(order); +} catch (error) { + Sentry.captureException(error, { + tags: { + order_id: order.id, + payment_method: order.paymentMethod, + }, + level: "error", + }); + throw error; +} +``` + +```python {tabTitle: Python} +import sentry_sdk + +try: + process_order(order) +except Exception as e: + sentry_sdk.capture_exception(e) + sentry_sdk.set_tag("order_id", order.id) + sentry_sdk.set_tag("payment_method", order.payment_method) + raise +``` + +```php {tabTitle: PHP} +try { + $this->processOrder($order); +} catch (\Throwable $exception) { + \Sentry\configureScope(function (\Sentry\State\Scope $scope) use ($order): void { + $scope->setTag('order_id', $order->id); + $scope->setTag('payment_method', $order->paymentMethod); + }); + \Sentry\captureException($exception); + throw $exception; +} +``` + +```csharp {tabTitle: .NET} +try +{ + await ProcessOrder(order); +} +catch (Exception ex) +{ + SentrySdk.ConfigureScope(scope => + { + scope.SetTag("order_id", order.Id); + scope.SetTag("payment_method", order.PaymentMethod); + }); + SentrySdk.CaptureException(ex); + throw; +} +``` + +```ruby {tabTitle: Ruby} +begin + process_order(order) +rescue => e + Sentry.set_tags(order_id: order.id, payment_method: order.payment_method) + Sentry.capture_exception(e) + raise +end +``` + +```dart {tabTitle: Flutter} +try { + await processOrder(order); +} catch (error, stackTrace) { + Sentry.configureScope((scope) { + scope.setTag('order_id', order.id); + scope.setTag('payment_method', order.paymentMethod); + }); + await Sentry.captureException(error, stackTrace: stackTrace); + rethrow; +} +``` + +```swift {tabTitle: Swift} +import Sentry + +do { + try processOrder(order) +} catch { + SentrySDK.configureScope { scope in + scope.setTag(value: order.id, key: "order_id") + scope.setTag(value: order.paymentMethod, key: "payment_method") + } + SentrySDK.capture(error: error) + throw error +} +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +try { + processOrder(order) +} catch (e: Exception) { + Sentry.configureScope { scope -> + scope.setTag("order_id", order.id) + scope.setTag("payment_method", order.paymentMethod) + } + Sentry.captureException(e) + throw e +} +``` + +**Levels:** `fatal`, `error`, `warning`, `info`, `debug` + +**Context:** Tags, user info, logs, and session replays help you debug faster. Tags are searchable, so use them for high-cardinality data like IDs, regions, and feature flags. + +Every error in Sentry is automatically trace-connected. Click the trace ID to see the full [trace view](/concepts/key-terms/tracing/#traces-to-trace-view) and understand what led to the error. + +## Where to Look + +Start by creating these five [Issue views](https://sentry.io/orgredirect/organizations/:orgslug/issues/) to catch the most critical problems. + +**Save these views**: Turn these five searches into saved Issues views by clicking **Save As** after setting each filter. + +### 1. Unresolved High-Volume Issues + +High event counts mean either many users are affected or one user is stuck in a loop. Both need immediate attention. + +**[In Issues](https://sentry.io/orgredirect/organizations/:orgslug/issues/):** Search for `is:unresolved` (applied by default) and use the sort dropdown (defaults to "Last Seen") to sort by **Events** + +**What to look for:** + +- Issues at the top with high event counts (many occurrences in a short time) +- Click into these issues to see the stack trace and how many users are affected + +Learn more about [Issue States & Triage](/product/issues/states-triage/) to manage and prioritize issues. + +**Alert idea:** Trigger when event count spikes in a short time window to catch high-impact bugs and infinite loops. + +### 2. New Issues After Deploy + +Every deploy introduces risk. New errors that appear right after a release are usually regressions. + +**[In Issues](https://sentry.io/orgredirect/organizations/:orgslug/issues/):** Filter by `is:unresolved firstRelease:v1.2.3` to find issues introduced in a specific release. Sort by **Age** to see the newest issues first. + +**What to look for:** + +- Issues that didn't exist in the previous release +- Errors in code paths you just changed +- New error types (TypeError, ReferenceError) indicating breaking changes + +Learn more about [Release Health](/product/releases/health/) to track error rates and crash-free sessions per release. + +**Alert idea:** Trigger when a new issue is created, filtered to production environment and error/fatal level. This catches regressions immediately after deploy. + +### 3. Errors by Environment + +Production errors are critical. Staging errors help you catch problems before they reach users. Comparing environments helps you spot configuration issues. + +**[In Issues](https://sentry.io/orgredirect/organizations/:orgslug/issues/):** Search for `is:unresolved environment:production` or `environment:staging` + +**What to look for:** + +- Errors only in production (often config, API keys, or data issues) +- Errors only in staging (caught before deploy, needs fixing) +- Same error in both (systemic code issue) + +Learn more about configuring environments to separate production and staging issues. + +**Alert idea:** Trigger when a new issue is created, filtered to production environment. These often indicate config drift or environment-specific bugs. + +### 4. Errors with High User Impact + +Some errors heavily affect power users. Others affect everyone, but rarely. Prioritize by unique user count, not just event count. + +**[In Issues](https://sentry.io/orgredirect/organizations/:orgslug/issues/):** Search for `is:unresolved` and use the sort dropdown to sort by **Users** + +**What to look for:** + +- Issues affecting many unique users (e.g., more than 10 users indicates widespread impact) +- Issues affecting VIP or paying users (check user tags) +- Issues blocking core workflows (login, checkout, data access) + +Learn more about custom tags to mark user tiers, plans, or roles. Then search `is:unresolved user.tier:enterprise` to prioritize high-value users. + +**Alert idea:** Trigger when unique user count exceeds a threshold in a time window (e.g., more than 50 users in 1 hour) to catch widespread issues. + +### 5. User-Reported Issues + +When users report problems, they often see an error. User feedback tells you which errors hurt the experience most, even if event counts are low. + +Enable the [User Feedback Widget](/platforms/javascript/user-feedback/) to let users report problems directly when errors happen. + +**[In Issues](https://sentry.io/orgredirect/organizations/:orgslug/issues/):** Navigate to **User Feedback** in the left sidebar to see reports submitted by users. + +**What to look for:** + +- User descriptions of what they were doing when the error occurred +- Patterns in feedback about specific workflows or features +- Issues that frustrate users even if they don't generate many events + +**Alert idea:** Trigger when a new issue is created, filtered to issue category equals feedback. This ensures you respond quickly when users report problems. + +## Error Handling Strategy + +### Capture Context, Not Just Exceptions + +When you catch an error, add tags and context to make debugging instant. Set user info globally so it applies to all events. Enable [Session Replays](/product/explore/session-replay/) and [Logs](/product/explore/logs/) for even more visibility. + +```javascript {tabTitle: JavaScript} +// Set user globally (e.g., after login) +Sentry.setUser({ id: user.id, email: user.email }); + +// Add tags and context per-event +Sentry.captureException(error, { + tags: { + order_id: order.id, + payment_gateway: "stripe", + region: user.region, + }, + contexts: { + order: { + total: order.total, + items: order.items.length, + discount_code: order.discountCode, + }, + }, +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +# Set user globally (e.g., after login) +sentry_sdk.set_user({"id": user.id, "email": user.email}) + +# Add tags and context per-event +sentry_sdk.set_tags({ + "order_id": order.id, + "payment_gateway": "stripe", + "region": user.region +}) +sentry_sdk.set_context("order", { + "total": order.total, + "items": len(order.items), + "discount_code": order.discount_code +}) +sentry_sdk.capture_exception(error) +``` + +```php {tabTitle: PHP} +// Set user globally (e.g., after login) +\Sentry\configureScope(function (\Sentry\State\Scope $scope) use ($user): void { + $scope->setUser(['id' => $user->id, 'email' => $user->email]); +}); + +// Add tags and context per-event +\Sentry\configureScope(function (\Sentry\State\Scope $scope) use ($order, $user): void { + $scope->setTag('order_id', $order->id); + $scope->setTag('payment_gateway', 'stripe'); + $scope->setTag('region', $user->region); + $scope->setContext('order', [ + 'total' => $order->total, + 'items' => count($order->items), + 'discount_code' => $order->discountCode + ]); +}); +\Sentry\captureException($error); +``` + +```csharp {tabTitle: .NET} +// Set user globally (e.g., after login) +SentrySdk.ConfigureScope(scope => +{ + scope.User = new SentryUser { Id = user.Id, Email = user.Email }; +}); + +// Add tags and context per-event +SentrySdk.ConfigureScope(scope => +{ + scope.SetTag("order_id", order.Id); + scope.SetTag("payment_gateway", "stripe"); + scope.SetTag("region", user.Region); + scope.Contexts["order"] = new + { + total = order.Total, + items = order.Items.Count, + discount_code = order.DiscountCode + }; +}); +SentrySdk.CaptureException(error); +``` + +```ruby {tabTitle: Ruby} +# Set user globally (e.g., after login) +Sentry.set_user(id: user.id, email: user.email) + +# Add tags and context per-event +Sentry.set_tags( + order_id: order.id, + payment_gateway: 'stripe', + region: user.region +) +Sentry.set_context('order', { + total: order.total, + items: order.items.length, + discount_code: order.discount_code +}) +Sentry.capture_exception(error) +``` + +```dart {tabTitle: Flutter} +// Set user globally (e.g., after login) +Sentry.configureScope((scope) { + scope.setUser(SentryUser(id: user.id, email: user.email)); +}); + +// Add tags and context per-event +Sentry.configureScope((scope) { + scope.setTag('order_id', order.id); + scope.setTag('payment_gateway', 'stripe'); + scope.setTag('region', user.region); + scope.setContexts('order', { + 'total': order.total, + 'items': order.items.length, + 'discount_code': order.discountCode, + }); +}); +await Sentry.captureException(error); +``` + +```swift {tabTitle: Swift} +import Sentry + +// Set user globally (e.g., after login) +let sentryUser = User() +sentryUser.userId = user.id +sentryUser.email = user.email +SentrySDK.setUser(sentryUser) + +// Add tags and context per-event +SentrySDK.configureScope { scope in + scope.setTag(value: order.id, key: "order_id") + scope.setTag(value: "stripe", key: "payment_gateway") + scope.setTag(value: user.region, key: "region") + scope.setContext(value: [ + "total": order.total, + "items": order.items.count, + "discount_code": order.discountCode + ], key: "order") +} +SentrySDK.capture(error: error) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry +import io.sentry.protocol.User + +// Set user globally (e.g., after login) +Sentry.setUser(User().apply { + id = user.id + email = user.email +}) + +// Add tags and context per-event +Sentry.configureScope { scope -> + scope.setTag("order_id", order.id) + scope.setTag("payment_gateway", "stripe") + scope.setTag("region", user.region) + scope.setContexts("order.total", order.total) + scope.setContexts("order.items", order.items.size) + scope.setContexts("order.discount_code", order.discountCode) +} +Sentry.captureException(error) +``` + +**Search in Sentry:** `order_id:order_123` or `payment_gateway:stripe region:us-west` + +### Ignore Known Noise + +Some errors aren't actionable. Use ignoreErrors to filter them out. + +```javascript {tabTitle: JavaScript} +Sentry.init({ + dsn: "...", + ignoreErrors: [ + "Non-Error promise rejection captured", + /^Timeout of \d+ms exceeded$/, + ], +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +sentry_sdk.init( + dsn="...", + ignore_errors=[ + ValueError, + ConnectionError, + ] +) +``` + +```php {tabTitle: PHP} +\Sentry\init([ + 'dsn' => '...', + 'ignore_exceptions' => [ + \RuntimeException::class, + ], +]); +``` + +```csharp {tabTitle: .NET} +SentrySdk.Init(options => +{ + options.Dsn = "..."; + options.SetBeforeSend((sentryEvent, hint) => + { + // Filter out specific error types + if (sentryEvent.Exception is NetworkException) + { + return null; + } + return sentryEvent; + }); +}); +``` + +```ruby {tabTitle: Ruby} +Sentry.init do |config| + config.dsn = '...' + config.before_send = lambda do |event, hint| + # Filter out specific error types + if hint[:exception].is_a?(NetworkError) + nil + else + event + end + end +end +``` + +```dart {tabTitle: Flutter} +await SentryFlutter.init( + (options) { + options.dsn = '...'; + options.beforeSend = (event, hint) { + // Filter out specific error types + if (event.exceptions?.any((e) => e.type == 'NetworkException') ?? false) { + return null; + } + return event; + }; + }, + appRunner: () => runApp(MyApp()), +); +``` + +```swift {tabTitle: Swift} +import Sentry + +SentrySDK.start { options in + options.dsn = "..." + options.beforeSend = { event in + // Filter out specific error types + if let exceptions = event.exceptions, + exceptions.contains(where: { $0.type == "NetworkError" }) { + return nil + } + return event + } +} +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.android.core.SentryAndroid +import io.sentry.SentryOptions.BeforeSendCallback + +SentryAndroid.init(context) { options -> + options.dsn = "..." + options.beforeSend = BeforeSendCallback { event, hint -> + // Filter out specific error types + if (event.exceptions?.any { it.type == "NetworkException" } == true) { + null + } else { + event + } + } +} +``` + +You can also use beforeSend to filter errors dynamically: + +```javascript {tabTitle: JavaScript} +Sentry.init({ + beforeSend(event, hint) { + // Ignore errors from browser extensions + if ( + event.exception?.values?.[0]?.stacktrace?.frames?.some((frame) => + frame.filename?.includes("chrome-extension://") + ) + ) { + return null; + } + return event; + }, +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +def before_send(event, hint): + # Ignore specific error types + if "exc_info" in hint: + exc_type, exc_value, tb = hint["exc_info"] + if isinstance(exc_value, KeyboardInterrupt): + return None + return event + +sentry_sdk.init( + dsn="...", + before_send=before_send +) +``` + +```php {tabTitle: PHP} +\Sentry\init([ + 'dsn' => '...', + 'before_send' => function (\Sentry\Event $event, ?\Sentry\EventHint $hint): ?\Sentry\Event { + // Ignore specific error types + if ($hint !== null && $hint->exception instanceof \RuntimeException) { + return null; + } + return $event; + }, +]); +``` + +```csharp {tabTitle: .NET} +SentrySdk.Init(options => +{ + options.Dsn = "..."; + options.SetBeforeSend((sentryEvent, hint) => + { + // Ignore specific error types + if (sentryEvent.Exception is InvalidOperationException) + { + return null; + } + return sentryEvent; + }); +}); +``` + +```ruby {tabTitle: Ruby} +Sentry.init do |config| + config.dsn = '...' + config.before_send = lambda do |event, hint| + # Ignore specific error types + if hint[:exception].is_a?(ArgumentError) + nil + else + event + end + end +end +``` + +```dart {tabTitle: Flutter} +await SentryFlutter.init( + (options) { + options.dsn = '...'; + options.beforeSend = (event, hint) { + // Ignore specific error types + final exception = hint?.exception; + if (exception is StateError) { + return null; + } + return event; + }; + }, + appRunner: () => runApp(MyApp()), +); +``` + +```swift {tabTitle: Swift} +import Sentry + +SentrySDK.start { options in + options.dsn = "..." + options.beforeSend = { event in + // Ignore specific error types + if let error = event.error as NSError?, + error.domain == "MyAppErrorDomain" { + return nil + } + return event + } +} +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.android.core.SentryAndroid +import io.sentry.SentryOptions.BeforeSendCallback + +SentryAndroid.init(context) { options -> + options.dsn = "..." + options.beforeSend = BeforeSendCallback { event, hint -> + // Ignore specific error types + val throwable = hint.originalThrowable + if (throwable is IllegalStateException) { + null + } else { + event + } + } +} +``` + +## Quick Reference + +| View | Search Query | Look For | +| ------------------ | -------------------------------- | ------------------------------------- | +| High-volume issues | `is:unresolved` (sort by Events) | High event counts, post-deploy spikes | +| New regressions | `is:unresolved` (sort by Age) | Issues that first appeared recently | +| Environment issues | `environment:production` | Prod-only config or data issues | +| High user impact | `is:unresolved` (sort by Users) | Issues affecting many users | + +## Next Steps + +Explore the [product walkthrough guides](/product/) to learn more about the Sentry interface and discover additional tips. diff --git a/docs/guides/logs.mdx b/docs/guides/logs.mdx new file mode 100644 index 00000000000000..da80fcb0c747cf --- /dev/null +++ b/docs/guides/logs.mdx @@ -0,0 +1,1081 @@ +--- +title: "What to Log" +sidebar_order: 10 +description: "Practical guidance on what to log, how to search logs, and when to set alerts." +--- + +You've set up [Sentry Logs](/product/explore/logs/). Now what? This guide covers the high-value logging patterns that help you debug faster and catch problems before users report them. + +## Anatomy of a Log + +Every structured log follows the same format: + +```javascript {tabTitle: JavaScript} +Sentry.logger.(message, { attributes }); +``` + +```python {tabTitle: Python} +from sentry_sdk import logger +logger.(message, attribute=value) +``` + +```php {tabTitle: PHP} +\Sentry\logger()->(message, attributes: [...]); +``` + +```csharp {tabTitle: .NET} +using Sentry; +SentrySdk.Logger.(message); +``` + +Logs in Sentry are automatically trace-connected. Each log shows a trace ID that links to the full [trace view](/concepts/key-terms/tracing/#traces-to-trace-view). + +```ruby {tabTitle: Ruby} +Sentry.logger.(message) +``` + +```dart {tabTitle: Flutter} +import 'package:sentry/sentry.dart'; +Sentry.logger.(message); +``` + +```swift {tabTitle: Swift} +import Sentry +SentrySDK.logger.(message, attributes: [...]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry +Sentry.logger().(message) +``` + +**Levels:** `trace`, `debug`, `info`, `warn` (or `warning` in Python), `error`, `fatal` + +**Attributes:** Key-value pairs you can search and filter on. Consistency matters, so use whatever naming convention fits your codebase. + +```javascript {tabTitle: JavaScript} +Sentry.logger.info("Order completed", { + orderId: "order_123", + userId: user.id, + amount: 149.99, + paymentMethod: "stripe", +}); +``` + +```python {tabTitle: Python} +from sentry_sdk import logger as sentry_logger + +sentry_logger.info("Order completed", + order_id="order_123", + user_id=user.id, + amount=149.99, + payment_method="stripe" +) +``` + +```php {tabTitle: PHP} +\Sentry\logger()->info('Order completed', attributes: [ + 'order_id' => 'order_123', + 'user_id' => $user->id, + 'amount' => 149.99, + 'payment_method' => 'stripe', +]); +``` + +```csharp {tabTitle: .NET} +using Sentry; + +SentrySdk.Logger.Info("Order completed", logger => logger + .SetAttribute("orderId", "order_123") + .SetAttribute("userId", user.Id) + .SetAttribute("amount", 149.99) + .SetAttribute("paymentMethod", "stripe")); +``` + +```ruby {tabTitle: Ruby} +Sentry.logger.info('Order completed', + order_id: 'order_123', + user_id: user.id, + amount: 149.99, + payment_method: 'stripe' +) +``` + +```dart {tabTitle: Flutter} +Sentry.logger.info('Order completed', attributes: { + 'orderId': 'order_123', + 'userId': user.id, + 'amount': 149.99, + 'paymentMethod': 'stripe', +}); +``` + +```swift {tabTitle: Swift} +import Sentry + +SentrySDK.logger.info("Order completed", attributes: [ + "orderId": "order_123", + "userId": user.id, + "amount": 149.99, + "paymentMethod": "stripe" +]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +Sentry.logger().info("Order completed orderId=%s userId=%s amount=%.2f", + "order_123", user.id, 149.99) +``` + +Logs in Sentry are automatically trace-connected. Each log shows a trace ID that links to the full [trace view](/concepts/key-terms/tracing/trace-view/). + +## Where to Add Logs + +Start with these five areas and you'll catch most issues before users do. + +### 1. Authentication Events + +Login flows are invisible until something breaks. Log successes and failures to spot patterns like brute force attempts, OAuth misconfigurations, or MFA issues. + +```javascript {tabTitle: JavaScript} +// After successful authentication +Sentry.logger.info("User logged in", { + userId: user.id, + authMethod: "oauth", + provider: "google", +}); + +// After authentication fails +Sentry.logger.warn("Login failed", { + email: maskedEmail, + reason: "invalid_password", + attemptCount: 3, +}); +``` + +```python {tabTitle: Python} +from sentry_sdk import logger as sentry_logger + +# After successful authentication +sentry_logger.info("User logged in", + user_id=user.id, + auth_method="oauth", + provider="google" +) + +# After authentication fails +sentry_logger.warning("Login failed", + email=masked_email, + reason="invalid_password", + attempt_count=3 +) +``` + +```php {tabTitle: PHP} +// After successful authentication +\Sentry\logger()->info('User logged in', attributes: [ + 'user_id' => $user->id, + 'auth_method' => 'oauth', + 'provider' => 'google', +]); + +// After authentication fails +\Sentry\logger()->warn('Login failed', attributes: [ + 'email' => $maskedEmail, + 'reason' => 'invalid_password', + 'attempt_count' => 3, +]); +``` + +```csharp {tabTitle: .NET} +// After successful authentication +SentrySdk.Logger.Info("User logged in", logger => logger + .SetAttribute("userId", user.Id) + .SetAttribute("authMethod", "oauth") + .SetAttribute("provider", "google")); + +// After authentication fails +SentrySdk.Logger.Warning("Login failed", logger => logger + .SetAttribute("email", maskedEmail) + .SetAttribute("reason", "invalid_password") + .SetAttribute("attemptCount", 3)); +``` + +```ruby {tabTitle: Ruby} +# After successful authentication +Sentry.logger.info('User logged in', + user_id: user.id, + auth_method: 'oauth', + provider: 'google' +) + +# After authentication fails +Sentry.logger.warn('Login failed', + email: masked_email, + reason: 'invalid_password', + attempt_count: 3 +) +``` + +```dart {tabTitle: Flutter} +// After successful authentication +Sentry.logger.info('User logged in', attributes: { + 'userId': user.id, + 'authMethod': 'oauth', + 'provider': 'google', +}); + +// After authentication fails +Sentry.logger.warn('Login failed', attributes: { + 'email': maskedEmail, + 'reason': 'invalid_password', + 'attemptCount': 3, +}); +``` + +```swift {tabTitle: Swift} +import Sentry + +// After successful authentication +SentrySDK.logger.info("User logged in", attributes: [ + "userId": user.id, + "authMethod": "oauth", + "provider": "google" +]) + +// After authentication fails +SentrySDK.logger.warn("Login failed", attributes: [ + "email": maskedEmail, + "reason": "invalid_password", + "attemptCount": 3 +]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +// After successful authentication +Sentry.logger().info("User logged in userId=%s authMethod=%s", user.id, "oauth") + +// After authentication fails +Sentry.logger().warn("Login failed email=%s reason=%s", maskedEmail, "invalid_password") +``` + +**Query in [Explore > Logs](https://sentry.io/orgredirect/organizations/:orgslug/explore/logs/):** `userId:123 "logged in"` or `severity:warn authMethod:*` + +**Alert idea:** Alert when `severity:warn "Login failed"` spikes in a 5-minute window—this can indicate brute force attempts or auth provider issues. + +### 2. Payment and Checkout + +Money paths need visibility even when they succeed. When payments fail, you need context fast. + +```javascript {tabTitle: JavaScript} +// After payment gateway returns an error +Sentry.logger.error("Payment failed", { + orderId: "order_123", + amount: 99.99, + gateway: "stripe", + errorCode: "card_declined", + cartItems: 3, +}); +``` + +```python {tabTitle: Python} +from sentry_sdk import logger as sentry_logger + +# After payment gateway returns an error +sentry_logger.error("Payment failed", + order_id="order_123", + amount=99.99, + gateway="stripe", + error_code="card_declined", + cart_items=3 +) +``` + +```php {tabTitle: PHP} +// After payment gateway returns an error +\Sentry\logger()->error('Payment failed', attributes: [ + 'order_id' => 'order_123', + 'amount' => 99.99, + 'gateway' => 'stripe', + 'error_code' => 'card_declined', + 'cart_items' => 3, +]); +``` + +```csharp {tabTitle: .NET} +// After payment gateway returns an error +SentrySdk.Logger.Error("Payment failed", logger => logger + .SetAttribute("orderId", "order_123") + .SetAttribute("amount", 99.99) + .SetAttribute("gateway", "stripe") + .SetAttribute("errorCode", "card_declined") + .SetAttribute("cartItems", 3)); +``` + +```ruby {tabTitle: Ruby} +# After payment gateway returns an error +Sentry.logger.error('Payment failed', + order_id: 'order_123', + amount: 99.99, + gateway: 'stripe', + error_code: 'card_declined', + cart_items: 3 +) +``` + +```dart {tabTitle: Flutter} +// After payment gateway returns an error +Sentry.logger.error('Payment failed', attributes: { + 'orderId': 'order_123', + 'amount': 99.99, + 'gateway': 'stripe', + 'errorCode': 'card_declined', + 'cartItems': 3, +}); +``` + +```swift {tabTitle: Swift} +import Sentry + +// After payment gateway returns an error +SentrySDK.logger.error("Payment failed", attributes: [ + "orderId": "order_123", + "amount": 99.99, + "gateway": "stripe", + "errorCode": "card_declined", + "cartItems": 3 +]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +// After payment gateway returns an error +Sentry.logger().error("Payment failed orderId=%s gateway=%s errorCode=%s", + "order_123", "stripe", "card_declined") +``` + +**Query in [Explore > Logs](https://sentry.io/orgredirect/organizations/:orgslug/explore/logs/):** `orderId:order_123` or `severity:error gateway:stripe` + +**Alert idea:** Alert when `severity:error gateway:*` spikes—this can indicate payment provider outages. + +### 3. External APIs and Async Operations + +Traces capture what your code does. Logs capture context about external triggers and async boundaries. These are things like webhooks, scheduled tasks, and third-party API responses that traces can't automatically instrument. + +```javascript {tabTitle: JavaScript} +// Third-party API call +const start = Date.now(); +const response = await shippingApi.getRates(items); + +Sentry.logger.info("Shipping rates fetched", { + service: "shipping-provider", + endpoint: "/rates", + durationMs: Date.now() - start, + rateCount: response.rates.length, +}); + +// Webhook received +Sentry.logger.info("Webhook received", { + source: "stripe", + eventType: "payment_intent.succeeded", + paymentId: event.data.object.id, +}); +``` + +```python {tabTitle: Python} +import time +from sentry_sdk import logger as sentry_logger + +# Third-party API call +start = time.time() +response = shipping_api.get_rates(items) + +sentry_logger.info("Shipping rates fetched", + service="shipping-provider", + endpoint="/rates", + duration_ms=int((time.time() - start) * 1000), + rate_count=len(response.rates) +) + +# Webhook received +sentry_logger.info("Webhook received", + source="stripe", + event_type="payment_intent.succeeded", + payment_id=event["data"]["object"]["id"] +) +``` + +```php {tabTitle: PHP} +// Third-party API call +$start = microtime(true); +$response = $shippingApi->getRates($items); + +\Sentry\logger()->info('Shipping rates fetched', attributes: [ + 'service' => 'shipping-provider', + 'endpoint' => '/rates', + 'duration_ms' => (int)((microtime(true) - $start) * 1000), + 'rate_count' => count($response->rates), +]); + +// Webhook received +\Sentry\logger()->info('Webhook received', attributes: [ + 'source' => 'stripe', + 'event_type' => 'payment_intent.succeeded', + 'payment_id' => $event['data']['object']['id'], +]); +``` + +```csharp {tabTitle: .NET} +// Third-party API call +var stopwatch = Stopwatch.StartNew(); +var response = await shippingApi.GetRatesAsync(items); + +SentrySdk.Logger.Info("Shipping rates fetched", logger => logger + .SetAttribute("service", "shipping-provider") + .SetAttribute("endpoint", "/rates") + .SetAttribute("durationMs", stopwatch.ElapsedMilliseconds) + .SetAttribute("rateCount", response.Rates.Count)); + +// Webhook received +SentrySdk.Logger.Info("Webhook received", logger => logger + .SetAttribute("source", "stripe") + .SetAttribute("eventType", "payment_intent.succeeded") + .SetAttribute("paymentId", eventData.Object.Id)); +``` + +```ruby {tabTitle: Ruby} +# Third-party API call +start = Process.clock_gettime(Process::CLOCK_MONOTONIC) +response = shipping_api.get_rates(items) + +Sentry.logger.info('Shipping rates fetched', + service: 'shipping-provider', + endpoint: '/rates', + duration_ms: ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).to_i, + rate_count: response.rates.length +) + +# Webhook received +Sentry.logger.info('Webhook received', + source: 'stripe', + event_type: 'payment_intent.succeeded', + payment_id: event['data']['object']['id'] +) +``` + +```dart {tabTitle: Flutter} +// Third-party API call +final stopwatch = Stopwatch()..start(); +final response = await shippingApi.getRates(items); + +Sentry.logger.info('Shipping rates fetched', attributes: { + 'service': 'shipping-provider', + 'endpoint': '/rates', + 'durationMs': stopwatch.elapsedMilliseconds, + 'rateCount': response.rates.length, +}); + +// Webhook received +Sentry.logger.info('Webhook received', attributes: { + 'source': 'stripe', + 'eventType': 'payment_intent.succeeded', + 'paymentId': event.data.object.id, +}); +``` + +```swift {tabTitle: Swift} +import Sentry + +// Third-party API call +let start = Date() +let response = try await shippingApi.getRates(items) + +SentrySDK.logger.info("Shipping rates fetched", attributes: [ + "service": "shipping-provider", + "endpoint": "/rates", + "durationMs": Int(Date().timeIntervalSince(start) * 1000), + "rateCount": response.rates.count +]) + +// Webhook received +SentrySDK.logger.info("Webhook received", attributes: [ + "source": "stripe", + "eventType": "payment_intent.succeeded", + "paymentId": event.data.object.id +]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +// Third-party API call +val start = System.currentTimeMillis() +val response = shippingApi.getRates(items) + +Sentry.logger().info("Shipping rates fetched service=%s durationMs=%d", + "shipping-provider", System.currentTimeMillis() - start) + +// Webhook received +Sentry.logger().info("Webhook received source=%s eventType=%s", + "stripe", "payment_intent.succeeded") +``` + +**Query in [Explore > Logs](https://sentry.io/orgredirect/organizations/:orgslug/explore/logs/):** `service:shipping-provider durationMs:>2000` or `source:stripe` + +**Alert idea:** Alert when `service:* durationMs:>3000` to catch third-party slowdowns before they cascade. + +### 4. Background Jobs + +Jobs run outside the request context. Without logs, failed jobs are invisible until someone notices missing data. + +```javascript {tabTitle: JavaScript} +// Inside background job handler +Sentry.logger.info("Job started", { + jobType: "email-digest", + jobId: "job_456", + queue: "notifications", +}); + +Sentry.logger.error("Job failed", { + jobType: "email-digest", + jobId: "job_456", + retryCount: 3, + lastError: "SMTP timeout", +}); +``` + +```python {tabTitle: Python} +from sentry_sdk import logger as sentry_logger + +# Inside background job handler +sentry_logger.info("Job started", + job_type="email-digest", + job_id="job_456", + queue="notifications" +) + +sentry_logger.error("Job failed", + job_type="email-digest", + job_id="job_456", + retry_count=3, + last_error="SMTP timeout" +) +``` + +```php {tabTitle: PHP} +// Inside background job handler +\Sentry\logger()->info('Job started', attributes: [ + 'job_type' => 'email-digest', + 'job_id' => 'job_456', + 'queue' => 'notifications', +]); + +\Sentry\logger()->error('Job failed', attributes: [ + 'job_type' => 'email-digest', + 'job_id' => 'job_456', + 'retry_count' => 3, + 'last_error' => 'SMTP timeout', +]); +``` + +```csharp {tabTitle: .NET} +// Inside background job handler +SentrySdk.Logger.Info("Job started", logger => logger + .SetAttribute("jobType", "email-digest") + .SetAttribute("jobId", "job_456") + .SetAttribute("queue", "notifications")); + +SentrySdk.Logger.Error("Job failed", logger => logger + .SetAttribute("jobType", "email-digest") + .SetAttribute("jobId", "job_456") + .SetAttribute("retryCount", 3) + .SetAttribute("lastError", "SMTP timeout")); +``` + +```ruby {tabTitle: Ruby} +# Inside background job handler +Sentry.logger.info('Job started', + job_type: 'email-digest', + job_id: 'job_456', + queue: 'notifications' +) + +Sentry.logger.error('Job failed', + job_type: 'email-digest', + job_id: 'job_456', + retry_count: 3, + last_error: 'SMTP timeout' +) +``` + +```dart {tabTitle: Flutter} +// Inside background job handler +Sentry.logger.info('Job started', attributes: { + 'jobType': 'email-digest', + 'jobId': 'job_456', + 'queue': 'notifications', +}); + +Sentry.logger.error('Job failed', attributes: { + 'jobType': 'email-digest', + 'jobId': 'job_456', + 'retryCount': 3, + 'lastError': 'SMTP timeout', +}); +``` + +```swift {tabTitle: Swift} +import Sentry + +// Inside background job handler +SentrySDK.logger.info("Job started", attributes: [ + "jobType": "email-digest", + "jobId": "job_456", + "queue": "notifications" +]) + +SentrySDK.logger.error("Job failed", attributes: [ + "jobType": "email-digest", + "jobId": "job_456", + "retryCount": 3, + "lastError": "SMTP timeout" +]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +// Inside background job handler +Sentry.logger().info("Job started jobType=%s jobId=%s queue=%s", + "email-digest", "job_456", "notifications") + +Sentry.logger().error("Job failed jobType=%s jobId=%s retryCount=%d", + "email-digest", "job_456", 3) +``` + +**Query in [Explore > Logs](https://sentry.io/orgredirect/organizations/:orgslug/explore/logs/):** `jobType:email-digest severity:error` + +**Alert idea:** Alert when `severity:error jobType:*` spikes—this can indicate queue processing issues or downstream failures. + +### 5. Feature Flags and Config Changes + +When something breaks after a deploy, the first question is "what changed?" Logging flag evaluations and config reloads gives you that answer instantly. + +```javascript {tabTitle: JavaScript} +// When feature flag is checked or config changes +Sentry.logger.info("Feature flag evaluated", { + flag: "new-checkout-flow", + enabled: true, + userId: user.id, +}); + +Sentry.logger.warn("Config reloaded", { + reason: "env-change", + changedKeys: ["API_TIMEOUT", "MAX_CONNECTIONS"], +}); +``` + +```python {tabTitle: Python} +from sentry_sdk import logger as sentry_logger + +# When feature flag is checked or config changes +sentry_logger.info("Feature flag evaluated", + flag="new-checkout-flow", + enabled=True, + user_id=user.id +) + +sentry_logger.warning("Config reloaded", + reason="env-change", + changed_keys=["API_TIMEOUT", "MAX_CONNECTIONS"] +) +``` + +```php {tabTitle: PHP} +// When feature flag is checked or config changes +\Sentry\logger()->info('Feature flag evaluated', attributes: [ + 'flag' => 'new-checkout-flow', + 'enabled' => true, + 'user_id' => $user->id, +]); + +\Sentry\logger()->warn('Config reloaded', attributes: [ + 'reason' => 'env-change', + 'changed_keys' => ['API_TIMEOUT', 'MAX_CONNECTIONS'], +]); +``` + +```csharp {tabTitle: .NET} +// When feature flag is checked or config changes +SentrySdk.Logger.Info("Feature flag evaluated", logger => logger + .SetAttribute("flag", "new-checkout-flow") + .SetAttribute("enabled", true) + .SetAttribute("userId", user.Id)); + +SentrySdk.Logger.Warning("Config reloaded", logger => logger + .SetAttribute("reason", "env-change") + .SetAttribute("changedKeys", new[] { "API_TIMEOUT", "MAX_CONNECTIONS" })); +``` + +```ruby {tabTitle: Ruby} +# When feature flag is checked or config changes +Sentry.logger.info('Feature flag evaluated', + flag: 'new-checkout-flow', + enabled: true, + user_id: user.id +) + +Sentry.logger.warn('Config reloaded', + reason: 'env-change', + changed_keys: ['API_TIMEOUT', 'MAX_CONNECTIONS'] +) +``` + +```dart {tabTitle: Flutter} +// When feature flag is checked or config changes +Sentry.logger.info('Feature flag evaluated', attributes: { + 'flag': 'new-checkout-flow', + 'enabled': true, + 'userId': user.id, +}); + +Sentry.logger.warn('Config reloaded', attributes: { + 'reason': 'env-change', + 'changedKeys': ['API_TIMEOUT', 'MAX_CONNECTIONS'], +}); +``` + +```swift {tabTitle: Swift} +import Sentry + +// When feature flag is checked or config changes +SentrySDK.logger.info("Feature flag evaluated", attributes: [ + "flag": "new-checkout-flow", + "enabled": true, + "userId": user.id +]) + +SentrySDK.logger.warn("Config reloaded", attributes: [ + "reason": "env-change", + "changedKeys": ["API_TIMEOUT", "MAX_CONNECTIONS"] +]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +// When feature flag is checked or config changes +Sentry.logger().info("Feature flag evaluated flag=%s enabled=%b userId=%s", + "new-checkout-flow", true, user.id) + +Sentry.logger().warn("Config reloaded reason=%s", "env-change") +``` + +**Query in [Explore > Logs](https://sentry.io/orgredirect/organizations/:orgslug/explore/logs/):** `flag:new-checkout-flow` or `"Config reloaded"` + +## Creating Alerts From Logs + +1. Go to **Explore > Logs** +2. Enter your search query (e.g., `severity:error gateway:*`) +3. Click **Save As** - **Alert** +4. Choose a threshold type: + - **Static:** Alert when count exceeds a value + - **Percent Change:** Alert when count changes relative to a previous period + - **Anomaly:** Let Sentry detect unusual patterns +5. Configure notification channels and save + +Learn about [creating alerts](/product/new-monitors-and-alerts/alerts/) and best practices for [reducing noise and routing notifications](/product/new-monitors-and-alerts/alerts/best-practices/). + +## Logging Strategy + +### Development Logging + +In development, set sample rates to 100% to catch everything. This helps you understand what logs are being generated and tune your instrumentation before it hits production. + +**Development configuration:** + +```javascript {tabTitle: JavaScript} +Sentry.init({ + dsn: "...", + environment: "development", + tracesSampleRate: 1.0, // 100% of traces + // Capture all logs in development + integrations: [ + Sentry.captureConsoleIntegration({ + levels: ["log", "info", "warn", "error", "debug"], + }), + ], +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +sentry_sdk.init( + dsn="...", + environment="development", + traces_sample_rate=1.0, # 100% of traces + enable_logs=True, +) +``` + +```php {tabTitle: PHP} +\Sentry\init([ + 'dsn' => '...', + 'environment' => 'development', + 'traces_sample_rate' => 1.0, // 100% of traces + 'enable_logs' => true, +]); +``` + +```csharp {tabTitle: .NET} +SentrySdk.Init(options => +{ + options.Dsn = "..."; + options.Environment = "development"; + options.TracesSampleRate = 1.0; // 100% of traces + options.EnableLogs = true; +}); +``` + +```ruby {tabTitle: Ruby} +Sentry.init do |config| + config.dsn = '...' + config.environment = 'development' + config.traces_sample_rate = 1.0 # 100% of traces + config.enable_logs = true +end +``` + +```dart {tabTitle: Flutter} +await SentryFlutter.init( + (options) { + options.dsn = '...'; + options.environment = 'development'; + options.tracesSampleRate = 1.0; // 100% of traces + options.enableLogs = true; + }, + appRunner: () => runApp(MyApp()), +); +``` + +```swift {tabTitle: Swift} +import Sentry + +SentrySDK.start { options in + options.dsn = "..." + options.environment = "development" + options.tracesSampleRate = 1.0 // 100% of traces + options.enableLogs = true +} +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.android.core.SentryAndroid + +SentryAndroid.init(context) { options -> + options.dsn = "..." + options.environment = "development" + options.tracesSampleRate = 1.0 // 100% of traces + options.logs.enabled = true +} +``` + +Use verbose logging levels like `debug` (development diagnostics) and `trace` (fine-grained execution details) freely in development. You can filter these out in production using beforeSendLog to only capture `info` and above. + +### Production Logging + +Local debugging often means many small logs tracing execution flow. In production, this creates noise that's hard to query. + +Instead, log fewer messages with higher cardinality. Store events during execution and emit them as a single structured log. + +**Don't do this:** + +```javascript {tabTitle: JavaScript} +Sentry.logger.info("Checkout started", { userId: "882" }); +Sentry.logger.info("Discount applied", { code: "WINTER20" }); +Sentry.logger.error("Payment failed", { reason: "Insufficient Funds" }); +``` + +```python {tabTitle: Python} +sentry_logger.info("Checkout started", user_id="882") +sentry_logger.info("Discount applied", code="WINTER20") +sentry_logger.error("Payment failed", reason="Insufficient Funds") +``` + +```php {tabTitle: PHP} +\Sentry\logger()->info('Checkout started', attributes: ['user_id' => '882']); +\Sentry\logger()->info('Discount applied', attributes: ['code' => 'WINTER20']); +\Sentry\logger()->error('Payment failed', attributes: ['reason' => 'Insufficient Funds']); +``` + +```csharp {tabTitle: .NET} +SentrySdk.Logger.Info("Checkout started", l => l.SetAttribute("userId", "882")); +SentrySdk.Logger.Info("Discount applied", l => l.SetAttribute("code", "WINTER20")); +SentrySdk.Logger.Error("Payment failed", l => l.SetAttribute("reason", "Insufficient Funds")); +``` + +```ruby {tabTitle: Ruby} +Sentry.logger.info('Checkout started', user_id: '882') +Sentry.logger.info('Discount applied', code: 'WINTER20') +Sentry.logger.error('Payment failed', reason: 'Insufficient Funds') +``` + +```dart {tabTitle: Flutter} +Sentry.logger.info('Checkout started', attributes: {'userId': '882'}); +Sentry.logger.info('Discount applied', attributes: {'code': 'WINTER20'}); +Sentry.logger.error('Payment failed', attributes: {'reason': 'Insufficient Funds'}); +``` + +```swift {tabTitle: Swift} +SentrySDK.logger.info("Checkout started", attributes: ["userId": "882"]) +SentrySDK.logger.info("Discount applied", attributes: ["code": "WINTER20"]) +SentrySDK.logger.error("Payment failed", attributes: ["reason": "Insufficient Funds"]) +``` + +```kotlin {tabTitle: Kotlin} +Sentry.logger().info("Checkout started userId=%s", "882") +Sentry.logger().info("Discount applied code=%s", "WINTER20") +Sentry.logger().error("Payment failed reason=%s", "Insufficient Funds") +``` + +These logs are trace-connected, but searching for the error won't return the userId or discount code from the same transaction. + +**Do this instead:** + +```javascript {tabTitle: JavaScript} +Sentry.logger.error("Checkout failed", { + userId: "882", + orderId: "order_pc_991", + cartTotal: 142.5, + discountCode: "WINTER20", + paymentMethod: "stripe", + errorReason: "Insufficient Funds", + itemCount: 4, +}); +``` + +```python {tabTitle: Python} +sentry_logger.error("Checkout failed", + user_id="882", + order_id="order_pc_991", + cart_total=142.50, + discount_code="WINTER20", + payment_method="stripe", + error_reason="Insufficient Funds", + item_count=4 +) +``` + +```php {tabTitle: PHP} +\Sentry\logger()->error('Checkout failed', attributes: [ + 'user_id' => '882', + 'order_id' => 'order_pc_991', + 'cart_total' => 142.50, + 'discount_code' => 'WINTER20', + 'payment_method' => 'stripe', + 'error_reason' => 'Insufficient Funds', + 'item_count' => 4, +]); +``` + +```csharp {tabTitle: .NET} +SentrySdk.Logger.Error("Checkout failed", logger => logger + .SetAttribute("userId", "882") + .SetAttribute("orderId", "order_pc_991") + .SetAttribute("cartTotal", 142.50) + .SetAttribute("discountCode", "WINTER20") + .SetAttribute("paymentMethod", "stripe") + .SetAttribute("errorReason", "Insufficient Funds") + .SetAttribute("itemCount", 4)); +``` + +```ruby {tabTitle: Ruby} +Sentry.logger.error('Checkout failed', + user_id: '882', + order_id: 'order_pc_991', + cart_total: 142.50, + discount_code: 'WINTER20', + payment_method: 'stripe', + error_reason: 'Insufficient Funds', + item_count: 4 +) +``` + +```dart {tabTitle: Flutter} +Sentry.logger.error('Checkout failed', attributes: { + 'userId': '882', + 'orderId': 'order_pc_991', + 'cartTotal': 142.50, + 'discountCode': 'WINTER20', + 'paymentMethod': 'stripe', + 'errorReason': 'Insufficient Funds', + 'itemCount': 4, +}); +``` + +```swift {tabTitle: Swift} +import Sentry + +SentrySDK.logger.error("Checkout failed", attributes: [ + "userId": "882", + "orderId": "order_pc_991", + "cartTotal": 142.50, + "discountCode": "WINTER20", + "paymentMethod": "stripe", + "errorReason": "Insufficient Funds", + "itemCount": 4 +]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry +import io.sentry.SentryAttribute +import io.sentry.SentryAttributes +import io.sentry.SentryLogLevel +import io.sentry.logger.SentryLogParameters + +Sentry.logger().log( + SentryLogLevel.ERROR, + SentryLogParameters.create( + SentryAttributes.of( + SentryAttribute.stringAttribute("userId", "882"), + SentryAttribute.stringAttribute("orderId", "order_pc_991"), + SentryAttribute.doubleAttribute("cartTotal", 142.50), + SentryAttribute.stringAttribute("discountCode", "WINTER20"), + SentryAttribute.stringAttribute("paymentMethod", "stripe"), + SentryAttribute.stringAttribute("errorReason", "Insufficient Funds"), + SentryAttribute.integerAttribute("itemCount", 4) + ) + ), + "Checkout failed" +) +``` + +One log tells the whole story. Search for the error and get full context. + +### Log Drains for Platform Logs + +If you can't install the Sentry SDK or need platform-level logs (CDN, database, load balancer), use [Log Drains](/product/drains/). + +**Platform drains:** [Vercel](/product/drains/vercel/), [Cloudflare Workers](/product/drains/cloudflare/), [Heroku](/product/drains/heroku/), [Supabase](/product/drains/supabase/) + +**Forwarders:** [OpenTelemetry Collector](/concepts/otlp/forwarding/pipelines/collector/), [Vector](/concepts/otlp/forwarding/pipelines/vector/), [Fluent Bit](/concepts/otlp/forwarding/pipelines/fluentbit/), [AWS CloudWatch](/concepts/otlp/forwarding/sources/aws-cloudwatch/), [Kafka](/concepts/otlp/forwarding/sources/kafka/) + +## Quick Reference + +| Category | Level | Example Attributes | +| --------------- | -------------- | ----------------------------------- | +| Auth events | `info`/`warn` | userId, authMethod, reason | +| Payments | `info`/`error` | orderId, amount, gateway, errorCode | +| External APIs | `info` | service, endpoint, durationMs | +| Background jobs | `info`/`error` | jobType, jobId, retryCount | +| Feature flags | `info` | flag, enabled, changedKeys | + +## Next Steps + +Explore the [product walkthrough guides](/product/) to learn more about the Sentry interface and discover additional tips. diff --git a/docs/guides/metrics.mdx b/docs/guides/metrics.mdx new file mode 100644 index 00000000000000..f20099592719b5 --- /dev/null +++ b/docs/guides/metrics.mdx @@ -0,0 +1,636 @@ +--- +title: "What to Track" +sidebar_order: 15 +description: "Practical guidance on what metrics to track, how to explore them, and when to set alerts." +--- + +You've set up [Sentry Metrics](/product/explore/metrics/). Now what? This guide covers the high-value metric patterns that give you visibility into application health and how to drill into traces when something looks off. + +## Anatomy of a Metric + +Sentry supports three metric types: + +| Type | Method | Use For | +| ---------------- | ------------------------------- | ------------------------------------------- | +| **Counter** | `Sentry.metrics.count()` | Events that happen (orders, clicks, errors) | +| **Gauge** | `Sentry.metrics.gauge()` | Current state (queue depth, connections) | +| **Distribution** | `Sentry.metrics.distribution()` | Values that vary (latency, sizes, amounts) | + +Every metric is trace-connected. When a metric spikes, click into samples to see the exact [trace](/concepts/key-terms/tracing/trace-view/) that produced it. + +```javascript {tabTitle: JavaScript} +Sentry.metrics.count("checkout.failed", 1, { + attributes: { + user_tier: "premium", + failure_reason: "payment_declined", + }, +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +sentry_sdk.metrics.count("checkout.failed", 1, attributes={ + "user_tier": "premium", + "failure_reason": "payment_declined" +}) +``` + +```php {tabTitle: PHP} +\Sentry\traceMetrics()->count('checkout.failed', 1, [ + 'user_tier' => 'premium', + 'failure_reason' => 'payment_declined', +]); +``` + +```csharp {tabTitle: .NET} +SentrySdk.Metrics.Counter("checkout.failed") + .Tag("user_tier", "premium") + .Tag("failure_reason", "payment_declined") + .Increment(); +``` + +```ruby {tabTitle: Ruby} +Sentry.metrics.count('checkout.failed', 1, + tags: { user_tier: 'premium', failure_reason: 'payment_declined' } +) +``` + +```dart {tabTitle: Flutter} +Sentry.metrics.count('checkout.failed', 1, attributes: { + 'user_tier': 'premium', + 'failure_reason': 'payment_declined', +}); +``` + +```swift {tabTitle: Swift} +import Sentry + +SentrySDK.metrics.count(key: "checkout.failed", value: 1, attributes: [ + "user_tier": "premium", + "failure_reason": "payment_declined" +]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +Sentry.metrics().count("checkout.failed", 1.0) +``` + +## Where to Track Metrics + +Start with these five metrics and you'll spot issues before they become problems. + +### 1. Business Events + +Track discrete events that matter to the business. These become your KPIs. + +```javascript {tabTitle: JavaScript} +Sentry.metrics.count("checkout.completed", 1, { + attributes: { user_tier: "premium", payment_method: "card" }, +}); + +Sentry.metrics.count("checkout.failed", 1, { + attributes: { user_tier: "premium", failure_reason: "payment_declined" }, +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +sentry_sdk.metrics.count("checkout.completed", 1, attributes={ + "user_tier": "premium", "payment_method": "card" +}) + +sentry_sdk.metrics.count("checkout.failed", 1, attributes={ + "user_tier": "premium", "failure_reason": "payment_declined" +}) +``` + +```php {tabTitle: PHP} +\Sentry\traceMetrics()->count('checkout.completed', 1, [ + 'user_tier' => 'premium', 'payment_method' => 'card' +]); + +\Sentry\traceMetrics()->count('checkout.failed', 1, [ + 'user_tier' => 'premium', 'failure_reason' => 'payment_declined' +]); +``` + +```csharp {tabTitle: .NET} +SentrySdk.Metrics.Counter("checkout.completed") + .Tag("user_tier", "premium") + .Tag("payment_method", "card") + .Increment(); + +SentrySdk.Metrics.Counter("checkout.failed") + .Tag("user_tier", "premium") + .Tag("failure_reason", "payment_declined") + .Increment(); +``` + +```ruby {tabTitle: Ruby} +Sentry.metrics.count('checkout.completed', 1, + tags: { user_tier: 'premium', payment_method: 'card' } +) + +Sentry.metrics.count('checkout.failed', 1, + tags: { user_tier: 'premium', failure_reason: 'payment_declined' } +) +``` + +```dart {tabTitle: Flutter} +Sentry.metrics.count('checkout.completed', 1, attributes: { + 'user_tier': 'premium', + 'payment_method': 'card', +}); + +Sentry.metrics.count('checkout.failed', 1, attributes: { + 'user_tier': 'premium', + 'failure_reason': 'payment_declined', +}); +``` + +```swift {tabTitle: Swift} +import Sentry + +SentrySDK.metrics.count(key: "checkout.completed", value: 1, attributes: [ + "user_tier": "premium", "payment_method": "card" +]) + +SentrySDK.metrics.count(key: "checkout.failed", value: 1, attributes: [ + "user_tier": "premium", "failure_reason": "payment_declined" +]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +Sentry.metrics().count("checkout.completed", 1.0) +Sentry.metrics().count("checkout.failed", 1.0) +``` + +**Explore in Sentry:** + +1. Go to [**Explore > Metrics**](https://sentry.io/orgredirect/organizations/:orgslug/explore/metrics/) +2. Select `checkout.failed`, set **Aggregate** to `sum` +3. **Group by** `failure_reason` +4. Click **Samples** to see individual events and their traces + +### 2. Application Health + +Track success and failure of critical operations. + +```javascript {tabTitle: JavaScript} +Sentry.metrics.count("email.sent", 1, { + attributes: { email_type: "welcome", provider: "sendgrid" }, +}); + +Sentry.metrics.count("email.failed", 1, { + attributes: { email_type: "welcome", error: "rate_limited" }, +}); + +Sentry.metrics.count("job.processed", 1, { + attributes: { job_type: "invoice-generation", queue: "billing" }, +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +sentry_sdk.metrics.count("email.sent", 1, attributes={ + "email_type": "welcome", "provider": "sendgrid" +}) + +sentry_sdk.metrics.count("email.failed", 1, attributes={ + "email_type": "welcome", "error": "rate_limited" +}) + +sentry_sdk.metrics.count("job.processed", 1, attributes={ + "job_type": "invoice-generation", "queue": "billing" +}) +``` + +```php {tabTitle: PHP} +\Sentry\traceMetrics()->count('email.sent', 1, [ + 'email_type' => 'welcome', 'provider' => 'sendgrid' +]); + +\Sentry\traceMetrics()->count('email.failed', 1, [ + 'email_type' => 'welcome', 'error' => 'rate_limited' +]); + +\Sentry\traceMetrics()->count('job.processed', 1, [ + 'job_type' => 'invoice-generation', 'queue' => 'billing' +]); +``` + +```csharp {tabTitle: .NET} +SentrySdk.Metrics.Counter("email.sent") + .Tag("email_type", "welcome") + .Tag("provider", "sendgrid") + .Increment(); + +SentrySdk.Metrics.Counter("email.failed") + .Tag("email_type", "welcome") + .Tag("error", "rate_limited") + .Increment(); + +SentrySdk.Metrics.Counter("job.processed") + .Tag("job_type", "invoice-generation") + .Tag("queue", "billing") + .Increment(); +``` + +```ruby {tabTitle: Ruby} +Sentry.metrics.count('email.sent', 1, + tags: { email_type: 'welcome', provider: 'sendgrid' } +) + +Sentry.metrics.count('email.failed', 1, + tags: { email_type: 'welcome', error: 'rate_limited' } +) + +Sentry.metrics.count('job.processed', 1, + tags: { job_type: 'invoice-generation', queue: 'billing' } +) +``` + +```dart {tabTitle: Flutter} +Sentry.metrics.count('email.sent', 1, attributes: { + 'email_type': 'welcome', + 'provider': 'sendgrid', +}); + +Sentry.metrics.count('email.failed', 1, attributes: { + 'email_type': 'welcome', + 'error': 'rate_limited', +}); + +Sentry.metrics.count('job.processed', 1, attributes: { + 'job_type': 'invoice-generation', + 'queue': 'billing', +}); +``` + +```swift {tabTitle: Swift} +import Sentry + +SentrySDK.metrics.count(key: "email.sent", value: 1, attributes: [ + "email_type": "welcome", "provider": "sendgrid" +]) + +SentrySDK.metrics.count(key: "email.failed", value: 1, attributes: [ + "email_type": "welcome", "error": "rate_limited" +]) + +SentrySDK.metrics.count(key: "job.processed", value: 1, attributes: [ + "job_type": "invoice-generation", "queue": "billing" +]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +Sentry.metrics().count("email.sent", 1.0) +Sentry.metrics().count("email.failed", 1.0) +Sentry.metrics().count("job.processed", 1.0) +``` + +**Query in [Explore > Metrics](https://sentry.io/orgredirect/organizations/:orgslug/explore/metrics/):** Add both `email.sent` and `email.failed`, group by `email_type`, compare the ratio. + +### 3. Resource Utilization + +Track the current state of pools, queues, and connections. Call these periodically (e.g., every 30 seconds). + +```javascript {tabTitle: JavaScript} +Sentry.metrics.gauge("queue.depth", await queue.size(), { + attributes: { queue_name: "notifications" }, +}); + +Sentry.metrics.gauge("pool.connections_active", pool.activeConnections, { + attributes: { pool_name: "postgres-primary" }, +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +sentry_sdk.metrics.gauge("queue.depth", queue.size(), attributes={ + "queue_name": "notifications" +}) + +sentry_sdk.metrics.gauge("pool.connections_active", pool.active_connections, attributes={ + "pool_name": "postgres-primary" +}) +``` + +```php {tabTitle: PHP} +use \Sentry\Metrics\Unit; + +\Sentry\traceMetrics()->gauge('queue.depth', $queue->size(), [ + 'queue_name' => 'notifications' +]); + +\Sentry\traceMetrics()->gauge('pool.connections_active', $pool->activeConnections, [ + 'pool_name' => 'postgres-primary' +]); +``` + +```csharp {tabTitle: .NET} +SentrySdk.Metrics.Gauge("queue.depth") + .Tag("queue_name", "notifications") + .Set(queue.Size); + +SentrySdk.Metrics.Gauge("pool.connections_active") + .Tag("pool_name", "postgres-primary") + .Set(pool.ActiveConnections); +``` + +```ruby {tabTitle: Ruby} +Sentry.metrics.gauge('queue.depth', queue.size, + tags: { queue_name: 'notifications' } +) + +Sentry.metrics.gauge('pool.connections_active', pool.active_connections, + tags: { pool_name: 'postgres-primary' } +) +``` + +```dart {tabTitle: Flutter} +Sentry.metrics.gauge('queue.depth', queue.size.toDouble(), attributes: { + 'queue_name': 'notifications', +}); + +Sentry.metrics.gauge('pool.connections_active', pool.activeConnections.toDouble(), attributes: { + 'pool_name': 'postgres-primary', +}); +``` + +```swift {tabTitle: Swift} +import Sentry + +SentrySDK.metrics.gauge(key: "queue.depth", value: Double(queue.size), attributes: [ + "queue_name": "notifications" +]) + +SentrySDK.metrics.gauge(key: "pool.connections_active", value: Double(pool.activeConnections), attributes: [ + "pool_name": "postgres-primary" +]) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry + +Sentry.metrics().gauge("queue.depth", queue.size.toDouble()) +Sentry.metrics().gauge("pool.connections_active", pool.activeConnections.toDouble()) +``` + +**Query in [Explore > Metrics](https://sentry.io/orgredirect/organizations/:orgslug/explore/metrics/):** View `max(queue.depth)` over time to spot backlogs. + +### 4. Latency and Performance + +Track values that vary and need percentile analysis. **Tip:** averages can hide outliers, use p90/p95/p99 instead. + +```javascript {tabTitle: JavaScript} +Sentry.metrics.distribution("api.latency", responseTimeMs, { + unit: "millisecond", + attributes: { endpoint: "/api/orders", method: "POST" }, +}); + +Sentry.metrics.distribution("db.query_time", queryDurationMs, { + unit: "millisecond", + attributes: { table: "orders", operation: "select" }, +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +sentry_sdk.metrics.distribution("api.latency", response_time_ms, + unit="millisecond", + attributes={"endpoint": "/api/orders", "method": "POST"} +) + +sentry_sdk.metrics.distribution("db.query_time", query_duration_ms, + unit="millisecond", + attributes={"table": "orders", "operation": "select"} +) +``` + +```php {tabTitle: PHP} +use \Sentry\Metrics\Unit; + +\Sentry\traceMetrics()->distribution('api.latency', $responseTimeMs, + ['endpoint' => '/api/orders', 'method' => 'POST'], + Unit::millisecond() +); + +\Sentry\traceMetrics()->distribution('db.query_time', $queryDurationMs, + ['table' => 'orders', 'operation' => 'select'], + Unit::millisecond() +); +``` + +```csharp {tabTitle: .NET} +SentrySdk.Metrics.Distribution("api.latency", responseTimeMs, + unit: MeasurementUnit.Duration.Millisecond) + .Tag("endpoint", "/api/orders") + .Tag("method", "POST"); + +SentrySdk.Metrics.Distribution("db.query_time", queryDurationMs, + unit: MeasurementUnit.Duration.Millisecond) + .Tag("table", "orders") + .Tag("operation", "select"); +``` + +```ruby {tabTitle: Ruby} +Sentry.metrics.distribution('api.latency', response_time_ms, + unit: 'millisecond', + tags: { endpoint: '/api/orders', method: 'POST' } +) + +Sentry.metrics.distribution('db.query_time', query_duration_ms, + unit: 'millisecond', + tags: { table: 'orders', operation: 'select' } +) +``` + +```dart {tabTitle: Flutter} +Sentry.metrics.distribution('api.latency', responseTimeMs, + unit: SentryMeasurementUnit.duration(SentryDurationUnit.milliSecond), + attributes: {'endpoint': '/api/orders', 'method': 'POST'}, +); + +Sentry.metrics.distribution('db.query_time', queryDurationMs, + unit: SentryMeasurementUnit.duration(SentryDurationUnit.milliSecond), + attributes: {'table': 'orders', 'operation': 'select'}, +); +``` + +```swift {tabTitle: Swift} +import Sentry + +SentrySDK.metrics.distribution(key: "api.latency", value: responseTimeMs, + unit: .millisecond, + attributes: ["endpoint": "/api/orders", "method": "POST"] +) + +SentrySDK.metrics.distribution(key: "db.query_time", value: queryDurationMs, + unit: .millisecond, + attributes: ["table": "orders", "operation": "select"] +) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry +import io.sentry.metrics.MetricsUnit + +Sentry.metrics().distribution("api.latency", responseTimeMs, + MetricsUnit.Duration.MILLISECOND) + +Sentry.metrics().distribution("db.query_time", queryDurationMs, + MetricsUnit.Duration.MILLISECOND) +``` + +**Query in [Explore > Metrics](https://sentry.io/orgredirect/organizations/:orgslug/explore/metrics/):** View `p95(api.latency)` grouped by `endpoint` to find slow routes. + +### 5. Business Values + +Track amounts, sizes, and quantities for analysis. + +```javascript {tabTitle: JavaScript} +Sentry.metrics.distribution("order.amount", order.totalUsd, { + unit: "usd", + attributes: { user_tier: "premium", region: "us-west" }, +}); + +Sentry.metrics.distribution("upload.size", fileSizeBytes, { + unit: "byte", + attributes: { file_type: "image", source: "profile-update" }, +}); +``` + +```python {tabTitle: Python} +import sentry_sdk + +sentry_sdk.metrics.distribution("order.amount", order.total_usd, + unit="usd", + attributes={"user_tier": "premium", "region": "us-west"} +) + +sentry_sdk.metrics.distribution("upload.size", file_size_bytes, + unit="byte", + attributes={"file_type": "image", "source": "profile-update"} +) +``` + +```php {tabTitle: PHP} +use \Sentry\Metrics\Unit; + +\Sentry\traceMetrics()->distribution('order.amount', $order->totalUsd, + ['user_tier' => 'premium', 'region' => 'us-west'], + Unit::custom('usd') +); + +\Sentry\traceMetrics()->distribution('upload.size', $fileSizeBytes, + ['file_type' => 'image', 'source' => 'profile-update'], + Unit::byte() +); +``` + +```csharp {tabTitle: .NET} +SentrySdk.Metrics.Distribution("order.amount", order.TotalUsd, + unit: MeasurementUnit.Custom("usd")) + .Tag("user_tier", "premium") + .Tag("region", "us-west"); + +SentrySdk.Metrics.Distribution("upload.size", fileSizeBytes, + unit: MeasurementUnit.Information.Byte) + .Tag("file_type", "image") + .Tag("source", "profile-update"); +``` + +```ruby {tabTitle: Ruby} +Sentry.metrics.distribution('order.amount', order.total_usd, + unit: 'usd', + tags: { user_tier: 'premium', region: 'us-west' } +) + +Sentry.metrics.distribution('upload.size', file_size_bytes, + unit: 'byte', + tags: { file_type: 'image', source: 'profile-update' } +) +``` + +```dart {tabTitle: Flutter} +Sentry.metrics.distribution('order.amount', order.totalUsd, + unit: SentryMeasurementUnit.custom('usd'), + attributes: {'user_tier': 'premium', 'region': 'us-west'}, +); + +Sentry.metrics.distribution('upload.size', fileSizeBytes.toDouble(), + unit: SentryMeasurementUnit.information(SentryInformationUnit.byte), + attributes: {'file_type': 'image', 'source': 'profile-update'}, +); +``` + +```swift {tabTitle: Swift} +import Sentry + +SentrySDK.metrics.distribution(key: "order.amount", value: order.totalUsd, + unit: .generic("usd"), + attributes: ["user_tier": "premium", "region": "us-west"] +) + +SentrySDK.metrics.distribution(key: "upload.size", value: Double(fileSizeBytes), + unit: .byte, + attributes: ["file_type": "image", "source": "profile-update"] +) +``` + +```kotlin {tabTitle: Kotlin} +import io.sentry.Sentry +import io.sentry.metrics.MetricsUnit + +Sentry.metrics().distribution("order.amount", order.totalUsd) + +Sentry.metrics().distribution("upload.size", fileSizeBytes.toDouble(), + MetricsUnit.Information.BYTE) +``` + +**Query in [Explore > Metrics](https://sentry.io/orgredirect/organizations/:orgslug/explore/metrics/):** View `avg(order.amount)` grouped by `region` to compare regional performance. + +## Alerts and Dashboard Widgets + + + Alerts and dashboard widgets for Metrics are coming soon. + + +You'll soon be able to: + +- Create alert rules based on metric queries +- Add metric visualizations to dashboards +- Set up notifications when metrics cross thresholds +- Save common queries for quick access + +## Quick Reference + +| Category | Type | Method | Example Attributes | +| -------------------- | ------------ | ---------------- | ----------------------------------------- | +| Business events | Counter | `count()` | user_tier, payment_method, failure_reason | +| Application health | Counter | `count()` | email_type, provider, job_type, queue | +| Resource utilization | Gauge | `gauge()` | queue_name, pool_name | +| Latency/performance | Distribution | `distribution()` | endpoint, method, table, operation | +| Business values | Distribution | `distribution()` | user_tier, region, file_type | + +## When to Use Metrics vs Traces vs Logs + +| Signal | Best For | Example Question | +| ----------- | ------------------------------------- | ---------------------------------------- | +| **Metrics** | Aggregated counts, rates, percentiles | "How many checkouts failed this hour?" | +| **Traces** | Request flow, latency breakdown | "Why was this specific request slow?" | +| **Logs** | Detailed context, debugging | "What happened right before this error?" | + +All three are trace-connected. Start wherever makes sense and navigate to the others. diff --git a/docs/guides/querying-traces.mdx b/docs/guides/querying-traces.mdx new file mode 100644 index 00000000000000..326d6b144bc9a5 --- /dev/null +++ b/docs/guides/querying-traces.mdx @@ -0,0 +1,91 @@ +--- +title: "Querying Traces" +sidebar_order: 20 +description: "Find performance issues using data Sentry captures automatically and set up alerts." +--- + +You've enabled [Sentry Tracing](/product/explore/trace-explorer/). Now what? Sentry's auto-instrumentation captures a lot without custom code. This guide shows you how to query that data to find performance issues. + + + +## What's Auto-Instrumented + +With `browserTracingIntegration()` enabled, Sentry automatically captures: + +- Page loads and navigation +- Fetch/XHR requests +- Long animation frames (main thread blocking) +- Resource loading (JS, CSS, images) + +## Where to Look + +Start with these five queries and you'll catch most performance issues before users complain. + +### 1. Slow Page Loads: Pages taking too long to become interactive hurt first impressions + +**Query in [Explore > Traces](https://sentry.io/orgredirect/organizations/:orgslug/explore/traces/):** `span.op:pageload` & **Visualize:** `p90(span.duration)` grouped by `transaction` to compare routes. + +- **What to look for:** Routes with p90 over 3 seconds. Explore sample traces to see the breakdown. Usually it's slow API calls, heavy JavaScript, or large images. + +- **Alert idea:** `p75(transaction.duration) > 3s` for pageload transactions. + +### 2. Slow API Calls: Fetch/XHR requests are often the bottleneck in modern web apps + +**Query in [Explore > Traces](https://sentry.io/orgredirect/organizations/:orgslug/explore/traces/):** `span.op:http.client` & **Visualize:** `avg(span.duration)` grouped by `span.description` (the URL). + +- **What to look for:** Endpoints with avg duration over 1 second or p95 over 2 seconds. Check if it's the backend or network latency by looking at sample traces. + +- **Alert idea:** `p95(span.duration) > 2s` where `span.op:http.client`. + +### 3. JavaScript Blocking the UI: Long animation frames mean JavaScript execution is freezing the interface + +**Query in [Explore > Traces](https://sentry.io/orgredirect/organizations/:orgslug/explore/traces/):** `span.op:ui.long-animation-frame` & **Visualize:** Sort by `span.duration` to find the worst offenders. + +- **What to look for:** Frames over 200ms. This is what causes jank and unresponsiveness. Look at the stack trace in sample traces to find the expensive operation. + +- **Alert idea:** `p75(span.duration) > 200ms` for long animation frames. + +### 4. Slow SPA Navigation: After the initial load, how fast do users move between pages? + +**Query in [Explore > Traces](https://sentry.io/orgredirect/organizations/:orgslug/explore/traces/):** `span.op:navigation` & **Visualize:** `p90(span.duration)` grouped by `transaction` to compare route performance. + +- **What to look for:** Navigation over 1 second feels sluggish. Click into traces to see if it's data fetching, component rendering, or something else. + +- **Alert idea:** `p75(span.duration) > 2s` for navigation. + +### 5. Heavy Resources: Large JS bundles, stylesheets, or images slowing down your site + +**Query in [Explore > Traces](https://sentry.io/orgredirect/organizations/:orgslug/explore/traces/):** `span.op:resource.script` (JavaScript), `span.op:resource.css` (stylesheets), or `span.op:resource.img` (images) & **Visualize:** `avg(span.duration)` to find the heaviest assets. + +- **What to look for:** Resources taking over 1 second. Check the span description to see which files. Often it's third-party scripts or unoptimized images. + +- **Alert idea:** `p75(span.duration) > 3s` for resource.script. + +## Creating Alerts From Traces + +1. Go to **Explore > Traces** +2. Build your query (e.g., `span.op:http.client`) +3. Click **Save As** - **Alert** +4. Choose a threshold type: + - **Static:** Alert when a value exceeds a threshold + - **Percent Change:** Alert when a value changes relative to a previous period + - **Anomaly:** Let Sentry detect unusual patterns +5. Configure notification channels and save + +**Tip:** Averages can hide outliers, use p75/p90/p95 instead. + +Learn about [creating alerts](/product/new-monitors-and-alerts/alerts/) and best practices for [reducing noise and routing notifications](/product/new-monitors-and-alerts/alerts/best-practices/). + +## Quick Reference + +| Category | Query | Visualize | +| ------------------- | --------------------------------- | ----------------------------------- | +| Slow page loads | `span.op:pageload` | `p90(span.duration)` by transaction | +| Slow fetch requests | `span.op:http.client` | `avg(span.duration)` by URL | +| JS blocking UI | `span.op:ui.long-animation-frame` | `max(span.duration)` | +| Slow SPA navigation | `span.op:navigation` | `p90(span.duration)` by transaction | +| Heavy resources | `span.op:resource.*` | `avg(span.duration)` by description | + +## Next Steps + +Explore the [product walkthrough guides](/product/) to learn more about the Sentry interface and discover additional tips. diff --git a/docs/guides/session-replay.mdx b/docs/guides/session-replay.mdx new file mode 100644 index 00000000000000..cf36fb46c48c3f --- /dev/null +++ b/docs/guides/session-replay.mdx @@ -0,0 +1,133 @@ +--- +title: "Using Session Replay" +sidebar_order: 40 +description: "Practical guidance on debugging errors and finding UX issues with Session Replay." +--- + +You've set up [Sentry Session Replay](/product/explore/session-replay/). Now what? Stack traces tell you _what_ broke. Replay shows you _why_. This guide covers how to use replay to debug errors and spot UX problems before users report them. + +## What Replay Captures + +Every replay connected to an error includes: + +- **User actions** — clicks, navigation, form inputs +- **Network requests** — API calls, responses, failures, latency +- **Console logs** — warnings, errors, debug messages +- **Application state** — URL changes, route transitions + +## AI Summary + + + +The AI Summary tab automatically generates a natural language summary of what happened during a session. Instead of watching the entire replay, you can read a text description that highlights key actions, navigation paths, and timestamps. + +Use AI Summary to: + +- Quickly understand what a user did without watching the full replay +- Jump to specific moments in the session by clicking timestamps in the summary +- Share context with teammates who need the highlights, not the full recording + +Click the **AI Summary** tab in any replay to see the generated summary. You can regenerate it if needed. + + + +## Where to Use Replay + +Start with these five workflows and you'll debug faster and catch UX issues before they become support tickets. + +### 1. Root Cause Analysis for Errors + +When an error spikes, the stack trace shows the line of code. Replay shows the user journey that triggered it. + +**What to look for:** + +- **Failed API calls** — Check the Network tab. A 500 error or timeout often cascaded into the JavaScript error. +- **Race conditions** — Did they click twice? Navigate before a request finished? Trigger conflicting operations? +- **Edge case data** — Empty arrays, null values, unexpected formats your code didn't handle. +- **Browser/device context** — Errors on slow connections or older browsers reveal assumptions in your code. + +**Search in Sentry:** Go to **Replays** and filter by `count_errors:>0` to see all sessions with errors. Click into a replay to watch it, or check the AI Summary tab to quickly jump to key moments. + +### 2. Reproducing User-Reported Bugs + +User says it's broken, but you can't reproduce it locally. Replay shows you exactly what they did. + +**What to watch:** + +- The exact sequence of clicks and navigation +- Form inputs or selections that triggered the bug +- Browser console errors they didn't mention +- Network failures or slow responses that affected behavior + +**Search in Sentry:** Go to **Replays** and filter by `user.email:jane@example.com` or `user.id:123` to find sessions around the time they reported the issue. + +### 3. Finding Error Patterns Across Users + +When multiple users hit the same error, patterns emerge that point to the root cause. + +**What to compare:** + +- Do they all come from the same release? +- Did they visit the same pages in the same order? +- Do they share the same browser, device, or region? +- Did a specific API endpoint fail for all of them? + +**Search in Sentry:** Go to **Replays** and filter by `count_errors:>0 release:1.2.3` to see if errors cluster by release, or use `count_errors:>0 browser.name:Chrome` to compare by browser. + +### 4. Spotting Rage Clicks and Dead Clicks + +Clicks that don't work create silent frustration. Replay catches these before users complain. + +**Rage clicks:** Users clicking the same element repeatedly because nothing happens. + +**Dead clicks:** Clicks on elements that look interactive but have no handler. + +**Common causes:** + +- Button appears clickable but has no handler +- Click handler is slow or async without visual feedback +- Element is covered by an invisible overlay (z-index issue) +- JavaScript error preventing the handler from running + +**Search in Sentry:** Go to **Replays** and check the "Most Rage Clicks" and "Most Dead Clicks" widgets at the top* to see the worst offenders. Or filter by `count_rage_clicks:>0` or `count_dead_clicks:>0`. *If you don't see the widgets, toggle "Show Widgets" at the top. + +### 5. Identifying Slow Interactions + +Users waiting too long for responses creates perceived sluggishness even if the page loaded fast. + +**What to watch:** + +- Long gaps between click and visual response +- Loading spinners that last too long (over 2-3 seconds) +- Form submissions with no feedback +- Navigation that feels frozen + +**Search in Sentry:** Go to **Replays** and filter by `url:*/checkout*` to focus on critical flows, then watch replays to spot slow interactions. + +## Privacy Considerations + +By default, Session Replay masks all text content, user input, and images. Sensitive data stays in the browser. + +You'll see placeholder blocks instead of actual content, which is enough to understand what users did without exposing their data. If you need to see specific elements for debugging (like button labels or navigation items), you can unmask them: + +```html +

Welcome to Checkout

+``` + +Be selective. Never unmask form inputs, and review your [privacy configuration](/platforms/javascript/session-replay/privacy/) before increasing sample rates. + +## Quick Reference + +| What You're Looking For | Filter | +| ----------------------- | ------------------------------------------ | +| Sessions with errors | `count_errors:>0` | +| Specific user | `user.email:jane@example.com` | +| Specific page | `url:*/checkout*` | +| Rage clicks | `count_rage_clicks:>0` | +| Dead clicks | `count_dead_clicks:>0` | +| Mobile users | `device.family:iOS` | +| Slow sessions | Filter by URL, watch for slow interactions | + +## Next Steps + +Explore the [product walkthrough guides](/product/) to learn more about the Sentry interface and discover additional tips. diff --git a/docs/platforms/android/index.mdx b/docs/platforms/android/index.mdx index ded14c1bd01fcb..ff78836ff873be 100644 --- a/docs/platforms/android/index.mdx +++ b/docs/platforms/android/index.mdx @@ -181,6 +181,7 @@ class MyActivity : AppCompatActivity() { ## Next Steps +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn about the features of Sentry's Android SDK - Learn how to enhance stack traces of your Sentry errors - Enrich events with additional context to make debugging simpler diff --git a/docs/platforms/dart/common/index.mdx b/docs/platforms/dart/common/index.mdx index baa27d2edd61db..75f4e920aadaa9 100644 --- a/docs/platforms/dart/common/index.mdx +++ b/docs/platforms/dart/common/index.mdx @@ -91,5 +91,6 @@ try { ## Next Steps +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn about the features of Sentry's Dart SDK - Add performance instrumentation to your app diff --git a/docs/platforms/dart/guides/flutter/index.mdx b/docs/platforms/dart/guides/flutter/index.mdx index 4a95ab6fa49d8e..9a4e796784877d 100644 --- a/docs/platforms/dart/guides/flutter/index.mdx +++ b/docs/platforms/dart/guides/flutter/index.mdx @@ -162,6 +162,7 @@ try { ## Next Steps +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn about the features of Sentry's Flutter SDK - Add readable stack traces to errors - Add performance instrumentation to your app diff --git a/docs/platforms/dotnet/guides/android/index.mdx b/docs/platforms/dotnet/guides/android/index.mdx index 9e310f511e2652..6382f4c9bec89f 100644 --- a/docs/platforms/dotnet/guides/android/index.mdx +++ b/docs/platforms/dotnet/guides/android/index.mdx @@ -118,3 +118,7 @@ The default value is 1000. This snippet includes an intentional error, so you can test that everything is working as soon as you set it up. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/apple/index.mdx b/docs/platforms/dotnet/guides/apple/index.mdx index 4f0e670b90103f..fce68d02fa330e 100644 --- a/docs/platforms/dotnet/guides/apple/index.mdx +++ b/docs/platforms/dotnet/guides/apple/index.mdx @@ -84,3 +84,7 @@ The .NET for iOS, macOS, and Mac Catalyst integration is part of [Sentry](/platf This snippet includes an intentional error, so you can test that everything is working as soon as you set it up. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/aspnet/index.mdx b/docs/platforms/dotnet/guides/aspnet/index.mdx index 9dc391e97ef7b7..01a23442670edd 100644 --- a/docs/platforms/dotnet/guides/aspnet/index.mdx +++ b/docs/platforms/dotnet/guides/aspnet/index.mdx @@ -129,3 +129,7 @@ For information about Troubleshooting, please visit the [troubleshooting](troubl ## Samples - A [sample with ASP.NET and EF 6](https://github.com/getsentry/examples/tree/master/dotnet/AspNetMvc5Ef6) and additional samples of the [.NET SDKs](https://github.com/getsentry/examples/tree/master/dotnet) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/aspnetcore/index.mdx b/docs/platforms/dotnet/guides/aspnetcore/index.mdx index a97db264a34792..4b88c8a007593b 100644 --- a/docs/platforms/dotnet/guides/aspnetcore/index.mdx +++ b/docs/platforms/dotnet/guides/aspnetcore/index.mdx @@ -273,3 +273,7 @@ Sentry.init({ ``` The [AspNetCore.Mvc sample](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.AspNetCore.Mvc) uses this approach. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/aws-lambda/index.mdx b/docs/platforms/dotnet/guides/aws-lambda/index.mdx index 82e03fe40923da..cd73af06cf8560 100644 --- a/docs/platforms/dotnet/guides/aws-lambda/index.mdx +++ b/docs/platforms/dotnet/guides/aws-lambda/index.mdx @@ -74,3 +74,7 @@ This snippet includes an intentional error, so you can test that everything is w ## Samples - Our [samples on GitHub](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.Aws.Lambda.AspNetCoreServer) demonstrate Sentry on AWS Lambda. (**C#**) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx b/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx index cf1ebc6774d225..0c2ee421763dd9 100644 --- a/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx +++ b/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx @@ -98,3 +98,7 @@ This snippet includes an intentional error, so you can test that everything is w ## Samples - [Azure Functions Sample](https://github.com/getsentry/sentry-dotnet/blob/main/samples/Sentry.Samples.OpenTelemetry.AzureFunctions/) demonstrates Sentry with Azure Functions Isolated Worker SDK. (**C#**) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/blazor-webassembly/index.mdx b/docs/platforms/dotnet/guides/blazor-webassembly/index.mdx index c7163bd6256526..47238187d469fc 100644 --- a/docs/platforms/dotnet/guides/blazor-webassembly/index.mdx +++ b/docs/platforms/dotnet/guides/blazor-webassembly/index.mdx @@ -60,3 +60,7 @@ This snippet includes an intentional error, so you can test that everything is w ## Samples - This [integration with Blazor WebAssembly](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.AspNetCore.Blazor.Wasm) sample demonstrates using Sentry with Blazor WebAssembly. (**C#**) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/entityframework/index.mdx b/docs/platforms/dotnet/guides/entityframework/index.mdx index 3649699b783d26..5cde6ef1229ea2 100644 --- a/docs/platforms/dotnet/guides/entityframework/index.mdx +++ b/docs/platforms/dotnet/guides/entityframework/index.mdx @@ -107,3 +107,7 @@ This snippet includes an intentional error, so you can test that everything is w Check out a complete working [sample](https://github.com/getsentry/sentry-dotnet-ef/tree/master/samples/Sentry.Samples.AspNet.Mvc) to see it in action. ![Sample breadcrumbs in Sentry](./img/dotnet-entityframework.png) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/extensions-logging/index.mdx b/docs/platforms/dotnet/guides/extensions-logging/index.mdx index 8ca30d77f97986..54e397b2a4290f 100644 --- a/docs/platforms/dotnet/guides/extensions-logging/index.mdx +++ b/docs/platforms/dotnet/guides/extensions-logging/index.mdx @@ -175,3 +175,7 @@ This snippet includes an intentional error, so you can test that everything is w - A [simple example](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.ME.Logging) using simply the `LoggerFactory`. - An [example](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.GenericHost) using the _generic host_. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/google-cloud-functions/index.mdx b/docs/platforms/dotnet/guides/google-cloud-functions/index.mdx index 790e9de7f9a50a..9f5a88864acf8c 100644 --- a/docs/platforms/dotnet/guides/google-cloud-functions/index.mdx +++ b/docs/platforms/dotnet/guides/google-cloud-functions/index.mdx @@ -166,3 +166,7 @@ This snippet includes an intentional error, so you can test that everything is w - [Google Cloud Functions sample](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.Google.Cloud.Functions) - For [more samples](https://github.com/getsentry/sentry-dotnet-samples) of the .NET SDKs. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/log4net/index.mdx b/docs/platforms/dotnet/guides/log4net/index.mdx index 31712fac53d066..1c239fea255b01 100644 --- a/docs/platforms/dotnet/guides/log4net/index.mdx +++ b/docs/platforms/dotnet/guides/log4net/index.mdx @@ -66,3 +66,7 @@ This snippet includes an intentional error, so you can test that everything is w For a [sample app.config](https://github.com/getsentry/sentry-dotnet/blob/main/samples/Sentry.Samples.Log4Net/app.config) or a complete working [sample](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.Log4Net) to see it in action. ![Sample event in Sentry](./img/log4net-sample.gif) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/maui/index.mdx b/docs/platforms/dotnet/guides/maui/index.mdx index 50201bf4e2987c..bd422b0b246cb9 100644 --- a/docs/platforms/dotnet/guides/maui/index.mdx +++ b/docs/platforms/dotnet/guides/maui/index.mdx @@ -123,3 +123,7 @@ Use caution when enabling, as such values may contain personally identifiable in This snippet includes an intentional error, so you can test that everything is working as soon as you set it up. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/nlog/index.mdx b/docs/platforms/dotnet/guides/nlog/index.mdx index b17176d4ced468..1e4fae1abe5a7a 100644 --- a/docs/platforms/dotnet/guides/nlog/index.mdx +++ b/docs/platforms/dotnet/guides/nlog/index.mdx @@ -207,3 +207,7 @@ This snippet includes an intentional error, so you can test that everything is w - A [simple example](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.NLog). - Example of [advanced configuration](configuration/advanced-configuration-example) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/serilog/index.mdx b/docs/platforms/dotnet/guides/serilog/index.mdx index b9fc0ad6c85aa7..767c129dc6ecd9 100644 --- a/docs/platforms/dotnet/guides/serilog/index.mdx +++ b/docs/platforms/dotnet/guides/serilog/index.mdx @@ -97,3 +97,7 @@ This snippet includes an intentional error, so you can test that everything is w - A [simple example](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.Serilog). - An [example with ASP.NET Core](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.AspNetCore.Serilog). + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/winforms/index.mdx b/docs/platforms/dotnet/guides/winforms/index.mdx index 20b2ccd6b7d6dd..8cbd6de571746f 100644 --- a/docs/platforms/dotnet/guides/winforms/index.mdx +++ b/docs/platforms/dotnet/guides/winforms/index.mdx @@ -235,3 +235,7 @@ This snippet includes an intentional error, so you can test that everything is w ## Resources [Discussion on GitHub `Application.SetUnhandledExceptionMode`](https://github.com/getsentry/sentry-dotnet/issues/176) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/winui/index.mdx b/docs/platforms/dotnet/guides/winui/index.mdx index beb9ca8e3f0a35..b2d9a8d58a816e 100644 --- a/docs/platforms/dotnet/guides/winui/index.mdx +++ b/docs/platforms/dotnet/guides/winui/index.mdx @@ -156,3 +156,7 @@ sealed partial class App : Application This snippet includes an intentional error, so you can test that everything is working as soon as you set it up. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/wpf/index.mdx b/docs/platforms/dotnet/guides/wpf/index.mdx index 17bcf507ee8436..a73c37958c4022 100644 --- a/docs/platforms/dotnet/guides/wpf/index.mdx +++ b/docs/platforms/dotnet/guides/wpf/index.mdx @@ -77,3 +77,7 @@ public partial class App : Application This snippet includes an intentional error, so you can test that everything is working as soon as you set it up. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/guides/xamarin/index.mdx b/docs/platforms/dotnet/guides/xamarin/index.mdx index 4dd41a94aad029..2f1cf14199e4be 100644 --- a/docs/platforms/dotnet/guides/xamarin/index.mdx +++ b/docs/platforms/dotnet/guides/xamarin/index.mdx @@ -92,3 +92,7 @@ For information about Troubleshooting, please visit the [troubleshooting](troubl ## Samples - An [example](https://github.com/getsentry/sentry-xamarin/tree/main/Samples) using Xamarin Forms and most of the SDK features. (**Android, iOS, UWP**) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/dotnet/index.mdx b/docs/platforms/dotnet/index.mdx index d4da60e9d2c83e..b8181ba3ec7ae9 100644 --- a/docs/platforms/dotnet/index.mdx +++ b/docs/platforms/dotnet/index.mdx @@ -89,3 +89,7 @@ SentrySdk.Init(options => This snippet includes an intentional error, so you can test that everything is working as soon as you set it up. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/elixir/index.mdx b/docs/platforms/elixir/index.mdx index 0fff6c05aae940..21af83ed257fb0 100644 --- a/docs/platforms/elixir/index.mdx +++ b/docs/platforms/elixir/index.mdx @@ -40,3 +40,7 @@ Learn more about manually capturing an error or message in our To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/go/common/index.mdx b/docs/platforms/go/common/index.mdx index 4179c4a200eee8..fccb464507e6ec 100644 --- a/docs/platforms/go/common/index.mdx +++ b/docs/platforms/go/common/index.mdx @@ -33,3 +33,7 @@ Learn more about manually capturing an error or message in our To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/go/guides/echo/index.mdx b/docs/platforms/go/guides/echo/index.mdx index c083f518b7e045..60990f48044516 100644 --- a/docs/platforms/go/guides/echo/index.mdx +++ b/docs/platforms/go/guides/echo/index.mdx @@ -136,3 +136,7 @@ sentry.Init(sentry.ClientOptions{ }, }) ``` + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/go/guides/fasthttp/index.mdx b/docs/platforms/go/guides/fasthttp/index.mdx index 167a91fb81527f..f929e6e9b88319 100644 --- a/docs/platforms/go/guides/fasthttp/index.mdx +++ b/docs/platforms/go/guides/fasthttp/index.mdx @@ -144,3 +144,7 @@ sentry.Init(sentry.ClientOptions{ }, }) ``` + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/go/guides/fiber/index.mdx b/docs/platforms/go/guides/fiber/index.mdx index 3a3128125ad7ca..acc99fc0511d22 100644 --- a/docs/platforms/go/guides/fiber/index.mdx +++ b/docs/platforms/go/guides/fiber/index.mdx @@ -135,3 +135,7 @@ sentry.Init(sentry.ClientOptions{ }, }) ``` + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/go/guides/gin/index.mdx b/docs/platforms/go/guides/gin/index.mdx index 54e811ceb91481..a1024f85b601e6 100644 --- a/docs/platforms/go/guides/gin/index.mdx +++ b/docs/platforms/go/guides/gin/index.mdx @@ -130,3 +130,7 @@ sentry.Init(sentry.ClientOptions{ }, }) ``` + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/go/guides/http/index.mdx b/docs/platforms/go/guides/http/index.mdx index bf03bbb552308d..6d50fbf2c28a0a 100644 --- a/docs/platforms/go/guides/http/index.mdx +++ b/docs/platforms/go/guides/http/index.mdx @@ -143,3 +143,7 @@ sentry.Init(sentry.ClientOptions{ }, }) ``` + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/go/guides/iris/index.mdx b/docs/platforms/go/guides/iris/index.mdx index 473b819039f399..e1dc4b2acab8d9 100644 --- a/docs/platforms/go/guides/iris/index.mdx +++ b/docs/platforms/go/guides/iris/index.mdx @@ -130,3 +130,7 @@ sentry.Init(sentry.ClientOptions{ }, }) ``` + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/go/guides/logrus/index.mdx b/docs/platforms/go/guides/logrus/index.mdx index b05fcec5dcba43..a16a111e49c51b 100644 --- a/docs/platforms/go/guides/logrus/index.mdx +++ b/docs/platforms/go/guides/logrus/index.mdx @@ -182,3 +182,7 @@ if client != nil { ## Logs For comprehensive logging setup with Logrus, including advanced configuration options and best practices, see the [Go Logs documentation](/platforms/go/logs/). The Logrus integration shown above provides seamless integration with Sentry's structured logging features. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/go/guides/negroni/index.mdx b/docs/platforms/go/guides/negroni/index.mdx index 7138f898e95aee..3cc5883ce26c2d 100644 --- a/docs/platforms/go/guides/negroni/index.mdx +++ b/docs/platforms/go/guides/negroni/index.mdx @@ -163,3 +163,7 @@ app.UseHandler(mux) http.ListenAndServe(":3000", app) ``` + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/go/guides/slog/index.mdx b/docs/platforms/go/guides/slog/index.mdx index fc8edfa8cafdc2..534e18f57dff31 100644 --- a/docs/platforms/go/guides/slog/index.mdx +++ b/docs/platforms/go/guides/slog/index.mdx @@ -88,3 +88,7 @@ logger.With("key.string", "value").Info("An error occurred") ## Logs For comprehensive logging setup with slog, including advanced configuration options and best practices, see the [Go Logs documentation](/platforms/go/logs/). The slog integration shown above provides seamless integration with Sentry's structured logging features. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/go/guides/zerolog/index.mdx b/docs/platforms/go/guides/zerolog/index.mdx index 4966c02d43a806..51e19f66d7aa58 100644 --- a/docs/platforms/go/guides/zerolog/index.mdx +++ b/docs/platforms/go/guides/zerolog/index.mdx @@ -159,3 +159,7 @@ This ensures that logs from specific contexts or threads use the appropriate Sen Use Zerolog as you normally would, and it will automatically send logs at or above the specified levels to Sentry. Note: Ensure Sentry is flushed before the application exits to avoid losing any pending events. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/godot/index.mdx b/docs/platforms/godot/index.mdx index f2ccb5b1a4c8fd..3757cad916acab 100644 --- a/docs/platforms/godot/index.mdx +++ b/docs/platforms/godot/index.mdx @@ -42,3 +42,7 @@ Learn more about manually capturing an error or message in our To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/java/common/index.mdx b/docs/platforms/java/common/index.mdx index 00ceed9ceb5520..19690d65913ec9 100644 --- a/docs/platforms/java/common/index.mdx +++ b/docs/platforms/java/common/index.mdx @@ -35,3 +35,7 @@ Learn more about manually capturing an error or message in our To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/java/guides/spring-boot/index.mdx b/docs/platforms/java/guides/spring-boot/index.mdx index 95da1d4a0037a2..d9a14e7b098aed 100644 --- a/docs/platforms/java/guides/spring-boot/index.mdx +++ b/docs/platforms/java/guides/spring-boot/index.mdx @@ -37,3 +37,7 @@ Learn more about manually capturing an error or message in our To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/java/guides/spring/index.mdx b/docs/platforms/java/guides/spring/index.mdx index c305185e86965b..e7a8eb447c32b2 100644 --- a/docs/platforms/java/guides/spring/index.mdx +++ b/docs/platforms/java/guides/spring/index.mdx @@ -37,3 +37,7 @@ Learn more about manually capturing an error or message in our To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/javascript/guides/angular/index.mdx b/docs/platforms/javascript/guides/angular/index.mdx index cf9d8b14f8921a..72389d55aa207e 100644 --- a/docs/platforms/javascript/guides/angular/index.mdx +++ b/docs/platforms/javascript/guides/angular/index.mdx @@ -80,6 +80,7 @@ At this point, you should have integrated Sentry into Angular application and sh Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Extend Sentry to your backend using one of our [SDKs](/) - Continue to customize your configuration - Make use of Angular-specific features diff --git a/docs/platforms/javascript/guides/aws-lambda/index.mdx b/docs/platforms/javascript/guides/aws-lambda/index.mdx index fa8592dba9e6eb..904ee6ddd79c00 100644 --- a/docs/platforms/javascript/guides/aws-lambda/index.mdx +++ b/docs/platforms/javascript/guides/aws-lambda/index.mdx @@ -52,3 +52,7 @@ export const handler = Sentry.wrapHandler(async (event, context) => { throw new Error("This is a test error"); })); ``` + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/javascript/guides/azure-functions/index.mdx b/docs/platforms/javascript/guides/azure-functions/index.mdx index 43eaf012d2c677..31ccdf7c9732fe 100644 --- a/docs/platforms/javascript/guides/azure-functions/index.mdx +++ b/docs/platforms/javascript/guides/azure-functions/index.mdx @@ -175,6 +175,7 @@ At this point, you should have integrated Sentry into your Azure Function and sh Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Continue to customize your configuration - Learn how to manually capture errors - Get familiar with [Sentry's product features](/) like tracing, insights, and alerts diff --git a/docs/platforms/javascript/guides/bun/index.mdx b/docs/platforms/javascript/guides/bun/index.mdx index 61e1ca8ef22365..4459845808df70 100644 --- a/docs/platforms/javascript/guides/bun/index.mdx +++ b/docs/platforms/javascript/guides/bun/index.mdx @@ -137,6 +137,7 @@ At this point, you should have integrated Sentry into your Bun application, whic Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Extend Sentry to your frontend using one of our [frontend SDKs](/) - Learn how to manually capture errors - Continue to customize your configuration diff --git a/docs/platforms/javascript/guides/capacitor/index.mdx b/docs/platforms/javascript/guides/capacitor/index.mdx index 992b2961079a82..0bd10a0c9fce7b 100644 --- a/docs/platforms/javascript/guides/capacitor/index.mdx +++ b/docs/platforms/javascript/guides/capacitor/index.mdx @@ -564,3 +564,7 @@ Learn more about manually capturing an error or message in our To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/javascript/guides/cloudflare/index.mdx b/docs/platforms/javascript/guides/cloudflare/index.mdx index 61829fcbe953b6..a07ef31f5753e7 100644 --- a/docs/platforms/javascript/guides/cloudflare/index.mdx +++ b/docs/platforms/javascript/guides/cloudflare/index.mdx @@ -221,6 +221,7 @@ At this point, you should have integrated Sentry and should already be sending d Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to [manually capture errors](/platforms/javascript/guides/cloudflare/usage/) - Continue to [customize your configuration](/platforms/javascript/guides/cloudflare/configuration/) - Make use of [Cloudflare-specific features](/platforms/javascript/guides/cloudflare/features) diff --git a/docs/platforms/javascript/guides/cordova/index.mdx b/docs/platforms/javascript/guides/cordova/index.mdx index 6f1e4980feb6ca..aa3f1381a23ca9 100644 --- a/docs/platforms/javascript/guides/cordova/index.mdx +++ b/docs/platforms/javascript/guides/cordova/index.mdx @@ -93,6 +93,7 @@ At this point, you should have integrated Sentry into your Cordova application a Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Continue to customize your configuration - Learn how to upload debug symbols to make sure your native stack traces are readable - Check our [Ionic support guide](/platforms/javascript/guides/cordova/ionic/) diff --git a/docs/platforms/javascript/guides/deno/index.mdx b/docs/platforms/javascript/guides/deno/index.mdx index 9198844a3c3630..80fbd940a5aa55 100644 --- a/docs/platforms/javascript/guides/deno/index.mdx +++ b/docs/platforms/javascript/guides/deno/index.mdx @@ -138,6 +138,7 @@ At this point, you should have integrated Sentry into your Deno application and Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Extend Sentry to your frontend using one of our [frontend SDKs](/) - Learn how to manually capture errors - Continue to customize your configuration diff --git a/docs/platforms/javascript/guides/electron/index.mdx b/docs/platforms/javascript/guides/electron/index.mdx index 360f7b83b329d1..188f2aff4c67b0 100644 --- a/docs/platforms/javascript/guides/electron/index.mdx +++ b/docs/platforms/javascript/guides/electron/index.mdx @@ -256,6 +256,7 @@ At this point, you should have integrated Sentry into your Electron application Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Continue to customize your configuration - Learn how to manually capture errors - Make use of Electron-specific features diff --git a/docs/platforms/javascript/guides/ember/index.mdx b/docs/platforms/javascript/guides/ember/index.mdx index df76bcee5c681d..079522d16fd8b6 100644 --- a/docs/platforms/javascript/guides/ember/index.mdx +++ b/docs/platforms/javascript/guides/ember/index.mdx @@ -176,6 +176,7 @@ At this point, you should have integrated Sentry into your Ember application and Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to [manually capture errors](/platforms/javascript/guides/ember/usage/) - Continue to [customize your configuration](/platforms/javascript/guides/ember/configuration/) - Get familiar with [Sentry's product features](/product/) like tracing, insights, and alerts diff --git a/docs/platforms/javascript/guides/firebase/index.mdx b/docs/platforms/javascript/guides/firebase/index.mdx index 5e75dc28723f90..caf9f38d480b97 100644 --- a/docs/platforms/javascript/guides/firebase/index.mdx +++ b/docs/platforms/javascript/guides/firebase/index.mdx @@ -184,6 +184,7 @@ At this point, you should have integrated Sentry into your Cloud Functions for F Now's a good time to customize your setup and look into more advanced topics: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Continue to customize your configuration - Learn how to manually capture errors - Get familiar with [Sentry's product features](/product/) like tracing, insights, and alerts diff --git a/docs/platforms/javascript/guides/gatsby/index.mdx b/docs/platforms/javascript/guides/gatsby/index.mdx index 9f89caca167934..4682ffd85df081 100644 --- a/docs/platforms/javascript/guides/gatsby/index.mdx +++ b/docs/platforms/javascript/guides/gatsby/index.mdx @@ -198,6 +198,7 @@ At this point, you should have integrated Sentry into your Gatsby application an Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Extend Sentry to your backend using one of our [SDKs](/) - Continue to customize your configuration - Learn how to manually capture errors diff --git a/docs/platforms/javascript/guides/gcp-functions/index.mdx b/docs/platforms/javascript/guides/gcp-functions/index.mdx index 1a1203edded552..fb63c7359fc707 100644 --- a/docs/platforms/javascript/guides/gcp-functions/index.mdx +++ b/docs/platforms/javascript/guides/gcp-functions/index.mdx @@ -132,6 +132,7 @@ At this point, you should have integrated Sentry into your Google Cloud Platform Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Continue to customize your configuration - Learn how to manually capture errors - Get familiar with [Sentry's product features](/product/) like tracing, insights, and alerts diff --git a/docs/platforms/javascript/guides/nestjs/index.mdx b/docs/platforms/javascript/guides/nestjs/index.mdx index 016bade28f9938..6ced340c9130db 100644 --- a/docs/platforms/javascript/guides/nestjs/index.mdx +++ b/docs/platforms/javascript/guides/nestjs/index.mdx @@ -106,6 +106,7 @@ At this point, you should have integrated Sentry into your Nest.js application a Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Extend Sentry to your frontend using one of our [frontend SDKs](/) - Learn how to [manually capture errors](/platforms/javascript/guides/nestjs/usage/) - Continue to [customize your configuration](/platforms/javascript/guides/nestjs/configuration/) diff --git a/docs/platforms/javascript/guides/nextjs/index.mdx b/docs/platforms/javascript/guides/nextjs/index.mdx index af9e5843b3d06c..be8906efafb7f0 100644 --- a/docs/platforms/javascript/guides/nextjs/index.mdx +++ b/docs/platforms/javascript/guides/nextjs/index.mdx @@ -335,6 +335,7 @@ Learn more about [Logs configuration](/platforms/javascript/guides/nextjs/logs/) You've successfully integrated Sentry into your Next.js application! Here's what to explore next: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - [Logs Integrations](/platforms/javascript/guides/nextjs/logs/#integrations) - Connect popular logging libraries like Pino, Winston, and Bunyan - [Distributed Tracing](/platforms/javascript/guides/nextjs/tracing/distributed-tracing/) - Trace requests across services and microservices - [AI Agent Monitoring](/platforms/javascript/guides/nextjs/ai-agent-monitoring/) - Monitor AI agents built with Vercel AI SDK, LangChain, and more diff --git a/docs/platforms/javascript/guides/nuxt/index.mdx b/docs/platforms/javascript/guides/nuxt/index.mdx index a950a2c6df1abe..2fe4b2165d7752 100644 --- a/docs/platforms/javascript/guides/nuxt/index.mdx +++ b/docs/platforms/javascript/guides/nuxt/index.mdx @@ -103,6 +103,7 @@ At this point, you should have integrated Sentry into your Nuxt application and Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to [manually capture errors](/platforms/javascript/guides/nuxt/usage/) - Continue to [customize your configuration](/platforms/javascript/guides/nuxt/configuration/) - Get familiar with [Sentry's product features](/product) like tracing, insights, and alerts diff --git a/docs/platforms/javascript/guides/react-router/index.mdx b/docs/platforms/javascript/guides/react-router/index.mdx index 8be24ca9d0fe76..7504409b216c7c 100644 --- a/docs/platforms/javascript/guides/react-router/index.mdx +++ b/docs/platforms/javascript/guides/react-router/index.mdx @@ -257,6 +257,7 @@ At this point, you should have integrated Sentry into your React Router Framewor Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to manually capture errors - Continue to customize your configuration - Get familiar with [Sentry's product features](/product/) like tracing, insights, and alerts diff --git a/docs/platforms/javascript/guides/react/index.mdx b/docs/platforms/javascript/guides/react/index.mdx index cb115f20469406..84db6936f704a8 100644 --- a/docs/platforms/javascript/guides/react/index.mdx +++ b/docs/platforms/javascript/guides/react/index.mdx @@ -440,6 +440,7 @@ For more help, see the Troubleshooting page You've successfully integrated Sentry into your React application! Here's what to explore next: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - [Session Replay](/platforms/javascript/guides/react/session-replay/) — Watch video-like reproductions of user sessions to debug errors in context - [Distributed Tracing](/platforms/javascript/guides/react/tracing/distributed-tracing/) — Trace requests from your React frontend to backend services - [Connect GitHub + Seer](/organization/integrations/source-code-mgmt/github/#installing-github) — Enable AI-powered [root cause analysis](/product/ai-in-sentry/seer/) by connecting your repository diff --git a/docs/platforms/javascript/guides/remix/index.mdx b/docs/platforms/javascript/guides/remix/index.mdx index b9655c17186b5f..0557f18f365721 100644 --- a/docs/platforms/javascript/guides/remix/index.mdx +++ b/docs/platforms/javascript/guides/remix/index.mdx @@ -103,6 +103,7 @@ At this point, you should have integrated Sentry into your Remix application and Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to [manually capture errors](/platforms/javascript/guides/remix/usage/) - Continue to [customize your configuration](/platforms/javascript/guides/remix/configuration/) - Get familiar with [Sentry's product features](/product/) like tracing, insights, and alerts diff --git a/docs/platforms/javascript/guides/solid/index.mdx b/docs/platforms/javascript/guides/solid/index.mdx index ec7de3f11d098e..5d09b87b95f5fd 100644 --- a/docs/platforms/javascript/guides/solid/index.mdx +++ b/docs/platforms/javascript/guides/solid/index.mdx @@ -192,6 +192,7 @@ At this point, you should have integrated Sentry into your Solid application and Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Extend Sentry to your backend using one of our [SDKs](/) - Continue to customize your configuration - Make use of Solid-specific features diff --git a/docs/platforms/javascript/guides/solidstart/index.mdx b/docs/platforms/javascript/guides/solidstart/index.mdx index 6ec5ff0f228c14..4a5102cb757c9f 100644 --- a/docs/platforms/javascript/guides/solidstart/index.mdx +++ b/docs/platforms/javascript/guides/solidstart/index.mdx @@ -370,6 +370,7 @@ At this point, you should have integrated Sentry into your SolidStart applicatio Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to manually capture errors - Continue to customize your configuration - Learn how to make use of SolidStart-specific features diff --git a/docs/platforms/javascript/guides/svelte/index.mdx b/docs/platforms/javascript/guides/svelte/index.mdx index 6391d42ceb9ec7..53487083ddb3c4 100644 --- a/docs/platforms/javascript/guides/svelte/index.mdx +++ b/docs/platforms/javascript/guides/svelte/index.mdx @@ -283,6 +283,7 @@ At this point, you should have integrated Sentry into your Svelte application an Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Extend Sentry to your backend using one of our [SDKs](/) - Continue to customize your configuration - Make use of Svelte-specific features diff --git a/docs/platforms/javascript/guides/sveltekit/index.mdx b/docs/platforms/javascript/guides/sveltekit/index.mdx index efd2eca2fa6d74..b424771bcad858 100644 --- a/docs/platforms/javascript/guides/sveltekit/index.mdx +++ b/docs/platforms/javascript/guides/sveltekit/index.mdx @@ -73,6 +73,7 @@ At this point, you should have integrated Sentry into your SvelteKit application Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to [manually capture errors](/platforms/javascript/guides/sveltekit/usage/) - Continue to [customize your configuration](/platforms/javascript/guides/sveltekit/configuration/) - Learn how to [manually instrument](/platforms/javascript/guides/sveltekit/apis#load-function-instrumentation) SvelteKit-specific features diff --git a/docs/platforms/javascript/guides/tanstackstart-react/index.mdx b/docs/platforms/javascript/guides/tanstackstart-react/index.mdx index 568ff96a89837b..3c173eee88cefd 100644 --- a/docs/platforms/javascript/guides/tanstackstart-react/index.mdx +++ b/docs/platforms/javascript/guides/tanstackstart-react/index.mdx @@ -391,6 +391,7 @@ At this point, you should have integrated Sentry into your TanStack Start React Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to [manually capture errors](/platforms/javascript/guides/tanstackstart-react/usage/) - Continue to [customize your configuration](/platforms/javascript/guides/tanstackstart-react/configuration/) - Get familiar with [Sentry's product features](/product/) like tracing, insights, and alerts diff --git a/docs/platforms/javascript/guides/vue/index.mdx b/docs/platforms/javascript/guides/vue/index.mdx index 4d33cd06135771..6540aca0262a56 100644 --- a/docs/platforms/javascript/guides/vue/index.mdx +++ b/docs/platforms/javascript/guides/vue/index.mdx @@ -298,6 +298,7 @@ At this point, you should have integrated Sentry into your Vue application and s Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Extend Sentry to your backend using one of our [SDKs](/) - Continue to customize your configuration - Make use of Vue-specific features diff --git a/docs/platforms/javascript/guides/wasm/index.mdx b/docs/platforms/javascript/guides/wasm/index.mdx index e4bd6da115ce32..8afbd943711aa8 100644 --- a/docs/platforms/javascript/guides/wasm/index.mdx +++ b/docs/platforms/javascript/guides/wasm/index.mdx @@ -195,6 +195,7 @@ At this point, you should have integrated Sentry into your JavaScript applicatio Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Instrument your frontend and backend using our [SDKs](/) - Continue to [customize your configuration](/platforms/javascript/guides/wasm/configuration) - Learn how to [manually capture errors](/platforms/javascript/guides/wasm/usage) diff --git a/docs/platforms/kotlin/guides/compose-multiplatform/index.mdx b/docs/platforms/kotlin/guides/compose-multiplatform/index.mdx index cdcd623dda4357..df4fb6c4896583 100644 --- a/docs/platforms/kotlin/guides/compose-multiplatform/index.mdx +++ b/docs/platforms/kotlin/guides/compose-multiplatform/index.mdx @@ -55,3 +55,7 @@ For Android applications, you need to manually upload ProGuard mapping files usi ### iOS For iOS applications, follow the [Uploading Debug Symbols guide](/platforms/apple/guides/ios/dsym) to set up debug symbols upload. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/kotlin/guides/kotlin-multiplatform/index.mdx b/docs/platforms/kotlin/guides/kotlin-multiplatform/index.mdx index 856d3c362725a9..3ad27af0e2f892 100644 --- a/docs/platforms/kotlin/guides/kotlin-multiplatform/index.mdx +++ b/docs/platforms/kotlin/guides/kotlin-multiplatform/index.mdx @@ -41,6 +41,7 @@ To view and resolve the recorded error, log into [sentry.io](https://sentry.io) ## Next Steps +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn more about Sentry's Kotlin Multiplatform SDK features - Learn about different ways to initialize the SDK - See configuration options for the Kotlin Multiplatform Gradle Plugin diff --git a/docs/platforms/native/common/index.mdx b/docs/platforms/native/common/index.mdx index 982b872dd61cbb..eac4618542734d 100644 --- a/docs/platforms/native/common/index.mdx +++ b/docs/platforms/native/common/index.mdx @@ -31,3 +31,7 @@ Learn more about manually capturing an error or message in our To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/native/guides/breakpad/index.mdx b/docs/platforms/native/guides/breakpad/index.mdx index 250d49de8ac7e4..c493bcd73f3f24 100644 --- a/docs/platforms/native/guides/breakpad/index.mdx +++ b/docs/platforms/native/guides/breakpad/index.mdx @@ -85,3 +85,4 @@ bool UploadMinidump(std::string &path) { ); } ``` + diff --git a/docs/platforms/native/guides/crashpad/index.mdx b/docs/platforms/native/guides/crashpad/index.mdx index 752ac15adb7462..9be7076f096c4d 100644 --- a/docs/platforms/native/guides/crashpad/index.mdx +++ b/docs/platforms/native/guides/crashpad/index.mdx @@ -78,3 +78,4 @@ By default, the crashpad handler will limit uploads to one per hour. To disable ```cpp arguments.push_back("--no-rate-limit"); ``` + diff --git a/docs/platforms/native/guides/minidumps/index.mdx b/docs/platforms/native/guides/minidumps/index.mdx index a49d59487042b5..b25bab49078049 100644 --- a/docs/platforms/native/guides/minidumps/index.mdx +++ b/docs/platforms/native/guides/minidumps/index.mdx @@ -129,3 +129,4 @@ uploads. These limits are subject to future change and defined currently as: + diff --git a/docs/platforms/native/guides/wasm/index.mdx b/docs/platforms/native/guides/wasm/index.mdx index 64bc149ff84eb6..c3aa7b2178d027 100644 --- a/docs/platforms/native/guides/wasm/index.mdx +++ b/docs/platforms/native/guides/wasm/index.mdx @@ -106,3 +106,4 @@ Here is an example event for WebAssembly: } } ``` + diff --git a/docs/platforms/nintendo-switch/index.mdx b/docs/platforms/nintendo-switch/index.mdx index 99e92a848ad3d8..e9f6548c291c9c 100644 --- a/docs/platforms/nintendo-switch/index.mdx +++ b/docs/platforms/nintendo-switch/index.mdx @@ -15,3 +15,4 @@ You can also use Sentry's [Unity](/platforms/unity/game-consoles/) and [Unreal E ---- "Nintendo", "Nintendo Switch" are trademarks or registered trademarks of Nintendo. + diff --git a/docs/platforms/php/guides/laravel/index.mdx b/docs/platforms/php/guides/laravel/index.mdx index ce7e7a57e24072..8ee3666001a285 100644 --- a/docs/platforms/php/guides/laravel/index.mdx +++ b/docs/platforms/php/guides/laravel/index.mdx @@ -120,3 +120,7 @@ If you do leave Sentry enabled when developing or running tests, it's possible f If you're using Laravel's Forge platform to provision and deploy your PHP application, you can create a Sentry organization through [Forge](https://forge.laravel.com/docs/integrations/sentry.html). ![Sentry and Forge](./img/forge-sentry.png) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/php/guides/symfony/index.mdx b/docs/platforms/php/guides/symfony/index.mdx index 0d4d1a365c4d7d..9c0cff050cb2b9 100644 --- a/docs/platforms/php/guides/symfony/index.mdx +++ b/docs/platforms/php/guides/symfony/index.mdx @@ -67,3 +67,7 @@ class SentryTestController extends AbstractController ``` After you visit the `/_sentry-test` page, you can view and resolve the recorded error by logging into [sentry.io](https://sentry.io) and opening your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/php/index.mdx b/docs/platforms/php/index.mdx index c019bbc430af6d..da3aeed7159a5b 100644 --- a/docs/platforms/php/index.mdx +++ b/docs/platforms/php/index.mdx @@ -90,3 +90,7 @@ try { If you're using Laravel's Forge platform to provision and deploy your PHP application, you can create a Sentry organization through [Forge](https://forge.laravel.com/docs/integrations/sentry.html). ![Sentry and Forge](./img/forge-sentry.png) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/playstation/index.mdx b/docs/platforms/playstation/index.mdx index 50e4eadb257c86..e5b692d1f2caa4 100644 --- a/docs/platforms/playstation/index.mdx +++ b/docs/platforms/playstation/index.mdx @@ -20,3 +20,4 @@ Access to Sentry's error and crash reporting for consoles is a paid feature. We ---- "PlayStation", "PS5" are registered trademarks or trademarks of Sony Interactive Entertainment Inc. + diff --git a/docs/platforms/python/index.mdx b/docs/platforms/python/index.mdx index aca9f92b4c3a90..e7d7726ba99b86 100644 --- a/docs/platforms/python/index.mdx +++ b/docs/platforms/python/index.mdx @@ -101,3 +101,7 @@ To view and resolve the recorded error, log into [sentry.io](https://sentry.io) Not seeing your error in Sentry? Make sure you're running the above example from a file and not from a Python shell like IPython. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/react-native/index.mdx b/docs/platforms/react-native/index.mdx index bdb9394e641d09..e7fa2bb589f0d7 100644 --- a/docs/platforms/react-native/index.mdx +++ b/docs/platforms/react-native/index.mdx @@ -130,6 +130,7 @@ Sentry.nativeCrash(); ## Next Steps +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn about the features of Sentry's React Native SDK - Add readable stack traces to errors - Add Apple Privacy manifest diff --git a/docs/platforms/ruby/common/index.mdx b/docs/platforms/ruby/common/index.mdx index b687e4e39d26c3..6f1e062b0a0a6e 100644 --- a/docs/platforms/ruby/common/index.mdx +++ b/docs/platforms/ruby/common/index.mdx @@ -38,3 +38,7 @@ Learn more about manually capturing an error or message in our To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/rust/guides/actix-web/index.mdx b/docs/platforms/rust/guides/actix-web/index.mdx index beb77f680c0857..9dcda181c6cc23 100644 --- a/docs/platforms/rust/guides/actix-web/index.mdx +++ b/docs/platforms/rust/guides/actix-web/index.mdx @@ -93,3 +93,7 @@ Learn more about manually capturing an error or message in our To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/rust/guides/axum/index.mdx b/docs/platforms/rust/guides/axum/index.mdx index f045e23454db0b..dc4a83742116a3 100644 --- a/docs/platforms/rust/guides/axum/index.mdx +++ b/docs/platforms/rust/guides/axum/index.mdx @@ -105,3 +105,7 @@ Learn more about manually capturing an error or message in our To view and resolve the recorded panic, log into [sentry.io](https://sentry.io) and select your project. Select Issues, and then Errors & Outages in the sidebar, where you will find the newly created issue. Clicking on the issue's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/rust/guides/tracing/index.mdx b/docs/platforms/rust/guides/tracing/index.mdx index 9a5abe46436943..c779c3058551a1 100644 --- a/docs/platforms/rust/guides/tracing/index.mdx +++ b/docs/platforms/rust/guides/tracing/index.mdx @@ -122,3 +122,7 @@ To view and resolve the recorded error, log into [sentry.io](https://sentry.io) If you're using tracing (the Sentry feature), you can view the recorded traces and spans by selecting Explore, and then Traces in the sidebar. If you're using logs, you can view the recorded logs by selecting Explore, and then Logs in the sidebar. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/rust/index.mdx b/docs/platforms/rust/index.mdx index 116ad0d3b95a88..6548c8df738cb0 100644 --- a/docs/platforms/rust/index.mdx +++ b/docs/platforms/rust/index.mdx @@ -134,3 +134,7 @@ Conflicts could lead to UI warning messages in Sentry, as it can be interpreted - [Crates.io page](https://crates.io/crates/sentry) - [Bug Tracker](https://github.com/getsentry/sentry-rust/issues) - [GitHub Project](https://github.com/getsentry/sentry-rust) + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/unity/index.mdx b/docs/platforms/unity/index.mdx index fdf7385f89f0a0..a57321c352cdac 100644 --- a/docs/platforms/unity/index.mdx +++ b/docs/platforms/unity/index.mdx @@ -102,3 +102,7 @@ Learn more about manually capturing an error or message in our [Usage documentat To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/unreal/index.mdx b/docs/platforms/unreal/index.mdx index 31a2c13181a990..37a1f53e9a1c24 100644 --- a/docs/platforms/unreal/index.mdx +++ b/docs/platforms/unreal/index.mdx @@ -121,3 +121,7 @@ To view and resolve the recorded error, log into [sentry.io](https://sentry.io) ☝ This feature is supported on Windows, Linux, and Android. + +## Next Steps + +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup diff --git a/docs/platforms/xbox/index.mdx b/docs/platforms/xbox/index.mdx index f7216782be22cf..26c6298ea20346 100644 --- a/docs/platforms/xbox/index.mdx +++ b/docs/platforms/xbox/index.mdx @@ -19,3 +19,4 @@ Access to Sentry's error and crash reporting for consoles is a paid feature. We ---- "Microsoft", "Xbox" are trademarks of the Microsoft group of companies. + diff --git a/includes/apple-platform-getting-started.mdx b/includes/apple-platform-getting-started.mdx index a8a9d5741ab8ff..b326cccd289ab9 100644 --- a/includes/apple-platform-getting-started.mdx +++ b/includes/apple-platform-getting-started.mdx @@ -422,6 +422,7 @@ if (error) { ## Next Steps +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn more about Sentry's Apple SDK features - Add readable stack traces to errors - Add Apple Privacy manifest diff --git a/platform-includes/getting-started-complete/javascript.astro.mdx b/platform-includes/getting-started-complete/javascript.astro.mdx index dc08647b6af711..fa796a4a2d7ca1 100644 --- a/platform-includes/getting-started-complete/javascript.astro.mdx +++ b/platform-includes/getting-started-complete/javascript.astro.mdx @@ -403,6 +403,7 @@ Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Continue to customize your configuration - Learn how to manually capture errors - Learn more about [deploying Astro apps to Cloudflare Pages](/platforms/javascript/guides/cloudflare/frameworks/astro/) @@ -412,6 +413,7 @@ Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Continue to customize your configuration - Learn how to manually capture errors - Get familiar with [Sentry's product features](/product/) like tracing, insights, and alerts diff --git a/platform-includes/getting-started-complete/javascript.mdx b/platform-includes/getting-started-complete/javascript.mdx index 9cb7b43c75f818..8c73f92de24073 100644 --- a/platform-includes/getting-started-complete/javascript.mdx +++ b/platform-includes/getting-started-complete/javascript.mdx @@ -48,6 +48,7 @@ At this point, you should have integrated Sentry into your JavaScript applicatio Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Extend Sentry to your backend using one of our [SDKs](/) - Learn how to [manually capture errors](/platforms/javascript/usage/) - Continue to [customize your configuration](/platforms/javascript/configuration/) diff --git a/platform-includes/getting-started-complete/javascript.nuxt.mdx b/platform-includes/getting-started-complete/javascript.nuxt.mdx index fc065d8a9d4a9e..01be5fe060b2eb 100644 --- a/platform-includes/getting-started-complete/javascript.nuxt.mdx +++ b/platform-includes/getting-started-complete/javascript.nuxt.mdx @@ -369,6 +369,7 @@ At this point, you should have integrated Sentry into your Nuxt application and Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to [manually capture errors](/platforms/javascript/guides/nuxt/usage/) - Continue to [customize your configuration](/platforms/javascript/guides/nuxt/configuration/) - Get familiar with [Sentry's product features](/product) like tracing, insights, and alerts @@ -387,6 +388,7 @@ Now's a good time to customize your setup and look into more advanced topics. Ou +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to [manually capture errors](/platforms/javascript/guides/nuxt/usage/) - Continue to [customize your configuration](/platforms/javascript/guides/nuxt/configuration/) - Get familiar with [Sentry's product features](/product) like tracing, insights, and alerts diff --git a/platform-includes/getting-started-complete/javascript.remix.mdx b/platform-includes/getting-started-complete/javascript.remix.mdx index 3a54ead3a7851c..8ddeca706bce3b 100644 --- a/platform-includes/getting-started-complete/javascript.remix.mdx +++ b/platform-includes/getting-started-complete/javascript.remix.mdx @@ -460,6 +460,7 @@ At this point, you should have integrated Sentry into your Remix application and Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to manually capture errors - Continue to customize your configuration - Get familiar with [Sentry's product features](/product/) like tracing, insights, and alerts diff --git a/platform-includes/getting-started-complete/javascript.sveltekit.mdx b/platform-includes/getting-started-complete/javascript.sveltekit.mdx index 7e2fcf8e662f8d..38e87bbe37813a 100644 --- a/platform-includes/getting-started-complete/javascript.sveltekit.mdx +++ b/platform-includes/getting-started-complete/javascript.sveltekit.mdx @@ -461,6 +461,7 @@ Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to [manually capture errors](/platforms/javascript/guides/sveltekit/usage/) - Continue to [customize your configuration](/platforms/javascript/guides/sveltekit/configuration/) - Learn how to [manually instrument](/platforms/javascript/guides/sveltekit/apis#load-function-instrumentation) SvelteKit-specific features @@ -478,6 +479,7 @@ Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Learn how to [manually capture errors](/platforms/javascript/guides/cloudflare/usage/) - Continue to [customize your configuration](/platforms/javascript/guides/cloudflare/configuration/) - Get familiar with [Sentry's product features](/product) like tracing, insights, and alerts diff --git a/platform-includes/getting-started-node/javascript.mdx b/platform-includes/getting-started-node/javascript.mdx index 7a73dc5eb6f6a5..82065334b18c07 100644 --- a/platform-includes/getting-started-node/javascript.mdx +++ b/platform-includes/getting-started-node/javascript.mdx @@ -83,6 +83,7 @@ At this point, you should have integrated Sentry into your application, which sh Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are: +- Explore [practical guides](/guides/) on what to monitor, log, track, and investigate after setup - Extend Sentry to your frontend using one of our [frontend SDKs](/) - Learn how to manually capture errors - Continue to customize your configuration diff --git a/src/components/sidebar/sidebarNavigation.tsx b/src/components/sidebar/sidebarNavigation.tsx index 88de1485506fc7..8c6e7acc86ed3b 100644 --- a/src/components/sidebar/sidebarNavigation.tsx +++ b/src/components/sidebar/sidebarNavigation.tsx @@ -12,6 +12,10 @@ import {docNodeToNavNode, getNavNodes} from './utils'; /** a root of `"some-root"` maps to the `/some-root/` url */ // todo: we should probably get rid of this const productSidebarItems = [ + { + title: 'Guides', + root: 'guides', + }, { title: 'Account Settings', root: 'account', diff --git a/src/metrics.ts b/src/metrics.ts index 92dbeec10edb3a..9ec480d5813900 100644 --- a/src/metrics.ts +++ b/src/metrics.ts @@ -143,6 +143,7 @@ export const DocMetrics = { */ export type PageType = // Main product docs (from productSidebarItems in sidebarNavigation.tsx) + | 'guides' // Guides | 'account' // Account Settings | 'organization' // Organization Settings | 'product' // Product Walkthroughs