Sentry 性能监控 #

什么是性能监控? #

性能监控是 Sentry 的重要功能之一,帮助你了解应用的运行性能,发现性能瓶颈。

text
┌─────────────────────────────────────────────────────────────┐
│                    性能监控价值                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 发现慢请求                                              │
│     - API 响应时间过长                                      │
│     - 页面加载缓慢                                          │
│     - 数据库查询耗时                                        │
│                                                             │
│  2. 定位性能瓶颈                                            │
│     - 哪个操作最耗时                                        │
│     - 外部服务调用影响                                      │
│     - 资源加载问题                                          │
│                                                             │
│  3. 分布式追踪                                              │
│     - 跨服务请求链路                                        │
│     - 微服务调用分析                                        │
│     - 端到端性能                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

核心概念 #

Transaction(事务) #

事务是性能监控的基本单位,代表一个完整的操作流程。

text
┌─────────────────────────────────────────────────────────────┐
│                    Transaction 结构                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Transaction: GET /api/users                                │
│  ├── Span: db.query (50ms)                                  │
│  ├── Span: http.request (100ms)                             │
│  └── Span: cache.set (5ms)                                  │
│                                                             │
│  总耗时: 155ms                                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Span(跨度) #

Span 是事务中的具体操作,记录单个步骤的执行时间。

text
┌─────────────────────────────────────────────────────────────┐
│                    Span 属性                                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  op        - 操作类型(如 db.query, http.request)          │
│  description - 操作描述                                     │
│  start_timestamp - 开始时间                                 │
│  timestamp - 结束时间                                       │
│  data      - 额外数据                                       │
│  status    - 状态(ok, error, cancelled...)                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

操作类型(Operation Types) #

操作类型 描述
http.server HTTP 服务端请求
http.client HTTP 客户端请求
db.query 数据库查询
db.transaction 数据库事务
cache 缓存操作
queue 队列操作
ui.render UI 渲染
ui.load UI 加载

启用性能监控 #

前端配置 #

javascript
import * as Sentry from "@sentry/react";

Sentry.init({
  dsn: "https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
  integrations: [
    Sentry.browserTracingIntegration(),
  ],
  
  // 采样率(0.0 - 1.0)
  tracesSampleRate: 0.1,  // 10% 的事务会被上报
  
  // 或者使用动态采样
  tracesSampler: (samplingContext) => {
    // 健康检查不追踪
    if (samplingContext.name === "GET /health") {
      return 0;
    }
    
    // 重要接口全量追踪
    if (samplingContext.name.startsWith("POST /api/orders")) {
      return 1.0;
    }
    
    // 其他接口 10% 采样
    return 0.1;
  },
});

后端配置 #

python
import sentry_sdk

sentry_sdk.init(
    dsn="https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
    traces_sample_rate=0.1,
    
    # 动态采样
    traces_sampler=lambda sampling_context: (
        0 if sampling_context["transaction_context"]["name"] == "GET /health"
        else 0.1
    ),
)
javascript
// Node.js
const Sentry = require("@sentry/node");

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

创建事务 #

自动事务 #

框架集成会自动创建事务:

javascript
// Express 自动追踪
const Sentry = require("@sentry/node");

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

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

手动创建事务 #

javascript
// JavaScript
const transaction = Sentry.startTransaction({
  name: "processOrder",
  op: "task",
});

try {
  // 执行操作
  await processOrder(orderId);
  transaction.setStatus("ok");
} catch (error) {
  transaction.setStatus("internal_error");
  throw error;
} finally {
  transaction.finish();
}
python
# Python
import sentry_sdk

with sentry_sdk.start_transaction(
    op="task",
    name="process_order",
) as transaction:
    process_order(order_id)
    transaction.set_status("ok")
go
// Go
transaction := sentry.StartTransaction(
    context.TODO(),
    "processOrder",
    sentry.OpName("task"),
)
defer transaction.Finish()

processOrder(orderId)
transaction.Status = sentry.SpanStatusOK

创建 Span #

手动创建 Span #

javascript
// JavaScript
const transaction = Sentry.startTransaction({
  name: "checkout",
  op: "task",
});

// 创建子 Span
const dbSpan = transaction.startChild({
  op: "db.query",
  description: "SELECT * FROM orders WHERE id = ?",
});

const order = await db.query("SELECT * FROM orders WHERE id = ?", [orderId]);
dbSpan.finish();

const paymentSpan = transaction.startChild({
  op: "http.client",
  description: "POST /api/payment",
});

const result = await fetch("/api/payment", { method: "POST" });
paymentSpan.finish();

transaction.finish();
python
# Python
import sentry_sdk

with sentry_sdk.start_transaction(op="task", name="checkout") as transaction:
    with transaction.start_child(
        op="db.query",
        description="SELECT * FROM orders",
    ) as span:
        order = db.query("SELECT * FROM orders WHERE id = %s", [order_id])
    
    with transaction.start_child(
        op="http.client",
        description="POST /api/payment",
    ) as span:
        result = requests.post("/api/payment")

使用装饰器(Python) #

