Skip to main content

Source: ocean/docs/sentry-performance-monitoring.md | ✏️ Edit on GitHub

Sentry Performance Monitoring Guide

This guide covers the enhanced Sentry performance monitoring implementation in the Ocean application, focusing on tracking critical user journeys and business operations.

Overview

Our Sentry integration tracks performance metrics for:

  • Authentication flows (login, signup, OTP verification)
  • GraphQL operations (queries and mutations)
  • Core data operations (organizations, members, billing)
  • Stripe subscription management
  • Webhook processing

Frontend Performance Monitoring

1. Performance Monitoring Utilities

The core utilities are in /src/lib/performance-monitoring.ts:

import { PerformanceMonitor } from '@/lib/performance-monitoring'

// Start a transaction
const transactionId = PerformanceMonitor.startOperation('auth.login', {
description: 'User login via passwordless',
data: { method: 'passwordless' },
})

// End the transaction
PerformanceMonitor.endOperation(transactionId, {
status: 'success',
data: { userId: user.id },
})

2. Authentication Monitoring

All authentication operations are automatically tracked:

  • Login: Tracks passwordless login duration and success/failure
  • Signup: Monitors new user registration performance
  • OTP Verification: Measures OTP code verification time
  • Session Refresh: Tracks JWT token refresh operations

3. GraphQL Operation Tracking

GraphQL queries and mutations are automatically instrumented:

// Automatically tracked in useGraphQLQuery and useGraphQLMutation hooks
const { data } = useGraphQLQuery('myQuery', QUERY, variables)

Each GraphQL operation tracks:

  • Operation name and type (query/mutation)
  • Variables count and content
  • Success/error status
  • Network latency
  • Cache hit/miss status

4. Data Operation Monitoring

Core data operations are tracked with semantic names:

  • data.fetch: Loading lists (organizations, members)
  • data.create: Creating new resources
  • data.update: Updating existing resources
  • data.delete: Deleting resources

5. Stripe Operations

Subscription management operations are monitored:

  • stripe.checkout: Creating checkout sessions
  • stripe.subscription.update: Subscription changes (upgrade/downgrade/cancel)
  • stripe.webhook: Webhook event processing

Backend Performance Monitoring (Edge Functions)

1. Webhook Processing

The Stripe webhook handler tracks:

  • Event processing duration by event type
  • Success/failure rates
  • Organization update performance

2. Observability Configuration

Edge Functions use the shared observability module:

import { initSentry, Logger, trackOperation } from '../_shared/observability.ts'

// Initialize at function start
initSentry('function-name')

// Track operations
await trackOperation('operation_name', async () => {
// Your operation code
})

Performance Thresholds and Alerts

Automatic Alerts

Operations exceeding these thresholds trigger warnings:

  • 3 seconds: Slow operation warning
  • 10 seconds: Critical performance issue

Custom Metrics

The system tracks:

  • Operation duration histograms
  • Success/failure counters
  • Error rates by operation type

Cost Optimization

Sampling Rates

To control costs, we use intelligent sampling:

  • Production: 10% transaction sampling
  • Development: 100% transaction sampling
  • Session Replays: 1% normally, 100% on error

Filtering

Noise reduction filters exclude:

  • Browser extension errors
  • Network connectivity issues
  • Expected validation errors
  • Health check endpoints

Environment Variables

Frontend

  • VITE_SENTRY_DSN: Frontend Sentry DSN
  • SENTRY_ORG: Organization for source maps
  • SENTRY_PROJECT: Project for source maps
  • SENTRY_AUTH_TOKEN: Auth token for builds

Edge Functions

  • EDGE_FUNCTION_SENTRY_DSN or SENTRY_DSN: Backend Sentry DSN
  • ENVIRONMENT: Current environment (development/staging/production)

Usage Examples

Track a Custom Operation

import { PerformanceMonitor } from '@/lib/performance-monitoring'

// Option 1: Manual tracking
const transactionId = PerformanceMonitor.startOperation('report.generate', {
description: 'Generating monthly report',
data: { reportType: 'monthly', format: 'pdf' },
})

try {
const report = await generateReport()
PerformanceMonitor.endOperation(transactionId, {
status: 'success',
data: { pageCount: report.pages },
})
} catch (error) {
PerformanceMonitor.endOperation(transactionId, {
status: 'error',
error,
})
}

// Option 2: Async wrapper
const report = await PerformanceMonitor.trackAsyncOperation(
'report.generate',
() => generateReport(),
{
description: 'Generating monthly report',
data: { reportType: 'monthly' },
}
)

Track Nested Operations

const parentId = PerformanceMonitor.startOperation('data.fetch')

// Create child spans
const childSpan = PerformanceMonitor.createSpan('database_query', 'db.query', {
table: 'organizations',
})

// Perform operation
const data = await queryDatabase()

// End child span
childSpan?.end()

// End parent
PerformanceMonitor.endOperation(parentId, { status: 'success' })

Best Practices

  1. Semantic Naming: Use the predefined operation types for consistency
  2. Include Context: Add relevant data (IDs, counts, status) to operations
  3. Error Handling: Always capture errors with proper context
  4. Avoid PII: Never include personal information in tracking data
  5. Batch Operations: Track batch operations with item counts

Monitoring Dashboard

Access performance data in Sentry:

  1. Navigate to Performance → Transactions
  2. Filter by operation type or name
  3. Analyze P50, P75, P95 latencies
  4. Identify slow operations and bottlenecks
  5. Set up custom alerts for critical paths

Future Enhancements

Planned improvements include:

  • Real User Monitoring (RUM) integration
  • Custom performance budgets
  • Automated performance regression detection
  • Enhanced GraphQL field-level tracking
  • Database query performance tracking