Sentry Error Tracking Samples
Comprehensive Sentry error tracking and performance monitoring setup with SDK integrations for various platforms
Key Facts
- Category
- Error Monitoring
- Items
- 4
- Format Families
- json, audio
Sample Overview
Comprehensive Sentry error tracking and performance monitoring setup with SDK integrations for various platforms This sample set belongs to Error Monitoring and can be used to test related workflows inside Elysia Tools.
💻 Sentry JavaScript SDK Setup javascript
Complete JavaScript SDK configuration for browser and Node.js applications with error tracking and performance monitoring
// Sentry JavaScript SDK Configuration
// Install: npm install @sentry/browser @sentry/node @sentry/tracing
// Frontend Browser Setup
// sentry-browser.js
import * as Sentry from "@sentry/browser";
import { BrowserTracing } from "@sentry/tracing";
// Initialize Sentry for browser
Sentry.init({
dsn: "https://[email protected]/project-id",
// Environment
environment: process.env.NODE_ENV || "development",
// Release version
release: `my-app@${process.env.APP_VERSION || "1.0.0"}`,
// Performance monitoring
integrations: [
new BrowserTracing({
// Set custom tracing options
routingInstrumentation: Sentry.reactRouterV6Instrumentation(
React.useEffect,
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes
),
}),
],
// Performance settings
tracesSampleRate: 1.0, // Capture 100% of transactions for testing
// Error sampling
sampleRate: 1.0, // Capture 100% of errors
// Before send callback for error filtering/enhancement
beforeSend(event, hint) {
// Add custom context
event.contexts = {
...event.contexts,
app: {
name: "My Web App",
version: process.env.APP_VERSION,
buildNumber: process.env.BUILD_NUMBER
},
browser: {
cookiesEnabled: navigator.cookieEnabled,
language: navigator.language,
online: navigator.onLine,
platform: navigator.platform,
userAgent: navigator.userAgent
}
};
// Filter out certain errors
if (event.exception) {
const error = hint.originalException;
// Ignore non-critical errors
if (error.message && error.message.includes("Non-critical")) {
return null;
}
// Add custom tags
event.tags = {
...event.tags,
component: "frontend",
userId: getCurrentUserId()
};
}
return event;
},
// Debug mode for development
debug: process.env.NODE_ENV === "development",
// Enable user feedback dialog
beforeSend(event, hint) {
// Check if it's an exception
if (event.exception) {
event.event_id = Sentry.showReportDialog({
eventId: event.event_id,
title: "Something went wrong",
subtitle: "Our team has been notified. If you'd like to help, tell us what happened below.",
subtitle2: "If you prefer not to share this information, you can just close this dialog.",
labelName: "Name",
labelEmail: "Email",
labelComments: "What happened?",
labelClose: "Close",
labelSubmit: "Submit",
errorGeneric: "An unknown error occurred while submitting your report. Please try again.",
errorFormEntry: "Some fields were invalid. Please correct the errors and try again.",
successMessage: "Your feedback has been sent. Thank you!"
});
}
return event;
},
// User context (will be updated dynamically)
initialScope: {
tags: {
section: "main"
},
user: {
id: "anonymous"
}
}
});
// Set user context dynamically
function setUserContext(user) {
Sentry.setUser({
id: user.id,
email: user.email,
username: user.username,
ip_address: "{{auto}}"
});
}
// Clear user context
function clearUserContext() {
Sentry.setUser(null);
}
// Add custom tags
function addTags(tags) {
Sentry.configureScope((scope) => {
Object.entries(tags).forEach(([key, value]) => {
scope.setTag(key, value);
});
});
}
// Add breadcrumbs for user actions
function trackUserAction(action, data = {}) {
Sentry.addBreadcrumb({
category: "user",
message: action,
level: "info",
data: data
});
}
// Manual error capture with context
function captureError(error, context = {}) {
Sentry.withScope((scope) => {
// Add context data
Object.entries(context).forEach(([key, value]) => {
scope.setContext(key, value);
});
// Add tags
if (context.tags) {
Object.entries(context.tags).forEach(([key, value]) => {
scope.setTag(key, value);
});
}
// Capture the error
Sentry.captureException(error);
});
}
// Performance monitoring
function startTransaction(name, operation = "navigation") {
return Sentry.startTransaction({
name: name,
operation: operation,
});
}
// Custom performance example
function performExpensiveOperation() {
const transaction = Sentry.startTransaction({
name: "expensive-operation",
operation: "task"
});
try {
// Step 1: Data processing
const dataProcessingSpan = transaction.startChild({
op: "processing",
description: "Processing user data"
});
// Simulate data processing
const processedData = processUserData(getUserData());
dataProcessingSpan.finish();
// Step 2: API call
const apiCallSpan = transaction.startChild({
op: "http.client",
description: "API call to external service"
});
return fetch('/api/process', {
method: 'POST',
body: JSON.stringify(processedData)
}).then(response => {
apiCallSpan.setData("statusCode", response.status);
apiCallSpan.finish();
if (!response.ok) {
throw new Error(`API call failed: ${response.status}`);
}
return response.json();
});
} catch (error) {
Sentry.captureException(error);
throw error;
} finally {
transaction.finish();
}
}
// React Error Boundary component
import React from "react";
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
Sentry.withScope((scope) => {
scope.setContext("react", {
componentStack: errorInfo.componentStack
});
scope.setTag("react", "error-boundary");
Sentry.captureException(error);
});
}
render() {
if (this.state.hasError) {
return (
<div>
<h1>Something went wrong.</h1>
<p>We've been notified about this issue.</p>
<button onClick={() => this.setState({ hasError: false })}>
Try again
</button>
</div>
);
}
return this.props.children;
}
}
// Backend Node.js Setup
// sentry-server.js
const Sentry = require("@sentry/node");
const { nodeprofilerIntegration } = require("@sentry/profiling-node");
// Initialize Sentry for Node.js
Sentry.init({
dsn: "https://[email protected]/project-id",
environment: process.env.NODE_ENV || "development",
release: `my-api@${process.env.APP_VERSION || "1.0.0"}`,
// Performance monitoring
integrations: [
// Add HTTP request tracking
new Sentry.Integrations.Http({ tracing: true }),
// Express.js integration
new Sentry.Integrations.Express({ app }),
// Profiling integration
nodeprofilerIntegration()
],
// Performance settings
tracesSampleRate: 0.1, // Capture 10% of transactions
// Profiling
_experiments: {
// The sampling rate for profiling is relative to tracesSampleRate
profilesSampleRate: 0.1,
},
// Before send callback for server errors
beforeSend(event, hint) {
// Add server context
event.contexts = {
...event.contexts,
server: {
name: process.env.HOSTNAME || "unknown",
pid: process.pid,
platform: process.platform,
nodeVersion: process.version
}
};
// Sanitize sensitive data
if (event.request && event.request.headers) {
// Remove sensitive headers
delete event.request.headers.authorization;
delete event.request.headers.cookie;
delete event.request.headers["x-api-key"];
}
// Add user context if available in the request
if (hint && hint.request && hint.request.user) {
event.user = {
id: hint.request.user.id,
email: hint.request.user.email
};
}
return event;
},
// Custom event processor
eventProcessor(event) {
// Filter out health check errors
if (event.request && event.request.url && event.request.url.includes("/health")) {
return null;
}
return event;
}
});
// Express.js middleware setup
const express = require("express");
const app = express();
// Request handler
app.use(Sentry.Handlers.requestHandler());
// Tracing handler
app.use(Sentry.Handlers.tracingHandler());
// Example route with custom monitoring
app.get("/api/users/:id", async (req, res) => {
try {
// Add request context
Sentry.configureScope((scope) => {
scope.setTag("route", "/api/users/:id");
scope.setTag("method", "GET");
scope.setContext("request_params", {
userId: req.params.id,
query: req.query
});
});
// Add breadcrumb
Sentry.addBreadcrumb({
category: "http",
message: `Fetching user ${req.params.id}`,
level: "info"
});
const user = await database.findUserById(req.params.id);
if (!user) {
Sentry.captureMessage(`User ${req.params.id} not found`, "warning");
return res.status(404).json({ error: "User not found" });
}
// Set user context
Sentry.setUser({ id: user.id, email: user.email });
res.json({ user });
} catch (error) {
// Capture error with additional context
Sentry.withScope((scope) => {
scope.setContext("database_error", {
operation: "findUserById",
userId: req.params.id,
error_code: error.code
});
Sentry.captureException(error);
});
res.status(500).json({ error: "Internal server error" });
}
});
// Error handler
app.use(Sentry.Handlers.errorHandler());
// Fallback error handler
app.use(function onError(err, req, res, next) {
res.statusCode = 500;
res.end(res.sentry + "\n");
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
// Record deployment
Sentry.captureMessage("Application started", "info");
});
💻 Sentry Python SDK Integration python
Complete Python SDK setup for Django, Flask, and FastAPI applications with error tracking and performance monitoring
# Sentry Python SDK Configuration
# Install: pip install sentry-sdk[django,flask,fastapi]
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.flask import FlaskIntegration
from sentry_sdk.integrations.fastapi import FastApiIntegration
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
from sentry_sdk.integrations.celery import CeleryIntegration
from sentry_sdk.integrations.redis import RedisIntegration
import logging
# Common configuration
SENTRY_DSN = "https://[email protected]/project-id"
ENVIRONMENT = "production"
RELEASE = "[email protected]"
# Configure sentry_sdk with common settings
def configure_sentry(integrations=None):
"""Configure Sentry SDK with common settings"""
# Default integrations
default_integrations = [
SqlalchemyIntegration(),
RedisIntegration(),
]
if integrations:
default_integrations.extend(integrations)
sentry_sdk.init(
dsn=SENTRY_DSN,
environment=ENVIRONMENT,
release=RELEASE,
# Performance monitoring
traces_sample_rate=0.1,
# Error monitoring
sample_rate=1.0,
# Integrations
integrations=default_integrations,
# Before send callback for error filtering
before_send=before_send_filter,
# Before breadcrumb callback
before_breadcrumb=before_breadcrumb_filter,
# Ignore specific exceptions
ignore_errors=[
KeyboardInterrupt,
SystemExit,
"django.http.request.DisallowedHost",
],
# Server name
server_name=get_server_name(),
# Max breadcrumbs
max_breadcrumbs=100,
# Attach stack traces
attach_stacktrace=True,
)
def before_send_filter(event, hint):
"""Filter and enhance error events"""
# Add custom context
event["contexts"] = {
**event.get("contexts", {}),
"app": {
"version": RELEASE,
"environment": ENVIRONMENT,
"process_id": os.getpid(),
},
"system": {
"platform": sys.platform,
"python_version": sys.version,
}
}
# Add user context if available
if hasattr(g, 'user') and g.user:
event["user"] = {
"id": g.user.id,
"email": g.user.email,
"username": g.user.username,
}
# Sanitize sensitive data
if "request" in event:
sanitize_request_data(event["request"])
# Filter out health checks
if event.get("request", {}).get("url", "").endswith("/health/"):
return None
return event
def before_breadcrumb_filter(breadcrumb, hint):
"""Filter breadcrumb data"""
# Sanitize breadcrumb data
if breadcrumb.get("category") == "http":
data = breadcrumb.get("data", {})
if "url" in data:
# Remove query parameters from URLs
data["url"] = data["url"].split("?")[0]
return breadcrumb
def sanitize_request_data(request):
"""Remove sensitive data from request"""
sensitive_headers = ["authorization", "cookie", "x-api-key"]
sensitive_params = ["password", "token", "secret", "key"]
# Remove sensitive headers
if "headers" in request:
for header in sensitive_headers:
request["headers"].pop(header, None)
# Remove sensitive query parameters
if "query_string" in request:
query_string = request["query_string"]
for param in sensitive_params:
query_string = re.sub(f"{param}=[^&]*", f"{param}=[FILTERED]", query_string, flags=re.IGNORECASE)
request["query_string"] = query_string
# Django Integration
# sentry_django.py
from django.conf import settings
# Configure Sentry for Django
configure_sentry([
DjangoIntegration(
transaction_style="url",
middleware_spans=True,
signals_spans=True,
),
CeleryIntegration(
monitor_beat_tasks=True,
propagate_traces=True,
),
])
# Custom middleware for additional context
class SentryContextMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Add request context
with sentry_sdk.configure_scope() as scope:
scope.set_tag("request_id", get_request_id(request))
scope.set_context("request", {
"method": request.method,
"path": request.path,
"user_agent": request.META.get("HTTP_USER_AGENT"),
"remote_addr": request.META.get("REMOTE_ADDR"),
})
# Add user context if authenticated
if hasattr(request, 'user') and request.user.is_authenticated:
scope.set_user({
"id": request.user.id,
"email": request.user.email,
"username": request.user.username,
})
# Add additional business context
if hasattr(request, 'organization'):
scope.set_tag("organization", request.organization.id)
scope.set_context("organization", {
"id": request.organization.id,
"name": request.organization.name,
})
response = self.get_response(request)
return response
# Add to Django MIDDLEWARE
MIDDLEWARE = [
"path.to.SentryContextMiddleware",
# ... other middleware
]
# Django views with custom Sentry usage
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
import sentry_sdk
@require_http_methods(["GET"])
def user_profile(request, user_id):
"""User profile view with Sentry instrumentation"""
# Add custom breadcrumb
sentry_sdk.add_breadcrumb(
category="auth",
message=f"Accessing user profile: {user_id}",
level="info",
data={"user_id": user_id}
)
try:
# Custom transaction for profile loading
with sentry_sdk.start_transaction(
name="user_profile_load",
op="view",
data={"user_id": user_id}
):
# Database operation
with sentry_sdk.start_span(op="db", description="Fetch user from database"):
user = User.objects.get(id=user_id)
# Additional data fetching
with sentry_sdk.start_span(op="db", description="Fetch user profile data"):
profile = UserProfile.objects.get(user=user)
# Add context
with sentry_sdk.configure_scope() as scope:
scope.set_context("user_profile", {
"user_id": user.id,
"profile_complete": profile.is_complete,
"last_login": user.last_login,
})
scope.set_tag("user_type", user.user_type)
return JsonResponse({
"user": {
"id": user.id,
"name": user.get_full_name(),
"email": user.email,
"profile": profile.to_dict()
}
})
except User.DoesNotExist:
# Capture warning for missing user
sentry_sdk.capture_message(
f"User {user_id} not found",
level="warning",
tags={"endpoint": "user_profile", "action": "not_found"}
)
return JsonResponse({"error": "User not found"}, status=404)
except Exception as e:
# Capture exception with context
sentry_sdk.capture_exception(e)
with sentry_sdk.configure_scope() as scope:
scope.set_context("error_details", {
"user_id": user_id,
"endpoint": "user_profile",
"error_type": type(e).__name__,
})
return JsonResponse({"error": "Internal server error"}, status=500)
# Flask Integration
# sentry_flask.py
from flask import Flask, request, g
import sentry_sdk
# Configure Sentry for Flask
configure_sentry([
FlaskIntegration(
transaction_style="url",
),
])
app = Flask(__name__)
@app.before_request
def add_request_context():
"""Add request context to Sentry"""
with sentry_sdk.configure_scope() as scope:
scope.set_tag("request_id", generate_request_id())
scope.set_context("request", {
"method": request.method,
"path": request.path,
"user_agent": request.headers.get("User-Agent"),
"remote_addr": request.remote_addr,
})
@app.route("/api/orders", methods=["GET", "POST"])
def handle_orders():
"""Order handling with Sentry instrumentation"""
if request.method == "GET":
return get_orders()
else:
return create_order()
def get_orders():
"""Get orders with custom monitoring"""
# Add breadcrumb
sentry_sdk.add_breadcrumb(
category="orders",
message="Fetching orders",
level="info"
)
try:
# Custom transaction
with sentry_sdk.start_transaction(name="order_retrieval", op="http.server"):
# Database operation
with sentry_sdk.start_span(op="db.query", description="Fetch orders"):
orders = Order.query.filter_by(user_id=g.user.id).all()
# Add metrics
with sentry_sdk.configure_scope() as scope:
scope.set_tag("order_count", len(orders))
scope.set_metric("orders_retrieved", len(orders))
return jsonify({
"orders": [order.to_dict() for order in orders]
})
except DatabaseError as e:
# Capture with specific context
sentry_sdk.capture_exception(e)
with sentry_sdk.configure_scope() as scope:
scope.set_context("database_error", {
"query_type": "SELECT",
"table": "orders",
"user_id": getattr(g, 'user', {}).get('id'),
})
raise
def create_order():
"""Create order with monitoring"""
order_data = request.get_json()
# Validate input
if not order_data or "items" not in order_data:
sentry_sdk.capture_message(
"Invalid order data received",
level="warning",
extra={"data": order_data}
)
return jsonify({"error": "Invalid order data"}), 400
try:
with sentry_sdk.start_transaction(name="order_creation", op="business") as transaction:
# Add order context
transaction.set_data("order_value", calculate_order_value(order_data))
transaction.set_tag("payment_method", order_data.get("payment_method"))
# Create order
with sentry_sdk.start_span(op="db.insert", description="Create order"):
order = Order.create(order_data)
# Process payment
with sentry_sdk.start_span(op="external", description="Process payment"):
payment_result = process_payment(order)
# Record custom event
sentry_sdk.capture_message(
f"Order created successfully: {order.id}",
level="info",
tags={
"order_id": order.id,
"user_id": order.user_id,
"payment_method": order_data.get("payment_method")
}
)
return jsonify({
"order_id": order.id,
"status": "created"
}), 201
except PaymentError as e:
# Capture payment error
sentry_sdk.capture_exception(e)
with sentry_sdk.configure_scope() as scope:
scope.set_context("payment_error", {
"order_data": sanitize_order_data(order_data),
"error_code": e.code,
"gateway": e.gateway,
})
return jsonify({"error": "Payment failed"}), 400
# FastAPI Integration
# sentry_fastapi.py
from fastapi import FastAPI, Request, Depends
import sentry_sdk
# Configure Sentry for FastAPI
configure_sentry([
FastApiIntegration(
transaction_style="url",
),
])
app = FastAPI()
@app.middleware("http")
async def add_sentry_context(request: Request, call_next):
"""Add request context to Sentry"""
with sentry_sdk.configure_scope() as scope:
scope.set_tag("request_id", generate_request_id())
scope.set_context("request", {
"method": request.method,
"path": request.url.path,
"user_agent": request.headers.get("user-agent"),
"client_ip": request.client.host if request.client else None,
})
response = await call_next(request)
return response
# Celery Integration
# sentry_celery.py
from celery import Celery
import sentry_sdk
celery_app = Celery('tasks')
@celery_app.task
def send_email_notification(user_id, message_data):
"""Send email notification with Sentry monitoring"""
with sentry_sdk.start_transaction(name="send_email_notification", op="task"):
try:
# Add context
with sentry_sdk.configure_scope() as scope:
scope.set_tag("task", "email_notification")
scope.set_tag("user_id", user_id)
scope.set_tag("message_type", message_data.get("type"))
# Fetch user data
with sentry_sdk.start_span(op="db.query", description="Fetch user"):
user = User.objects.get(id=user_id)
# Send email
with sentry_sdk.start_span(op="external", description="Send email"):
result = email_service.send(user.email, message_data)
# Record success
sentry_sdk.add_breadcrumb(
category="celery",
message=f"Email sent successfully to {user.email}",
level="info"
)
return {"status": "success", "email": user.email}
except Exception as e:
# Capture error with task context
sentry_sdk.capture_exception(e)
with sentry_sdk.configure_scope() as scope:
scope.set_context("celery_task", {
"task_name": "send_email_notification",
"user_id": user_id,
"message_type": message_data.get("type"),
"retry_count": send_email_notification.request.retries,
})
raise
# Custom performance monitoring
def monitor_slow_operation(operation_name, func, *args, **kwargs):
"""Monitor slow operations with Sentry"""
with sentry_sdk.start_transaction(name=operation_name, op="custom") as transaction:
try:
result = func(*args, **kwargs)
# Record operation metrics
duration = transaction.finish_timestamp - transaction.start_timestamp
with sentry_sdk.configure_scope() as scope:
scope.set_metric(f"{operation_name}_duration", duration)
return result
except Exception as e:
# Capture with operation context
sentry_sdk.capture_exception(e)
with sentry_sdk.configure_scope() as scope:
scope.set_context("operation", {
"name": operation_name,
"args_count": len(args),
"kwargs": list(kwargs.keys()),
})
raise
# Usage example
def process_large_dataset(dataset):
"""Example function with custom monitoring"""
def _process_data(data):
# Actual processing logic
return [item.upper() for item in data]
return monitor_slow_operation("data_processing", _process_data, dataset)
💻 Sentry Performance Monitoring javascript
Advanced performance monitoring with custom transactions, spans, and metrics for deep application insights
// Sentry Performance Monitoring Advanced Setup
// Install: npm install @sentry/tracing @sentry/browser
import * as Sentry from "@sentry/browser";
import { BrowserTracing } from "@sentry/tracing";
// Enhanced performance configuration
Sentry.init({
dsn: "https://[email protected]/project-id",
// Environment and release
environment: process.env.NODE_ENV,
release: `my-app@${process.env.APP_VERSION}`,
// Performance integrations
integrations: [
new BrowserTracing({
// Custom routing instrumentation
routingInstrumentation: (customRoutingInstrumentation) => ({
// Custom implementation
registerNavigationInstrumentation: () => {
// Track route changes
history.listen(({ location }) => {
const name = location.pathname + location.search;
Sentry.startTransaction({
name: name,
op: "navigation"
}).finish();
});
}
}),
// Enable user interaction tracing
userInteractionTracing: {
enabled: true,
eventTargets: [document.body],
keypressThresholdMs: 1000,
scrollTimeoutMs: 100
},
// Enable long task tracking
enableLongTask: true,
// Enable first paint/first contentful paint
enableFirstPaint: true
})
],
// Performance sampling
tracesSampleRate: calculateSampleRate(),
// Custom transaction context
initialScope: {
tags: {
section: "main",
platform: "web"
}
}
});
// Dynamic sampling rate based on user
function calculateSampleRate() {
const user = getCurrentUser();
if (!user) return 0.1; // 10% for anonymous users
// Higher sampling for paid users
if (user.subscription === "premium") return 0.5; // 50%
if (user.subscription === "pro") return 0.2; // 20%
return 0.05; // 5% for free users
}
// Custom transaction wrapper
class PerformanceTracker {
constructor(name, operation = "custom") {
this.transaction = Sentry.startTransaction({
name: name,
operation: operation,
data: {
page_url: window.location.href,
user_agent: navigator.userAgent,
timestamp: Date.now()
}
});
this.spans = new Map();
}
// Start a new span
startSpan(name, operation = "custom", data = {}) {
const span = this.transaction.startChild({
op: operation,
description: name,
data: data
});
this.spans.set(name, span);
return span;
}
// Finish a specific span
finishSpan(name) {
const span = this.spans.get(name);
if (span) {
span.finish();
this.spans.delete(name);
return true;
}
return false;
}
// Add data to transaction
setData(key, value) {
this.transaction.setData(key, value);
}
// Add tag to transaction
setTag(key, value) {
this.transaction.setTag(key, value);
}
// Finish the transaction
finish() {
// Finish any remaining spans
this.spans.forEach(span => span.finish());
// Add final metrics
this.transaction.setData("total_duration",
Date.now() - this.transaction.startTimestamp);
this.transaction.finish();
}
}
// Example usage: API request monitoring
class APIMonitor {
constructor(baseURL) {
this.baseURL = baseURL;
}
async request(method, endpoint, options = {}) {
const tracker = new PerformanceTracker(
`api-${method.toLowerCase()}-${endpoint}`,
"http.client"
);
try {
// Add request details
tracker.setData("request_method", method);
tracker.setData("request_endpoint", endpoint);
tracker.setTag("api_endpoint", endpoint);
tracker.setTag("http_method", method);
// Network span
const networkSpan = tracker.startSpan("network-request", "http.client", {
url: `${this.baseURL}${endpoint}`,
method: method
});
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: method,
...options
});
networkSpan.finish();
// Response processing span
const processingSpan = tracker.startSpan("response-processing", "http.client");
let data;
if (response.ok) {
data = await response.json();
} else {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
processingSpan.finish();
// Add response details
tracker.setData("response_status", response.status);
tracker.setData("response_size", JSON.stringify(data).length);
tracker.setTag("http_status_code", response.status.toString());
// Track specific business metrics
if (endpoint.includes("/orders")) {
tracker.setData("order_count", Array.isArray(data) ? data.length : 1);
tracker.setTag("has_orders", true);
}
tracker.finish();
return data;
} catch (error) {
// Add error context
tracker.setData("error_type", error.name);
tracker.setData("error_message", error.message);
tracker.setTag("error", true);
// Capture error in Sentry
Sentry.withScope((scope) => {
scope.setContext("api_error", {
method: method,
endpoint: endpoint,
error: error.message
});
Sentry.captureException(error);
});
tracker.finish();
throw error;
}
}
}
// Component performance monitoring
class ComponentMonitor {
static wrap(componentName, renderFunction) {
return function(...args) {
const tracker = new PerformanceTracker(
`component-${componentName}`,
"react.render"
);
try {
// Add component context
tracker.setTag("component_name", componentName);
tracker.setData("props_count", args[0] ? Object.keys(args[0]).length : 0);
// Render span
const renderSpan = tracker.startSpan("component-render", "react.render");
const result = renderFunction.apply(this, args);
renderSpan.finish();
// Post-render span (effects, etc.)
const postRenderSpan = tracker.startSpan("component-post-render", "react.effect");
// Use requestAnimationFrame to capture post-render work
requestAnimationFrame(() => {
postRenderSpan.finish();
tracker.finish();
});
return result;
} catch (error) {
tracker.setData("render_error", error.message);
tracker.setTag("render_error", true);
tracker.finish();
throw error;
}
};
}
}
// User interaction monitoring
class InteractionMonitor {
static init() {
// Click monitoring
document.addEventListener("click", (event) => {
const element = event.target.closest("[data-track]");
if (element) {
this.trackClick(element, event);
}
});
// Form submission monitoring
document.addEventListener("submit", (event) => {
if (event.target.tagName === "FORM") {
this.trackFormSubmission(event.target);
}
});
// Scroll monitoring (debounced)
let scrollTimeout;
window.addEventListener("scroll", () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => {
this.trackScrollDepth();
}, 100);
});
}
static trackClick(element, event) {
const tracker = new PerformanceTracker("user-click", "ui.click");
tracker.setTag("click_target", element.tagName.toLowerCase());
tracker.setTag("click_id", element.id || "");
tracker.setTag("click_class", element.className || "");
tracker.setData("click_x", event.clientX);
tracker.setData("click_y", event.clientY);
// Track specific interactions
if (element.matches("[data-track-cta]")) {
tracker.setTag("cta_click", true);
tracker.setData("cta_text", element.textContent.trim());
}
if (element.matches("[data-track-feature]")) {
const feature = element.dataset.trackFeature;
tracker.setTag("feature_interaction", true);
tracker.setData("feature_name", feature);
// Record custom event
Sentry.addBreadcrumb({
category: "ui.interaction",
message: `Feature used: ${feature}`,
level: "info",
data: {
feature: feature,
element: element.tagName.toLowerCase()
}
});
}
tracker.finish();
}
static trackFormSubmission(form) {
const tracker = new PerformanceTracker("form-submission", "ui.submit");
tracker.setTag("form_id", form.id || "");
tracker.setTag("form_class", form.className || "");
tracker.setData("field_count", form.elements.length);
// Track form type
if (form.matches(".login-form")) {
tracker.setTag("form_type", "login");
} else if (form.matches(".signup-form")) {
tracker.setTag("form_type", "signup");
} else if (form.matches(".contact-form")) {
tracker.setTag("form_type", "contact");
}
// Add breadcrumb
Sentry.addBreadcrumb({
category: "ui.interaction",
message: `Form submitted: ${tracker.getTransaction().tags.form_type || 'unknown'}`,
level: "info"
});
tracker.finish();
}
static trackScrollDepth() {
const scrollPercentage = Math.round(
(window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100
);
// Record significant scroll milestones
const milestones = [25, 50, 75, 90];
milestones.forEach(milestone => {
if (scrollPercentage >= milestone && !this.scrollMilestones?.[milestone]) {
this.scrollMilestones = this.scrollMilestones || {};
this.scrollMilestones[milestone] = true;
Sentry.addBreadcrumb({
category: "ui.interaction",
message: `Scroll depth reached: ${milestone}%`,
level: "info"
});
// Record custom metric
Sentry.metrics.increment(
"ui.scroll_depth_reached",
1,
{ tags: { milestone: milestone.toString() } }
);
}
});
}
}
// Resource loading monitoring
class ResourceMonitor {
static init() {
// Monitor critical resources
this.observeCriticalResources();
// Monitor API endpoints
this.monitorAPIPerformance();
}
static observeCriticalResources() {
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
entries.forEach(entry => {
if (entry.entryType === "resource") {
this.trackResourceLoading(entry);
}
});
});
observer.observe({ entryTypes: ["resource"] });
}
static trackResourceLoading(entry) {
// Only track certain resource types
const trackableTypes = ["script", "link", "img", "fetch", "xmlhttprequest"];
if (!trackableTypes.includes(entry.initiatorType)) return;
const tracker = new PerformanceTracker(
`resource-${entry.initiatorType}`,
"resource"
);
tracker.setTag("resource_type", entry.initiatorType);
tracker.setTag("resource_name", this.getResourceName(entry.name));
tracker.setData("resource_size", entry.transferSize || 0);
tracker.setData("load_time", entry.duration);
// Flag slow resources
if (entry.duration > 1000) { // 1 second threshold
tracker.setTag("slow_resource", true);
Sentry.captureMessage(
`Slow resource detected: ${entry.name} (${entry.duration}ms)`,
"warning"
);
}
// Flag failed resources
if (entry.transferSize === 0 && entry.duration > 0) {
tracker.setTag("resource_failed", true);
Sentry.captureMessage(
`Resource failed to load: ${entry.name}`,
"error"
);
}
tracker.finish();
}
static getResourceName(url) {
try {
const urlObj = new URL(url);
return urlObj.pathname.split('/').pop() || urlObj.pathname;
} catch {
return url;
}
}
static monitorAPIPerformance() {
// Track API performance metrics
setInterval(() => {
const apiCalls = Sentry.metrics.distribution(
"api.request_duration",
this.getRecentAPICallDurations(),
{ unit: "millisecond" }
);
const apiErrors = Sentry.metrics.increment(
"api.error_count",
this.getRecentAPIErrorCount(),
{ tags: { status: "error" } }
);
}, 30000); // Every 30 seconds
}
static getRecentAPICallDurations() {
// Implementation to collect recent API call durations
return this.apiCallDurations || [];
}
static getRecentAPIErrorCount() {
// Implementation to count recent API errors
return this.apiErrorCount || 0;
}
}
// Initialize all monitoring
function initPerformanceMonitoring() {
// Start interaction monitoring
InteractionMonitor.init();
// Start resource monitoring
ResourceMonitor.init();
// Record page load metrics
window.addEventListener("load", () => {
setTimeout(() => {
const perfData = performance.getEntriesByType("navigation")[0];
Sentry.addBreadcrumb({
category: "performance",
message: "Page load completed",
level: "info",
data: {
dom_content_loaded: perfData.domContentLoadedEventEnd - perfData.domContentLoadedEventStart,
load_complete: perfData.loadEventEnd - perfData.loadEventStart,
first_paint: getFirstPaintTime(),
first_contentful_paint: getFirstContentfulPaintTime()
}
});
}, 0);
});
}
// Utility functions
function getFirstPaintTime() {
const paintEntries = performance.getEntriesByType("paint");
const firstPaint = paintEntries.find(entry => entry.name === "first-paint");
return firstPaint ? Math.round(firstPaint.startTime) : 0;
}
function getFirstContentfulPaintTime() {
const paintEntries = performance.getEntriesByType("paint");
const fcp = paintEntries.find(entry => entry.name === "first-contentful-paint");
return fcp ? Math.round(fcp.startTime) : 0;
}
// Export monitoring classes
export {
PerformanceTracker,
APIMonitor,
ComponentMonitor,
InteractionMonitor,
ResourceMonitor,
initPerformanceMonitoring
};
💻 Sentry Custom Alerts and Rules json
Configure advanced alerting rules, notification integrations, and automated workflows for proactive error management
{
"alert_rules": [
{
"name": "Critical Error Spike",
"description": "Alert when critical errors increase significantly",
"conditions": [
{
"id": "error_rate_spike",
"interval": "5m",
"aggregation": "count()",
"field": "level",
"operator": "gt",
"value": 10,
"filters": [
{
"field": "level",
"value": "error",
"match": "exact"
},
{
"field": "environment",
"value": "production",
"match": "exact"
}
]
}
],
"actions": [
{
"type": "email",
"recipients": ["[email protected]", "[email protected]"],
"template": "critical_error_spike"
},
{
"type": "slack",
"channel": "#alerts-critical",
"template": "error_notification",
"mention_users": ["@devops", "@tech-lead"]
},
{
"type": "pagerduty",
"service_key": "your-pagerduty-key",
"severity": "critical"
},
{
"type": "jira",
"project": "BUG",
"issue_type": "Bug",
"priority": "Highest",
"assignee": "devops-team"
}
],
"thresholds": {
"critical": 50,
"warning": 20
},
"cooldown": "30m",
"enabled": true,
"tags": ["production", "critical", "error-spike"]
},
{
"name": "Performance Degradation",
"description": "Alert when application performance drops below threshold",
"conditions": [
{
"id": "slow_transactions",
"interval": "10m",
"aggregation": "p95(transaction.duration)",
"operator": "gt",
"value": 2000,
"filters": [
{
"field": "transaction.op",
"value": "http.server",
"match": "exact"
},
{
"field": "environment",
"value": "production",
"match": "exact"
}
]
}
],
"actions": [
{
"type": "slack",
"channel": "#performance-alerts",
"template": "performance_degradation"
},
{
"type": "email",
"recipients": ["[email protected]"],
"template": "performance_alert"
}
],
"thresholds": {
"critical": 3000,
"warning": 2000
},
"cooldown": "15m",
"enabled": true,
"tags": ["performance", "production"]
},
{
"name": "New Error Introduction",
"description": "Alert when new error types are detected",
"conditions": [
{
"id": "new_error_type",
"interval": "1h",
"aggregation": "count_distinct(exception.type)",
"operator": "gt",
"value": 1,
"filters": [
{
"field": "first_seen",
"value": ">= 1h",
"match": "age"
},
{
"field": "environment",
"value": "production",
"match": "exact"
}
]
}
],
"actions": [
{
"type": "slack",
"channel": "#development",
"template": "new_error_alert"
},
{
"type": "github",
"repository": "company/app",
"issue_title": "New Error Detected: {{error.type}}",
"issue_body": "New error type detected in production:\n\n{{error.message}}\n\nStack trace:\n{{error.stacktrace}}",
"assignees": ["development-team"]
}
],
"cooldown": "1h",
"enabled": true,
"tags": ["new-error", "production"]
},
{
"name": "Database Connection Issues",
"description": "Alert on database-related errors",
"conditions": [
{
"id": "database_errors",
"interval": "5m",
"aggregation": "count()",
"operator": "gt",
"value": 5,
"filters": [
{
"field": "exception.type",
"value": ["DatabaseError", "ConnectionError", "TimeoutError"],
"match": "contains"
}
]
}
],
"actions": [
{
"type": "pagerduty",
"service_key": "database-pagerduty-key",
"severity": "high"
},
{
"type": "email",
"recipients": ["[email protected]", "[email protected]"],
"template": "database_alert"
}
],
"thresholds": {
"critical": 20,
"warning": 5
},
"cooldown": "10m",
"enabled": true,
"tags": ["database", "infrastructure"]
},
{
"name": "User Experience Issues",
"description": "Alert on user-facing problems",
"conditions": [
{
"id": "ux_errors",
"interval": "10m",
"aggregation": "count()",
"operator": "gt",
"value": 10,
"filters": [
{
"field": "tags.ux_issue",
"value": "true",
"match": "exact"
},
{
"field": "user.id",
"value": "null",
"match": "not"
}
]
}
],
"actions": [
{
"type": "slack",
"channel": "#product-alerts",
"template": "ux_issue"
},
{
"type": "linear",
"team_id": "product-team-id",
"priority": "medium"
}
],
"cooldown": "20m",
"enabled": true,
"tags": ["user-experience", "customer-facing"]
},
{
"name": "Third-party Service Failures",
"description": "Alert on external service failures",
"conditions": [
{
"id": "external_service_errors",
"interval": "5m",
"aggregation": "count()",
"operator": "gt",
"value": 3,
"filters": [
{
"field": "transaction.op",
"value": "http.client",
"match": "exact"
},
{
"field": "http.response_code",
"value": ">= 500",
"match": "range"
}
]
}
],
"actions": [
{
"type": "email",
"recipients": ["[email protected]"],
"template": "external_service_failure"
},
{
"type": "statuspage",
"component_id": "external-api",
"status": "degraded_performance"
}
],
"cooldown": "15m",
"enabled": true,
"tags": ["external-services", "integrations"]
}
],
"notification_templates": {
"critical_error_spike": {
"subject": "🚨 Critical Error Spike Detected - {{error_count}} errors in last {{interval}}",
"body": `<h2>Critical Error Spike Alert</h2>
<p><strong>{{error_count}}</strong> critical errors detected in the last {{interval}}</p>
<h3>Error Details:</h3>
<ul>
<li><strong>Environment:</strong> {{environment}}</li>
<li><strong>Time Period:</strong> {{interval}}</li>
<li><strong>Error Rate:</strong> {{error_rate}} errors/minute</li>
<li><strong>Top Error:</strong> {{top_error.type}} - {{top_error.message}}</li>
</ul>
<h3>Recent Errors:</h3>
<table border="1" style="border-collapse: collapse;">
<tr>
<th>Time</th>
<th>Error Type</th>
<th>Message</th>
<th>User Impact</th>
</tr>
{{#each recent_errors}}
<tr>
<td>{{timestamp}}</td>
<td>{{exception.type}}</td>
<td>{{exception.message}}</td>
<td>{{user_impact}}</td>
</tr>
{{/each}}
</table>
<h3>Actions Required:</h3>
<ol>
<li>Check Sentry dashboard: {{sentry_url}}</li>
<li>Review recent deployments</li>
<li>Check infrastructure health</li>
<li>Communicate status to stakeholders</li>
</ol>
<p><a href="{{sentry_url}}">View in Sentry</a></p>`
},
"performance_degradation": {
"subject": "⚠️ Performance Degradation Detected - P95: {{p95_duration}}ms",
"body": `<h2>Performance Degradation Alert</h2>
<h3>Performance Metrics:</h3>
<ul>
<li><strong>P95 Response Time:</strong> {{p95_duration}}ms (threshold: {{threshold}}ms)</li>
<li><strong>P50 Response Time:</strong> {{p50_duration}}ms</li>
<li><strong>Slowest Transaction:</strong> {{slowest_transaction.name}} ({{slowest_transaction.duration}}ms)</li>
</ul>
<h3>Affected Endpoints:</h3>
<table>
<tr><th>Endpoint</th><th>P95 Time</th><th>Error Rate</th></tr>
{{#each slow_endpoints}}
<tr>
<td>{{transaction.name}}</td>
<td>{{duration}}ms</td>
<td>{{error_rate}}%</td>
</tr>
{{/each}}
</table>
<h3>Next Steps:</h3>
<ol>
<li>Review database query performance</li>
<li>Check external service response times</li>
<li>Analyze recent code changes</li>
<li>Consider scaling resources if needed</li>
</ol>`
},
"new_error_alert": {
"subject": "🆕 New Error Type Detected: {{error.type}}",
"body": `<h2>New Error Type Alert</h2>
<p>A new error type has been detected in production:</p>
<ul>
<li><strong>Error Type:</strong> {{exception.type}}</li>
<li><strong>Message:</strong> {{exception.message}}</li>
<li><strong>First Seen:</strong> {{first_seen}}</li>
<li><strong>Affected Users:</strong> {{affected_users}}</li>
<li><strong>Environment:</strong> {{environment}}</li>
</ul>
<h3>Stack Trace Preview:</h3>
<pre>{{exception.stacktrace | truncate: 500}}</pre>
<h3>Investigation Steps:</h3>
<ol>
<li>Review recent deployments that might have introduced this error</li>
<li>Check if this error affects critical user flows</li>
<li>Determine if immediate action is required</li>
<li>Create bug ticket if needed</li>
</ol>
<p><a href="{{sentry_url}}">View Error Details</a></p>`
},
"ux_issue": {
"subject": "😟 User Experience Issue - {{issue_count}} reports",
"body": `<h2>User Experience Issue Alert</h2>
<p><strong>{{issue_count}}</strong> user experience issues have been reported in the last {{interval}}.</p>
<h3>Issue Summary:</h3>
<ul>
<li><strong>Total Affected Users:</strong> {{affected_users}}</li>
<li><strong>Most Common Issue:</strong> {{common_issue}}</li>
<li><strong>User Feedback Score:</strong> {{ux_score}}/10</li>
</ul>
<h3>Recent User Reports:</h3>
{{#each user_reports}}
<div style="margin-bottom: 20px; padding: 10px; border: 1px solid #ccc;">
<p><strong>User:</strong> {{user.email}} (ID: {{user.id}})</p>
<p><strong>Issue:</strong> {{message}}</p>
<p><strong>Context:</strong> {{context}}</p>
<p><strong>Time:</strong> {{timestamp}}</p>
</div>
{{/each}}
<h3>Recommended Actions:</h3>
<ol>
<li>Prioritize issues affecting critical user flows</li>
<li>Reach out to affected users if needed</li>
<li>Update product team on potential feature impact</li>
<li>Consider temporary workarounds if issues are severe</li>
</ol>`
}
},
"integration_configs": {
"slack": {
"webhook_url": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
"default_channel": "#alerts",
"mention_users": ["@devops", "@oncall"],
"notification_threshold": "warning",
"resolve_notifications": true
},
"pagerduty": {
"service_key": "your-pagerduty-service-key",
"severity_mapping": {
"critical": "critical",
"warning": "high",
"info": "low"
},
"auto_resolve": true,
"grouping": true
},
"email": {
"smtp_server": "smtp.company.com",
"smtp_port": 587,
"default_recipients": ["[email protected]"],
"use_tls": true,
"from_address": "[email protected]"
},
"jira": {
"url": "https://company.atlassian.net",
"username": "sentry-bot",
"project_key": "BUG",
"default_issue_type": "Bug",
"auto_assign": true,
"default_priority": "Medium"
},
"github": {
"token": "your-github-token",
"repository": "company/app",
"auto_assign": true,
"default_labels": ["bug", "auto-generated"],
"default_milestone": "current-sprint"
},
"statuspage": {
"api_key": "your-statuspage-api-key",
"page_id": "your-statuspage-id",
"auto_update": true,
"notify_subscribers": true
},
"linear": {
"team_id": "your-linear-team-id",
"api_key": "your-linear-api-key",
"auto_create_issue": true,
"default_state": "Backlog",
"default_priority": "Medium"
}
},
"escalation_policies": [
{
"name": "Critical Production Issues",
"triggers": [
{
"rule_type": "error_count",
"threshold": 50,
"time_window": "5m",
"environment": "production"
},
{
"rule_type": "performance_degradation",
"threshold": "5000",
"metric": "p95_duration"
}
],
"steps": [
{
"wait_time": "0m",
"actions": ["slack_critical", "pagerduty_critical"]
},
{
"wait_time": "15m",
"actions": ["phone_call", "executive_notification"]
},
{
"wait_time": "30m",
"actions": ["war_room", "all_hands_notification"]
}
]
},
{
"name": "Non-Critical Issues",
"triggers": [
{
"rule_type": "error_count",
"threshold": 10,
"time_window": "30m"
}
],
"steps": [
{
"wait_time": "0m",
"actions": ["slack_warning", "email_team"]
},
{
"wait_time": "2h",
"actions": ["create_ticket"]
}
]
}
],
"maintenance_windows": [
{
"name": "Weekend Deployments",
"description": "Silence non-critical alerts during planned maintenance",
"schedule": {
"type": "weekly",
"days": ["Saturday", "Sunday"],
"start_time": "02:00",
"end_time": "06:00",
"timezone": "UTC"
},
"affected_rules": [
"performance_degradation",
"database_errors"
],
"critical_rules_enabled": true
},
{
"name": "Major Release Window",
"description": "Silence certain alerts during major releases",
"schedule": {
"type": "specific_dates",
"dates": ["2024-01-15", "2024-02-01"],
"start_time": "00:00",
"end_time": "23:59"
},
"affected_rules": [
"new_error_type",
"ux_issues"
]
}
]
}