python
import sentry_sdk
from functools import wraps

def traced(op, description=None):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            with sentry_sdk.start_span(op=op, description=description or func.__name__):
                return func(*args, **kwargs)
        return wrapper
    return decorator

@traced(op="db.query", description="fetch_user")
def fetch_user(user_id):
    return db.query("SELECT * FROM users WHERE id = %s", [user_id])

@traced(op="http.client")
def call_external_api(url):
    return requests.get(url)

分布式追踪 #

追踪上下文传播 #

分布式追踪需要在服务之间传播追踪上下文:

text
┌─────────────────────────────────────────────────────────────┐
│                    分布式追踪流程                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  服务 A                    服务 B                    服务 C  │
│  ┌─────────┐              ┌─────────┐              ┌─────────┐
│  │ Trans A │─────────────>│ Trans B │─────────────>│ Trans C │
│  │         │   Headers:   │         │   Headers:   │         │
│  │ Span 1  │   sentry-    │ Span 2  │   sentry-    │ Span 3  │
│  │         │   trace      │         │   trace      │         │
│  └─────────┘              └─────────┘              └─────────┘
│                                                             │
│  同一个 Trace ID 贯穿整个请求链                              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

HTTP 传播 #

javascript
// 发送请求时携带追踪头
import * as Sentry from "@sentry/node";

async function callExternalService(url) {
  const span = Sentry.startInactiveSpan({
    op: "http.client",
    name: `GET ${url}`,
  });
  
  const headers = {};
  
  // 添加追踪头
  span?.toTraceTraceContext();
  if (span) {
    const traceContext = span.toTraceTraceContext();
    headers["sentry-trace"] = traceContext["sentry-trace"];
    headers["baggage"] = traceContext.baggage;
  }
  
  const response = await fetch(url, { headers });
  span?.finish();
  
  return response;
}
python
# Python - Flask
import sentry_sdk
import requests
from flask import request

@app.route("/api/proxy")
def proxy():
    # 获取传入的追踪头
    sentry_trace = request.headers.get("sentry-trace")
    baggage = request.headers.get("baggage")
    
    # 继续追踪
    with sentry_sdk.continue_trace({
        "sentry-trace": sentry_trace,
        "baggage": baggage,
    }):
        # 调用外部服务
        response = requests.get("https://external-api.com/data")
        return response.json()

微服务追踪示例 #

text
┌─────────────────────────────────────────────────────────────┐
│                    电商下单追踪示例                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Trace ID: abc123                                           │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ Transaction: POST /api/orders                        │   │
│  │ Service: api-gateway                                │   │
│  │ Duration: 500ms                                      │   │
│  │                                                       │   │
│  │  ├── Span: auth.validate (10ms)                      │   │
│  │  ├── Span: http.client -> order-service (200ms)      │   │
│  │  │   └── Transaction: create-order                   │   │
│  │  │       ├── Span: db.query (50ms)                   │   │
│  │  │       ├── Span: http.client -> inventory (100ms)  │   │
│  │  │       │   └── Transaction: check-inventory        │   │
│  │  │       │       └── Span: db.query (80ms)           │   │
│  │  │       └── Span: http.client -> payment (40ms)     │   │
│  │  │           └── Transaction: process-payment        │   │
│  │  │               └── Span: http.client -> stripe     │   │
│  │  └── Span: cache.update (5ms)                        │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

性能指标 #

Web Vitals(前端) #

Sentry 自动捕获以下 Web Vitals:

指标 名称 描述
LCP Largest Contentful Paint 最大内容绘制时间
FID First Input Delay 首次输入延迟
CLS Cumulative Layout Shift 累积布局偏移
FCP First Contentful Paint 首次内容绘制
TTFB Time to First Byte 首字节时间
javascript
// 查看性能指标
Sentry.init({
  dsn: "https://xxxxxxxx@o123456.ingest.sentry.io/1234567",
  integrations: [
    Sentry.browserTracingIntegration(),
  ],
  tracesSampleRate: 0.1,
  
  // 设置性能阈值
  _experiments: {
    recordLongTasks: true,
  },
});

自定义指标 #

javascript
// 记录自定义指标
const transaction = Sentry.startTransaction({
  name: "checkout",
  op: "task",
});

// 添加指标数据
transaction.setMeasurement("order_value", 99.99, "currency");
transaction.setMeasurement("items_count", 5, "none");
transaction.setMeasurement("processing_time", 150, "millisecond");

transaction.finish();
python
# Python
import sentry_sdk

with sentry_sdk.start_transaction(op="task", name="checkout") as transaction:
    transaction.set_measurement("order_value", 99.99, "currency")
    transaction.set_measurement("items_count", 5, "none")
    transaction.set_measurement("processing_time", 150, "millisecond")

性能分析 #

查看事务性能 #

在 Sentry 控制台中:

  1. 进入 Performance 页面
  2. 选择要分析的事务
  3. 查看事务详情:
    • 响应时间分布
    • Span 时间线
    • 错误关联
    • 用户影响

识别性能瓶颈 #

