Elysia Tools

在一个清晰的工作台里浏览工具、案例、可视化和主题指南。

热门分类

专题

语言
ZHESPTRUFRDEEN

Elysia Tools

导航

错误监控

Sentry 错误追踪示例

全面的 Sentry 错误追踪和性能监控设置,包含各种平台的 SDK 集成

案例

这个案例集合中的条目

代码javascript中等

Sentry JavaScript SDK 设置

完整的浏览器和 Node.js 应用程序 JavaScript SDK 配置,包含错误追踪和性能监控

难度

6/10

预计时间

30 min

标签

sentry, javascript, react, node.js, monitoring, error-tracking

前置条件

JavaScript/Node.js, npm, Sentry account

javascript
// 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");
});
代码python中等

Sentry Python SDK 集成

完整的 Django、Flask 和 FastAPI 应用程序 Python SDK 设置,包含错误追踪和性能监控

难度

6/10

预计时间

35 min

标签

sentry, python, django, flask, fastapi, monitoring

前置条件

Python, Django/Flask/FastAPI, pip, Sentry account

python
# 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)
代码javascript复杂

Sentry 性能监控

高级性能监控,包含自定义事务、span 和指标,用于深度应用程序洞察

难度

8/10

预计时间

50 min

标签

sentry, performance, tracing, monitoring, profiling

前置条件

JavaScript, Sentry SDK, Performance concepts

javascript
// 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
};
代码json复杂

Sentry 自定义告警和规则

配置高级告警规则、通知集成和自动化工作流,用于主动错误管理

难度

9/10

预计时间

60 min

标签

sentry, alerts, monitoring, notifications, automation

前置条件

Sentry account, Alerting concepts, Webhook knowledge

json
{
  "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"
      ]
    }
  ]
}

工具

经常与该案例搭配使用的工具

相关内容

相关案例集合

相关内容

相关专题

工具使用指南

帮助搜索与理解工作流的案例说明

标题

Sentry 错误追踪示例

描述

全面的 Sentry 错误追踪和性能监控设置,包含各种平台的 SDK 集成

概览

全面的 Sentry 错误追踪和性能监控设置,包含各种平台的 SDK 集成

适用场景

  • Use this sample set when you want reference inputs for Sentry 错误追踪示例.
  • Use it to preview output formats and compare related sample variants.

使用方式

  1. 1Open a sample entry to inspect the prepared example payload or asset.
  2. 2Compare it with related tools to understand how the workflow connects.

常见用途

  • Sentry JavaScript SDK 设置
  • Sentry Python SDK 集成
  • Sentry 性能监控
  • Sentry 自定义告警和规则

常见问题

What is included in Sentry 错误追踪示例?

This page includes curated sample entries, related tools, and neighboring sample collections for Sentry 错误追踪示例.

专题

营销活动追踪链接与二维码投放验收

统一活动 UTM 参数,生成追踪链接和二维码,部署可选自托管短链,并通过最终素材扫码、跳转测试和投放台账完成交付。

专题

联系人与物流标识验证

在导入或发货前规范化并验证邮箱、电话、邮政编码和物流追踪号。

专题

JSON 字段提取、转换与数据血缘

按路径提取 JSON 字段,用 JSONata 重塑负载,并记录字段级来源与转换过程;不把血缘记录当作业务语义校验。

专题

药代动力学教学模型与结果核查

用于教学或 QA 的药代公式、模型假设和结果一致性核查,不提供用药剂量、诊断或临床建议。

首页
工具3201
案例593
可视化465
文件查看器103
专题233
标签333
图像、音频与视频657

图像、音频、视频处理、转换与优化工具

数学、日期与金融644

计算器、数值计算、日期逻辑、统计与金融工具

设计与颜色297

颜色、版式、图形、视觉样式与设计辅助工具

文本与写作209

写作、清洗、格式化、提取与文本分析工具

开发与 Web193

开发者工具、网络处理、Web 调试与自动化辅助工具

转换与编码175

格式、文件、压缩包、单位与编码转换工具

FLAC/WAV 无损音源疑点筛查与证据交付
自托管抽奖组件配置复核、嵌入测试与上线交付
Stripe 优惠码候选批次审核与本地导入预检
批量照片技术初筛、近重复复核与修图候选交付
界面截图结构化、人工校对与开发交付

© 2026 Elysia Tools. 保留所有权利。

文档价格关于我们服务条款隐私政策Cookie 政策联系我们

Development

Data URI 生成器

将文件转换为 Data URI(Base64 或百分号编码),用于直接在 HTML、CSS 或 Markdown 中内联图片、字体等资源

Media

音频和弦进行检测器

在本地估算音频中的和弦顺序,并以 ZIP 下载 CSV、JSON、SVG 时间线和方法说明。

Media

音频旋律轮廓提取器

从音频中提取主导旋律,并在一个 ZIP 中导出 MIDI、音符事件、音高轮廓、SVG 和 JSON。

Media

AAC 转 OGG 转换器

将 AAC 音频文件转换为 OGG Vorbis 格式,支持质量和声道控制

Media

批量音频转换器

批量转换多个音频文件格式,支持 MP3、WAV、FLAC、AAC、OGG、Opus,支持质量设置和批量处理

Media

音频编码切换

在选定输出格式内更换音频编码

Media

音频格式转换器

在不同音频格式之间转换文件,如 MP3、WAV、FLAC、AAC、OGG,支持质量设置和音量调节

Media

音频底噪时间线

按时间追踪启发式低电平 RMS 代理值,单独统计数字静音并逐声道标记变化。

DevOps

ELK Stack 日志分析示例

全面的 ELK Stack(Elasticsearch、Logstash、Kibana)示例,用于分布式系统中的日志聚合、处理和可视化

监控与可观测性

Datadog 监控示例

全面的 Datadog 监控和可观测性配置示例,包括 APM、日志、指标和仪表板

Web 框架

Express.js 示例

Express.js Web框架示例,包括Hello World、路由、中间件和REST API

媒体

无版权OGG Vorbis音频样本

用于测试与开发的开源OGG Vorbis音频样本集合,具有出色压缩效果,包含自然声音与冥想音乐

Swift

macOS Swift 错误处理示例

macOS Swift 错误处理示例,包括异常捕获、日志记录和参数验证

可观测性

OpenTelemetry 示例

OpenTelemetry 可观测性标准示例,包括多种语言和框架的追踪、指标和日志