🎯 Exemplos recomendados
Balanced sample collections from various categories for you to explore
Exemplos Sentry Error Tracking
Configuração completa Sentry error tracking e performance monitoring com integrações SDK para várias plataformas
💻 Configuração Sentry JavaScript SDK javascript
🟡 intermediate
⭐⭐⭐
Configuração completa SDK JavaScript para navegador e Node.js com error tracking e performance monitoring
⏱️ 30 min
🏷️ sentry, javascript, react, node.js, monitoring, error-tracking
Prerequisites:
JavaScript/Node.js, npm, Sentry account
// 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");
});
💻 Integração Sentry Python SDK python
🟡 intermediate
⭐⭐⭐
Configuração completa SDK Python para aplicações Django, Flask e FastAPI com error tracking e performance monitoring
⏱️ 35 min
🏷️ sentry, python, django, flask, fastapi, monitoring
Prerequisites:
Python, Django/Flask/FastAPI, pip, Sentry account
# 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
🔴 complex
⭐⭐⭐⭐
Monitoring de performance avançado com transações personalizadas, spans e métricas para insights profundos de aplicações
⏱️ 50 min
🏷️ sentry, performance, tracing, monitoring, profiling
Prerequisites:
JavaScript, Sentry SDK, Performance concepts
// 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: this.getFirstPaintTime(),
first_contentful_paint: this.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
};
💻 Alertas e Regras Personalizadas Sentry json
🔴 complex
⭐⭐⭐⭐⭐
Configurar regras de alertas avançadas, integrações de notificação e workflows automatizados para gestão proativa de erros
⏱️ 60 min
🏷️ sentry, alerts, monitoring, notifications, automation
Prerequisites:
Sentry account, Alerting concepts, Webhook knowledge
{
"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"
]
}
]
}