Sentry 后端集成 #

后端集成概述 #

后端服务是应用的核心,处理业务逻辑和数据存储。Sentry 后端集成可以帮助你:

text
┌─────────────────────────────────────────────────────────────┐
│                    后端监控价值                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 捕获服务端错误                                          │
│     - 未处理的异常                                          │
│     - 数据库错误                                            │
│     - 外部服务调用失败                                      │
│                                                             │
│  2. 监控 API 性能                                           │
│     - 请求处理时间                                          │
│     - 数据库查询耗时                                        │
│     - 外部 API 调用                                         │
│                                                             │
│  3. 分布式追踪                                              │
│     - 跨服务请求追踪                                        │
│     - 微服务调用链                                          │
│     - 性能瓶颈定位                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Python 集成 #

安装 #

bash
# pip
pip install sentry-sdk

# poetry
poetry add sentry-sdk

# pipenv
pipenv install sentry-sdk

Flask 集成 #

python
# app.py
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
from flask import Flask, request

sentry_sdk.init(
    dsn="https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
    integrations=[FlaskIntegration()],
    
    traces_sample_rate=0.1,
    profiles_sample_rate=0.1,
    
    environment="production",
    release="my-flask-app@1.0.0",
    
    send_default_pii=True,
)

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello, World!"

@app.route("/error")
def trigger_error():
    division_by_zero = 1 / 0
    return "This will not be reached"

@app.errorhandler(500)
def handle_500(error):
    sentry_sdk.capture_exception(error)
    return "Internal Server Error", 500

if __name__ == "__main__":
    app.run()

Django 集成 #

python
# settings.py
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration

sentry_sdk.init(
    dsn="https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
    integrations=[DjangoIntegration()],
    
    traces_sample_rate=0.1,
    
    environment="production",
    release="my-django-app@1.0.0",
    
    send_default_pii=True,
    
    signals_to_ignore=[
        "django.db.backends.signals",
    ],
)
python
# views.py
from django.http import JsonResponse
import sentry_sdk

def api_view(request):
    try:
        result = process_data(request.GET)
        return JsonResponse(result)
    except Exception as error:
        sentry_sdk.capture_exception(error)
        return JsonResponse({"error": str(error)}, status=500)

FastAPI 集成 #

python
# main.py
import sentry_sdk
from sentry_sdk.integrations.starlette import StarletteIntegration
from sentry_sdk.integrations.fastapi import FastApiIntegration
from fastapi import FastAPI, Request

sentry_sdk.init(
    dsn="https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
    integrations=[
        StarletteIntegration(),
        FastApiIntegration(),
    ],
    
    traces_sample_rate=0.1,
    
    environment="production",
)

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

@app.get("/error")
async def trigger_error():
    raise Exception("This is a test error")

@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    sentry_sdk.capture_exception(exc)
    return {"error": str(exc)}, 500

Python 异步支持 #

python
import sentry_sdk
import asyncio

async def async_operation():
    with sentry_sdk.start_transaction(
        op="task",
        name="async_operation",
    ) as transaction:
        span = transaction.start_child(
            op="db.query",
            description="fetch_users",
        )
        
        users = await fetch_users()
        
        span.finish()
        return users

async def main():
    async with sentry_sdk.Hub(sentry_sdk.Hub.current):
        await async_operation()

asyncio.run(main())

Node.js 集成 #

安装 #

bash
# npm
npm install @sentry/node

# yarn
yarn add @sentry/node

Express 集成 #

javascript
// app.js
const express = require("express");
const Sentry = require("@sentry/node");
const { ProfilingIntegration } = require("@sentry/profiling-node");

const app = express();

Sentry.init({
  dsn: "https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
  integrations: [
    new Sentry.Integrations.Http({ tracing: true }),
    new Sentry.Integrations.Express({ app }),
    new ProfilingIntegration(),
  ],
  
  tracesSampleRate: 0.1,
  profilesSampleRate: 0.1,
  
  environment: process.env.NODE_ENV,
  release: `my-express-app@${process.env.npm_package_version}`,
});

app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.tracingHandler());

app.use(express.json());

app.get("/", (req, res) => {
  res.send("Hello World");
});

app.get("/error", (req, res) => {
  throw new Error("This is a test error");
});

