Source:
ocean/docs/sentry-edge-functions-guide.md| ✏️ Edit on GitHub
Sentry Integration Guide for Edge Functions
Complete Sentry Coverage Implementation
1. Functions WITH Sentry ✅
handle-stripe-webhook- Full implementationprovision-tenant-resources- Full implementationprovision-user-resources- Full implementationcheck-tenant-health- Full implementationgraphql-v2- ✅ ADDED - Main API with distributed tracingstripe-billing- ✅ ADDED - Billing details with error trackingauth-hook- ✅ ADDED - Authentication events with security monitoringdatabase-hook- ✅ ADDED - Database changes with comprehensive trackingstripe-subscription- ✅ ADDED - Subscription management with Stripe operation trackingfeature-flags- ✅ ADDED - Feature flag evaluation with security checksstripe-portal- ✅ ADDED - Stripe customer portal with session trackingstripe-setup-intent- ✅ ADDED - Payment method setup with customer creation trackingstripe-products- ✅ ADDED - Product catalog with Stripe API trackingsync-stripe-data- ✅ ADDED - Data synchronization with comprehensive error trackingsync-user-to-stripe- ✅ ADDED - User profile sync with customer creation tracking
2. Functions NEEDING Sentry ❌
All functions now have Sentry integration!
Progress: 15/15 functions now have Sentry (🎉 100% COMPLETE! 🎉)
🚀 MISSION ACCOMPLISHED!
100% Sentry coverage achieved across ALL Edge Functions:
- ✅ Authentication & Security (auth-hook)
- ✅ Database Operations (database-hook)
- ✅ Main API (GraphQL-v2)
- ✅ Billing & Payments (stripe-billing, stripe-subscription, stripe-portal, stripe-setup-intent)
- ✅ Feature Management (feature-flags)
- ✅ Webhook Processing (handle-stripe-webhook)
- ✅ Product Management (stripe-products)
- ✅ Data Synchronization (sync-stripe-data, sync-user-to-stripe)
- ✅ Infrastructure Health (check-tenant-health, provision-tenant-resources, provision-user-resources)
3. Implementation Pattern
For EVERY Edge Function, add this at the top:
import {
initSentryWithTracing,
withTracing,
trackSupabaseOperation,
} from '../_shared/sentry-tracing.ts'
import { Logger } from '../_shared/observability.ts'
import * as Sentry from 'https://deno.land/x/sentry/index.mjs'
// Initialize Sentry
initSentryWithTracing('function-name')
const logger = new Logger({ functionName: 'function-name' })
// Wrap your serve function
Deno.serve(
withTracing('function-name', async (req) => {
try {
logger.info('Processing request', {
method: req.method,
url: req.url,
})
// Your function logic here
} catch (error) {
logger.error('Request failed', error, {
// Add relevant context
})
Sentry.withScope((scope) => {
scope.setTag('function.name', 'function-name')
// Add more context
Sentry.captureException(error)
})
return new Response(JSON.stringify({ error: 'Internal server error' }), {
status: 500,
headers: corsHeaders,
})
}
})
) // Note the double closing parenthesis!
4. Database Operations
Wrap ALL Supabase operations:
const { data, error } = await trackSupabaseOperation('select', 'table_name', async () =>
supabase.from('table_name').select('*').eq('id', id)
)
if (error) {
logger.error('Database operation failed', error, {
operation: 'select',
table: 'table_name',
id,
})
throw error
}
5. External API Calls
Use tracedFetch for all external APIs:
const response = await tracedFetch('https://api.stripe.com/v1/customers', {
method: 'POST',
headers: {
Authorization: `Bearer ${stripeKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
spanName: 'Create Stripe Customer',
})
6. Critical Context to Always Include
Sentry.withScope((scope) => {
// Always include
scope.setTag('function.name', 'function-name')
scope.setTag('environment', Deno.env.get('ENVIRONMENT') || 'development')
// User context if available
if (userId) scope.setUser({ id: userId })
// Organization context if available
if (organizationId) {
scope.setContext('organization', { id: organizationId })
}
// Operation specific context
scope.setContext('request', {
method: req.method,
url: req.url,
headers: Object.fromEntries(req.headers.entries()),
})
Sentry.captureException(error)
})
7. Performance Monitoring
Track slow operations:
import { trackOperation } from '../_shared/observability.ts'
const result = await trackOperation(
'critical_operation',
async () => {
// Your operation here
},
{
userId,
organizationId,
operationType: 'billing',
}
)
8. Distributed Tracing
The withTracing wrapper automatically:
- Extracts trace headers from frontend
- Creates spans for the entire function execution
- Propagates traces to downstream services
- Links frontend and backend errors
9. Cost Optimization
Our setup already includes:
- 10% transaction sampling in production
- Filtering of non-critical errors (CORS, validation)
- Removal of sensitive data
- Skipping health check endpoints
10. Testing Your Integration
After adding Sentry to a function:
-
Test Error Capture:
curl -X POST https://your-project.supabase.co/functions/v1/your-function \
-H "Content-Type: application/json" \
-d '{"test": "error"}' -
Check Sentry Dashboard:
- Errors should appear within seconds
- Check transaction traces show full request flow
- Verify context includes user/org data
-
Verify Distributed Tracing:
- Frontend errors should link to Edge Function traces
- Database operations should appear as child spans
Priority Implementation Order
- auth-hook - Auth errors are critical
- database-hook - Database errors affect all operations
- stripe-subscription - Revenue impacting
- stripe-portal - Customer facing payment errors
- feature-flags - Affects feature rollouts
- All other Stripe functions
Benefits of Full Coverage
- Complete Error Visibility: See errors across entire stack
- Faster Debugging: Distributed traces show exact failure point
- Proactive Monitoring: Catch errors before customers report
- Performance Insights: Identify slow database queries and API calls
- Security Monitoring: Track auth failures and suspicious patterns
With full Sentry coverage, you'll have complete observability across your entire application!