text
┌─────────────────────────────────────────────────────────────┐
│                    性能瓶颈分析                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Transaction: GET /api/dashboard                            │
│  Total Duration: 2000ms                                     │
│                                                             │
│  Span Breakdown:                                            │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ db.query (1500ms) ████████████████████████ 75%      │   │
│  │ http.client (400ms) ████████ 20%                    │   │
│  │ cache.get (50ms) ██ 2.5%                            │   │
│  │ other (50ms) ██ 2.5%                                │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  瓶颈: db.query 占用 75% 时间                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

性能告警 #

yaml
# 性能告警规则
rules:
  - name: "Slow API Response"
    conditions:
      - type: transaction_duration
        threshold: 1000  # 1秒
        comparison: greater_than
    actions:
      - type: email
        targets: ["dev-team@example.com"]
      - type: slack
        channel: "#performance-alerts"

性能优化建议 #

1. 数据库查询优化 #

python
import sentry_sdk

# 追踪数据库查询
with sentry_sdk.start_span(
    op="db.query",
    description="SELECT * FROM orders",
) as span:
    span.set_data("db.system", "postgresql")
    span.set_data("db.statement", "SELECT * FROM orders WHERE user_id = %s")
    span.set_data("db.rows_affected", len(orders))
    
    orders = db.query("SELECT * FROM orders WHERE user_id = %s", [user_id])

2. 缓存策略 #

python
import sentry_sdk

def get_user(user_id):
    # 先查缓存
    with sentry_sdk.start_span(op="cache.get", description=f"user:{user_id}") as span:
        user = cache.get(f"user:{user_id}")
        span.set_data("cache.hit", user is not None)
    
    if user:
        return user
    
    # 缓存未命中,查数据库
    with sentry_sdk.start_span(op="db.query", description="SELECT * FROM users"):
        user = db.query("SELECT * FROM users WHERE id = %s", [user_id])
    
    # 写入缓存
    with sentry_sdk.start_span(op="cache.set", description=f"user:{user_id}"):
        cache.set(f"user:{user_id}", user, ttl=3600)
    
    return user

3. 并行处理 #

javascript
// 并行执行多个操作
const transaction = Sentry.startTransaction({
  name: "loadDashboard",
  op: "task",
});

// 并行加载数据
const [users, orders, stats] = await Promise.all([
  (async () => {
    const span = transaction.startChild({ op: "db.query", description: "fetch users" });
    const result = await fetchUsers();
    span.finish();
    return result;
  })(),
  (async () => {
    const span = transaction.startChild({ op: "db.query", description: "fetch orders" });
    const result = await fetchOrders();
    span.finish();
    return result;
  })(),
  (async () => {
    const span = transaction.startChild({ op: "db.query", description: "fetch stats" });
    const result = await fetchStats();
    span.finish();
    return result;
  })(),
]);

transaction.finish();

4. 懒加载 #

javascript
// 懒加载非关键数据
const transaction = Sentry.startTransaction({
  name: "loadPage",
  op: "pageload",
});

// 立即加载关键数据
const criticalData = await fetchCriticalData();

// 延迟加载非关键数据
setTimeout(async () => {
  const span = transaction.startChild({ op: "lazy.load", description: "fetch recommendations" });
  await fetchRecommendations();
  span.finish();
}, 1000);

transaction.finish();

性能监控最佳实践 #

1. 合理设置采样率 #

javascript
Sentry.init({
  // 生产环境使用较低采样率
  tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,
  
  // 或者根据事务类型动态采样
  tracesSampler: (context) => {
    // 关键事务全量追踪
    if (context.name.includes("checkout") || context.name.includes("payment")) {
      return 1.0;
    }
    
    // 健康检查不追踪
    if (context.name.includes("health")) {
      return 0;
    }
    
    // 其他事务 10% 采样
    return 0.1;
  },
});

2. 命名规范 #

javascript
// ✅ 好的命名
transaction.name = "GET /api/users/:id";
transaction.op = "http.server";

span.op = "db.query";
span.description = "SELECT * FROM users WHERE id = ?";

// ❌ 不好的命名
transaction.name = "GET /api/users/123";  // 包含动态 ID
span.description = "query";  // 太模糊

3. 添加有意义的上下文 #

javascript
const transaction = Sentry.startTransaction({
  name: "processOrder",
  op: "task",
});

// 添加业务上下文
transaction.setTag("order_type", "subscription");
transaction.setTag("payment_method", "credit_card");
transaction.setData("order_id", orderId);
transaction.setData("user_id", userId);

4. 正确处理错误 #

javascript
const transaction = Sentry.startTransaction({
  name: "processOrder",
  op: "task",
});

try {
  await processOrder(orderId);
  transaction.setStatus("ok");
} catch (error) {
  // 记录错误状态
  transaction.setStatus("internal_error");
  
  // 关联错误到事务
  Sentry.captureException(error);
  
  throw error;
} finally {
  transaction.finish();
}

下一步 #

现在你已经掌握了性能监控的知识,接下来学习 Release 追踪 了解如何追踪版本发布!

最后更新:2026-03-29