app.get("/api/users/:id", async (req, res) => {
  const transaction = Sentry.startTransaction({
    name: "GET /api/users/:id",
    op: "http.server",
  });
  
  try {
    const user = await getUserById(req.params.id);
    res.json(user);
  } catch (error) {
    Sentry.captureException(error);
    res.status(500).json({ error: error.message });
  } finally {
    transaction.finish();
  }
});

app.use(Sentry.Handlers.errorHandler());

app.listen(3000, () => {
  console.log("Server running on port 3000");
});

NestJS 集成 #

typescript
// main.ts
import { NestFactory } from "@nestjs/core";
import * as Sentry from "@sentry/node";
import { SentryFilter } from "./sentry.filter";
import { AppModule } from "./app.module";

Sentry.init({
  dsn: "https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
  integrations: [
    new Sentry.Integrations.Http({ tracing: true }),
  ],
  tracesSampleRate: 0.1,
  environment: process.env.NODE_ENV,
});

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  
  app.use(Sentry.Handlers.requestHandler());
  app.useGlobalFilters(new SentryFilter());
  
  await app.listen(3000);
}
bootstrap();
typescript
// sentry.filter.ts
import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
  HttpStatus,
} from "@nestjs/common";
import { Request, Response } from "express";
import * as Sentry from "@sentry/node";

@Catch()
export class SentryFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    Sentry.withScope((scope) => {
      scope.setTag("path", request.url);
      scope.setExtra("body", request.body);
      scope.setUser({ id: request.user?.id });
      Sentry.captureException(exception);
    });

    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;

    const message =
      exception instanceof HttpException
        ? exception.message
        : "Internal server error";

    response.status(status).json({
      statusCode: status,
      message,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}

Koa 集成 #

javascript
// app.js
const Koa = require("koa");
const Sentry = require("@sentry/node");

const app = new Koa();

Sentry.init({
  dsn: "https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
  integrations: [
    new Sentry.Integrations.Koa({ app }),
  ],
  tracesSampleRate: 0.1,
});

app.use(async (ctx, next) => {
  try {
    await next();
  } catch (error) {
    Sentry.withScope((scope) => {
      scope.setTag("path", ctx.path);
      scope.setExtra("body", ctx.request.body);
      Sentry.captureException(error);
    });
    
    ctx.status = error.status || 500;
    ctx.body = { error: error.message };
  }
});

app.use(async (ctx) => {
  ctx.body = "Hello World";
});

app.listen(3000);

Go 集成 #

安装 #

bash
go get github.com/getsentry/sentry-go

基础配置 #

go
// main.go
package main

import (
    "time"
    
    "github.com/getsentry/sentry-go"
)

func main() {
    err := sentry.Init(sentry.ClientOptions{
        Dsn: "https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
        
        TracesSampleRate: 0.1,
        
        Environment: "production",
        Release:     "my-go-app@1.0.0",
        
        Debug: false,
    })
    if err != nil {
        panic(err)
    }
    defer sentry.Flush(2 * time.Second)
    
    // 应用逻辑...
}

HTTP Handler 集成 #

go
// main.go
package main

import (
    "net/http"
    "time"
    
    "github.com/getsentry/sentry-go"
    sentryhttp "github.com/getsentry/sentry-go/http"
)

func main() {
    sentry.Init(sentry.ClientOptions{
        Dsn: "https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
        TracesSampleRate: 0.1,
    })
    defer sentry.Flush(2 * time.Second)
    
    sentryHandler := sentryhttp.New(sentryhttp.Options{})
    
    http.Handle("/", sentryHandler.HandleFunc(func(w http.ResponseWriter, r *http.Request) {
        hub := sentry.GetHubFromContext(r.Context())
        hub.Scope().SetTag("path", r.URL.Path)
        
        w.Write([]byte("Hello, World!"))
    }))
    
    http.Handle("/error", sentryHandler.HandleFunc(func(w http.ResponseWriter, r *http.Request) {
        panic("This is a test error")
    }))
    
    http.ListenAndServe(":8080", nil)
}

Gin 集成 #

go
// main.go
package main

import (
    "time"
    
    "github.com/getsentry/sentry-go"
    sentrygin "github.com/getsentry/sentry-go/gin"
    "github.com/gin-gonic/gin"
)

func main() {
    sentry.Init(sentry.ClientOptions{
        Dsn: "https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
        TracesSampleRate: 0.1,
    })
    defer sentry.Flush(2 * time.Second)
    
    r := gin.Default()
    
    r.Use(sentrygin.New(sentrygin.Options{}))
    
    r.GET("/", func(c *gin.Context) {
        c.String(200, "Hello, World!")
    })
    
    r.GET("/error", func(c *gin.Context) {
        if hub := sentrygin.GetHubFromContext(c); hub != nil {
            hub.WithScope(func(scope *sentry.Scope) {
                scope.SetTag("path", c.Request.URL.Path)
                hub.CaptureException(fmt.Errorf("test error"))
            })
        }
        c.String(500, "Error occurred")
    })
    
    r.Run(":8080")
}

手动捕获错误 #

go
// 捕获错误
sentry.CaptureException(fmt.Errorf("something went wrong"))

// 捕获消息
sentry.CaptureMessage("Something went wrong", sentry.LevelWarning)

// 使用 Scope
sentry.WithScope(func(scope *sentry.Scope) {
    scope.SetTag("category", "database")
    scope.SetExtra("query", "SELECT * FROM users")
    scope.SetUser(sentry.User{ID: "123"})
    
    sentry.CaptureException(err)
})

// 事务追踪
transaction := sentry.StartTransaction(
    context.TODO(),
    "GET /api/users",
    sentry.OpName("http.server"),
)
defer transaction.Finish()

span := transaction.StartChild("db.query")
// 数据库操作...
span.Finish()

Java 集成 #

Maven 配置 #

xml
<dependency>
    <groupId>io.sentry</groupId>
    <artifactId>sentry</artifactId>
    <version>7.0.0</version>
</dependency>
<dependency>
    <groupId>io.sentry</groupId>
    <artifactId>sentry-spring-boot-starter</artifactId>
    <version>7.0.0</version>
</dependency>

Gradle 配置 #

groovy
implementation 'io.sentry:sentry:7.0.0'
implementation 'io.sentry:sentry-spring-boot-starter:7.0.0'

Spring Boot 配置 #

properties
# application.properties
sentry.dsn=https://xxxxxxxx@o123456.ingest.sentry.io/1234567
sentry.environment=production
sentry.release=my-spring-app@1.0.0
sentry.traces-sample-rate=0.1
sentry.send-default-pii=true
java
// SentryConfig.java
import io.sentry.Sentry;
import io.sentry.spring.SentryExceptionResolver;
import io.sentry.spring.SentryServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SentryConfig {
    
    @Bean
    public SentryExceptionResolver sentryExceptionResolver() {
        return new SentryExceptionResolver();
    }
    
    @Bean
    public SentryServletContextInitializer sentryServletContextInitializer() {
        return new SentryServletContextInitializer();
    }
}

手动捕获错误 #

java
import io.sentry.Sentry;
import io.sentry.SentryLevel;

// 捕获异常
try {
    int result = 10 / 0;
} catch (Exception e) {
    Sentry.captureException(e);
}

// 捕获消息
Sentry.captureMessage("Something went wrong", SentryLevel.WARNING);

// 使用 Scope
Sentry.withScope(scope -> {
    scope.setTag("category", "database");
    scope.setExtra("query", "SELECT * FROM users");
    scope.setUser(new User().setId("123").setEmail("user@example.com"));
    
    Sentry.captureException(exception);
});

// 事务追踪
ITransaction transaction = Sentry.startTransaction("processOrder", "task");
try {
    ISpan span = transaction.startChild("db.query", "fetch user");
    User user = userRepository.findById(userId);
    span.finish();
    
    span = transaction.startChild("api.call", "payment service");
    paymentService.charge(user);
    span.finish();
} finally {
    transaction.finish();
}

Spring MVC Controller #

java
import io.sentry.Sentry;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class UserController {
    
    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        Sentry.setTag("user.id", String.valueOf(id));
        
        try {
            return userService.findById(id);
        } catch (UserNotFoundException e) {
            Sentry.captureException(e);
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found");
        }
    }
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(Exception e) {
        Sentry.captureException(e);
        return ResponseEntity.status(500).body("Internal Server Error");
    }
}

数据库集成 #

SQLAlchemy (Python) #

python
import sentry_sdk
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
from sqlalchemy import create_engine

sentry_sdk.init(
    dsn="https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
    integrations=[SqlalchemyIntegration()],
    traces_sample_rate=0.1,
)

engine = create_engine("postgresql://user:pass@localhost/db")

Redis (Python) #

python
import sentry_sdk
from sentry_sdk.integrations.redis import RedisIntegration
import redis

sentry_sdk.init(
    dsn="https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
    integrations=[RedisIntegration()],
    traces_sample_rate=0.1,
)

r = redis.Redis(host="localhost", port=6379)

MongoDB (Node.js) #

javascript
const Sentry = require("@sentry/node");
const { MongoIntegration } = require("@sentry/integrations");

Sentry.init({
  dsn: "https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
  integrations: [new MongoIntegration()],
  tracesSampleRate: 0.1,
});

任务队列集成 #

Celery (Python) #

python
import sentry_sdk
from sentry_sdk.integrations.celery import CeleryIntegration
from celery import Celery

sentry_sdk.init(
    dsn="https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
    integrations=[CeleryIntegration()],
    traces_sample_rate=0.1,
)

app = Celery("tasks", broker="redis://localhost:6379")

@app.task
def process_order(order_id):
    with sentry_sdk.start_transaction(
        op="task",
        name="process_order",
    ) as transaction:
        sentry_sdk.set_tag("order_id", order_id)
        # 处理订单...

RQ (Python) #

python
import sentry_sdk
from sentry_sdk.integrations.rq import RqIntegration
from rq import Queue

sentry_sdk.init(
    dsn="https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
    integrations=[RqIntegration()],
)

def process_task(arg):
    # 任务逻辑...
    pass

q = Queue()
q.enqueue(process_task, "argument")

日志集成 #

Python logging #

python
import sentry_sdk
from sentry_sdk.integrations.logging import LoggingIntegration
import logging

sentry_sdk.init(
    dsn="https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
    integrations=[
        LoggingIntegration(
            level=logging.INFO,
            event_level=logging.ERROR,
        ),
    ],
)

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

logger.error("This will be sent to Sentry")

Winston (Node.js) #

javascript
const Sentry = require("@sentry/node");
const winston = require("winston");
const { SentryTransport } = require("@sentry/winston");

Sentry.init({
  dsn: "https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
});

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console(),
    new SentryTransport({
      level: "error",
    }),
  ],
});

logger.error("This will be sent to Sentry");

后端最佳实践 #

1. 请求上下文 #

python
# Flask
from flask import request
import sentry_sdk

@app.before_request
def before_request():
    sentry_sdk.set_user({
        "id": request.headers.get("X-User-ID"),
        "ip_address": request.remote_addr,
    })
    sentry_sdk.set_tag("endpoint", request.endpoint)

2. 数据库查询追踪 #

python
import sentry_sdk

def query_users():
    with sentry_sdk.start_span(
        op="db.query",
        description="SELECT * FROM users",
    ) as span:
        span.set_data("db.system", "postgresql")
        span.set_data("db.statement", "SELECT * FROM users")
        
        users = db.execute("SELECT * FROM users")
        return users

3. 外部 API 调用追踪 #

python
import sentry_sdk
import requests

def fetch_external_data(url):
    with sentry_sdk.start_span(
        op="http.client",
        description=f"GET {url}",
    ) as span:
        span.set_data("url", url)
        span.set_data("method", "GET")
        
        response = requests.get(url)
        span.set_data("status_code", response.status_code)
        
        return response.json()

4. 错误过滤 #

python
import sentry_sdk

def before_send(event, hint):
    # 过滤健康检查
    if event.get("request", {}).get("url", "").endswith("/health"):
        return None
    
    # 过滤特定错误
    if "exc_info" in hint:
        exc_type, exc_value, tb = hint["exc_info"]
        if isinstance(exc_value, (ConnectionError, TimeoutError)):
            return None
    
    return event

sentry_sdk.init(
    dsn="https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
    before_send=before_send,
)

5. 敏感数据过滤 #

python
import sentry_sdk

def before_send(event, hint):
    # 过滤请求体中的敏感字段
    request = event.get("request", {})
    body = request.get("data", {})
    
    if isinstance(body, dict):
        sensitive_fields = ["password", "token", "credit_card"]
        for field in sensitive_fields:
            if field in body:
                body[field] = "[Filtered]"
    
    return event

下一步 #

现在你已经掌握了后端集成的知识,接下来学习 性能监控 了解如何监控应用性能!

最后更新:2026-03-29