关于 sentry-skill
sentry-skill 是关于 Sentry 错误监控、性能追踪与应用可观测性的操作指南,面向负责应用监控和发布的开发者与运维人员。内容涵盖 SDK、CLI、API、告警及自托管部署。
主要功能
- 01配置多语言 SDK 并捕获错误
- 02跟踪事务、Span 与分布式调用
- 03通过 CLI 管理发布和 Source Map
- 04使用 API 查询事件与问题
- 05配置错误和指标告警
- 06支持自托管部署与扩展
适用场景
- 01排查应用错误及相关事件
- 02监控请求性能和跨服务追踪
- 03在发布流程中上传 Source Map
- 04查询问题并配置告警
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ julianobarbosa/ claude-code-skills --skill sentry-skill安装后在 Claude Code 中输入/sentry-skill确认已加载。
详细介绍
Sentry 技能
使用 Sentry 进行错误监控、性能跟踪和应用可观测性的综合指南。
快速参考
DSN(数据源名称)
DSN 是 Sentry 项目的唯一标识符:
https://<PUBLIC_KEY>@<HOST>/<PROJECT_ID>
示例:https://[email protected]/1234567
核心概念
| 概念 | 描述 |
|---|---|
| 事件 | 发送到 Sentry 的单个数据实例(错误、事务等) |
| 问题 | 根据指纹去重后的一组相似事件 |
| 事务 | 表示一个工作单元的性能监控跨度 |
| Span | 事务中的单个操作(数据库查询、HTTP 调用) |
| Trace | 跨服务连接的一系列事务 |
| 发布版本 | 部署到某个环境的代码版本 |
| 环境 | 部署目标(生产、预发布、开发) |
SDK 安装与配置
JavaScript/Node.js
npm install @sentry/node @sentry/profiling-node
const Sentry = require("@sentry/node");
const { nodeProfilingIntegration } = require("@sentry/profiling-node");
Sentry.init({
dsn: "https://[email protected]/1",
release: process.env.RELEASE_VERSION || "1.0.0",
environment: process.env.NODE_ENV || "development",
// Error sampling (1.0 = 100% of errors)
sampleRate: 1.0,
// Performance monitoring (0.1 = 10% of transactions)
tracesSampleRate: 0.1,
// OR use dynamic sampling
tracesSampler: (samplingContext) => {
if (samplingContext.transactionContext.name === "/health") {
return 0; // Don't sample health checks
}
if (samplingContext.parentSampled !== undefined) {
return samplingContext.parentSampled; // Inherit parent decision
}
return 0.1; // Default 10%
},
// Profiling
profilesSampleRate: 0.1,
integrations: [nodeProfilingIntegration()],
// Data scrubbing
beforeSend(event) {
if (event.request?.headers) {
delete event.request.headers["Authorization"];
}
return event;
},
});
Python
pip install sentry-sdk
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
sentry_sdk.init(
dsn="https://[email protected]/1",
release="[email protected]",
environment="production",
# Error sampling
sample_rate=1.0,
# Performance monitoring
traces_sample_rate=0.1,
# OR dynamic sampling
traces_sampler=lambda ctx: (
0 if ctx.get("transaction_context", {}).get("name") == "/health"
else 0.1
),
# Profiling
profiles_sample_rate=0.1,
# Integrations
integrations=[
FlaskIntegration(),
SqlalchemyIntegration(),
],
# Data scrubbing
before_send=lambda event, hint: scrub_sensitive_data(event),
)
def scrub_sensitive_data(event):
if event.get("request", {}).get("headers"):
event["request"]["headers"].pop("Authorization", None)
return event
Go
go get github.com/getsentry/sentry-go
package main
import (
"log"
"time"
"github.com/getsentry/sentry-go"
)
func main() {
err := sentry.Init(sentry.ClientOptions{
Dsn: "https://[email protected]/1",
Release: "[email protected]",
Environment: "production",
TracesSampleRate: 0.1,
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
// Scrub sensitive data
return event
},
})
if err != nil {
log.Fatalf("sentry.Init: %s", err)
}
defer sentry.Flush(2 * time.Second)
}
错误捕获
手动捕获错误
// JavaScript
try {
riskyOperation();
} catch (error) {
Sentry.captureException(error, {
tags: { component: "payment" },
extra: { orderId: "12345" },
user: { id: "user-123", email: "[email protected]" },
});
}
// Capture message
Sentry.captureMessage("Something unexpected happened", "warning");
# Python
try:
risky_operation()
except Exception as e:
sentry_sdk.capture_exception(e)
sentry_sdk.set_tag("component", "payment")
sentry_sdk.set_extra("order_id", "12345")
sentry_sdk.set_user({"id": "user-123", "email": "[email protected]"})
# Capture message
sentry_sdk.capture_message("Something unexpected happened", level="warning")
面包屑
// Add context breadcrumbs
Sentry.addBreadcrumb({
category: "auth",
message: "User logged in",
level: "info",
data: { userId: "123" },
});
作用域
// Configure scope for context
Sentry.configureScope((scope) => {
scope.setUser({ id: "user-123" });
scope.setTag("page_locale", "en-US");
scope.setExtra("session_data", { cart_items: 5 });
});
// Isolated scope
Sentry.withScope((scope) => {
scope.setTag("isolated", "true");
Sentry.captureException(new Error("Scoped error"));
});
性能监控
手动创建事务
const transaction = Sentry.startTransaction({
op: "task",
name: "Process Order",
});
// Set transaction on scope
Sentry.getCurrentHub().configureScope((scope) => {
scope.setSpan(transaction);
});
// Create child spans
const span = transaction.startChild({
op: "db.query",
description: "SELECT * FROM orders",
});
// Do work...
await queryDatabase();
span.finish();
transaction.finish();
分布式追踪
// Service A - Create trace
const transaction = Sentry.startTransaction({ name: "API Request" });
const traceHeader = transaction.toTraceparent();
// Pass traceHeader to Service B via HTTP header: sentry-trace
// Service B - Continue trace
const incomingTrace = request.headers["sentry-trace"];
const transaction = Sentry.startTransaction({
name: "Process Request",
op: "http.server",
}, { parentSampled: true });
Sentry CLI
安装
# npm
npm install -g @sentry/cli
# curl
curl -sL https://sentry.io/get-cli/ | bash
# Homebrew
brew install getsentry/tools/sentry-cli
身份验证
# Login interactively
sentry-cli login
# Or set auth token
export SENTRY_AUTH_TOKEN=your-token
export SENTRY_ORG=your-org
export SENTRY_PROJECT=your-project
发布版本管理
# Create release
sentry-cli releases new v1.0.0
# Associate commits (auto-detect from git)
sentry-cli releases set-commits v1.0.0 --auto
# Or specify commit range
sentry-cli releases set-commits v1.0.0 --commit "repo@from_sha..to_sha"
# Upload source maps
sentry-cli releases files v1.0.0 upload-sourcemaps ./dist \
--url-prefix '~/static/js' \
--rewrite
# Upload debug symbols (iOS/Android/Native)
sentry-cli debug-files upload --include-sources path/to/symbols
# Deploy release to environment
sentry-cli releases deploys v1.0.0 new -e production
# Finalize release
sentry-cli releases finalize v1.0.0
Source Maps 工作流
# Build with source maps
npm run build
# Create release and upload
export VERSION=$(sentry-cli releases propose-version)
sentry-cli releases new $VERSION
sentry-cli releases files $VERSION upload-sourcemaps ./dist \
--url-prefix '~/' \
--validate
sentry-cli releases finalize $VERSION
Cron 监控
# Wrap a cron job
sentry-cli monitors run <monitor-slug> -- /path/to/script.sh
# Or use check-in API
sentry-cli monitors run <monitor-slug> --check-in-status in_progress
# ... run job ...
sentry-cli monitors run <monitor-slug> --check-in-status ok
发送测试事件
sentry-cli send-event -m "Test event from CLI"
API 参考
身份验证
# Bearer token (recommended)
curl -H "Authorization: Bearer <AUTH_TOKEN>" \
https://sentry.io/api/0/projects/
# DSN-based (limited endpoints)
curl -u <PUBLIC_KEY>: \
https://sentry.io/api/<PROJECT_ID>/store/
常用端点
| 端点 | 方法 | 描述 |
|---|---|---|
/api/0/organizations/ | GET | 列出组织 |
/api/0/organizations/{org}/projects/ | GET | 列出项目 |
/api/0/projects/{org}/{project}/issues/ | GET | 列出问题 |
/api/0/organizations/{org}/issues/{issue_id}/ | GET | 获取问题详情 |
/api/0/projects/{org}/{project}/events/ | GET | 列出事件 |
/api/0/organizations/{org}/releases/ | GET/POST | 列出/创建发布版本 |
/api/0/projects/{org}/{project}/keys/ | GET | 列出 DSN 密钥 |
查询问题
# List issues with filters
curl -H "Authorization: Bearer $TOKEN" \
"https://sentry.io/api/0/projects/{org}/{project}/issues/?query=is:unresolved+level:error&statsPeriod=24h"
# Get issue details
curl -H "Authorization: Bearer $TOKEN" \
"https://sentry.io/api/0/organizations/{org}/issues/{issue_id}/"
# Resolve issue
curl -X PUT -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "resolved"}' \
"https://sentry.io/api/0/organizations/{org}/issues/{issue_id}/"
通过 API 创建发布版本
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"version": "v1.0.0",
"projects": ["my-project"],
"refs": [{
"repository": "org/repo",
"commit": "abc123"
}]
}' \
"https://sentry.io/api/0/organizations/{org}/releases/"
分页
# Response includes Link header
Link: <https://sentry.io/api/0/...?cursor=123:0:0>; rel="previous"; results="false",
<https://sentry.io/api/0/...?cursor=456:0:0>; rel="next"; results="true"
速率限制
- 默认:大多数端点每秒 40 个请求
- 批量端点:限制较低
- 标头:
X-Sentry-Rate-Limit-Remaining、X-Sentry-Rate-Limit-Reset
警报配置
问题警报(通过 UI/API)
{
"name": "High Error Rate Alert",
"conditions": [
{
"id": "sentry.rules.conditions.event_frequency.EventFrequencyCondition",
"interval": "1h",
"value": 100
}
],
"actions": [
{
"id": "sentry.integrations.slack.notify_action.SlackNotifyServiceAction",
"channel": "#alerts",
"workspace": "workspace-id"
}
],
"actionMatch": "all",
"filterMatch": "all",
"frequency": 30
}
指标警报
# Example: Alert on error rate > 5%
triggers:
- alertThreshold: 5
label: critical
actions:
- type: slack
channel: "#critical-alerts"
- alertThreshold: 2
label: warning
actions:
- type: email
targetIdentifier: "[email protected]"
OpenTelemetry 集成
导出 OTLP 到 Sentry
const { NodeSDK } = require("@opentelemetry/sdk-node");
const { OTLPTraceExporter } = require("@opentelemetry/exporter-trace-otlp-http");
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: "https://sentry.io/api/<PROJECT_ID>/envelope/",
headers: {
"sentry-trace": "...",
},
}),
});
sdk.start();
将 Sentry 与 OpenTelemetry 配合使用
const Sentry = require("@sentry/node");
Sentry.init({
dsn: "...",
instrumenter: "otel", // Use OpenTelemetry for instrumentation
tracesSampleRate: 0.1,
});
自托管部署
系统要求
| 资源 | 最低要求 | 建议配置 |
|---|---|---|
| CPU | 4 核 | 8 核以上 |
| RAM | 16 GB | 32 GB 以上 |
| 交换空间 | 16 GB | - |
| 磁盘 | 100 GB SSD | 500 GB SSD 以上 |
| Docker | 19.03+ | 最新版本 |
| Docker Compose | 2.19+ | 最新版本 |
安装
# Clone repository
VERSION=$(curl -Ls -o /dev/null -w %{url_effective} \
https://github.com/getsentry/self-hosted/releases/latest)
VERSION=${VERSION##*/}
git clone https://github.com/getsentry/self-hosted.git
cd self-hosted
git checkout ${VERSION}
# Run installer
./install.sh
# Start services
docker compose up -d
# Access at http://localhost:9000
配置(sentry/config.yml)
# Mail
mail.backend: 'smtp'
mail.host: 'smtp.example.com'
mail.port: 587
mail.username: '[email protected]'
mail.password: 'password'
mail.use-tls: true
mail.from: '[email protected]'
# System
system.url-prefix: 'https://sentry.example.com'
system.secret-key: 'your-secret-key'
# Features
features.organizations:early-adopter: False
外部存储(GCS/S3)
# sentry/config.yml
filestore.backend: 'gcs'
filestore.options:
bucket_name: 'sentry-files'
# Or S3
filestore.backend: 's3'
filestore.options:
access_key: 'AWS_ACCESS_KEY'
secret_key: 'AWS_SECRET_KEY'
bucket_name: 'sentry-files'
region_name: 'us-east-1'
外部数据库
# PostgreSQL
SENTRY_POSTGRES_HOST: 'postgres.example.com'
SENTRY_POSTGRES_PORT: '5432'
SENTRY_DB_NAME: 'sentry'
SENTRY_DB_USER: 'sentry'
SENTRY_DB_PASSWORD: 'password'
# Redis
SENTRY_REDIS_HOST: 'redis.example.com'
SENTRY_REDIS_PORT: '6379'
# Kafka
SENTRY_KAFKA_HOST: 'kafka.example.com:9092'
扩展 Worker
# Scale specific services
docker compose up -d --scale worker=4 --scale snuba-consumer=2
监控自托管部署
# Enable StatsD metrics
SENTRY_METRICS_BACKEND: 'statsd'
SENTRY_METRICS_OPTIONS:
host: 'statsd.example.com'
port: 8125
最佳实践
采样策略
// Dynamic sampling based on context
tracesSampler: (ctx) => {
// Always sample errors
if (ctx.transactionContext.name.includes("error")) return 1.0;
// Lower rate for high-volume endpoints
if (ctx.transactionContext.name === "/api/health") return 0;
if (ctx.transactionContext.name.startsWith("/api/v1/")) return 0.05;
// Default rate
return 0.1;
}
数据清理
beforeSend(event) {
// Remove PII
if (event.user) {
delete event.user.email;
delete event.user.ip_address;
}
// Scrub sensitive headers
if (event.request?.headers) {
delete event.request.headers["Authorization"];
delete event.request.headers["Cookie"];
}
// Filter local errors in production
if (event.exception?.values?.[0]?.type === "ChunkLoadError") {
return null; // Drop event
}
return event;
}
发布版本跟踪
# CI/CD Pipeline Example
export SENTRY_RELEASE=$(git rev-parse --short HEAD)
# Before deploy
sentry-cli releases new $SENTRY_RELEASE
sentry-cli releases set-commits $SENTRY_RELEASE --auto
sentry-cli releases files $SENTRY_RELEASE upload-sourcemaps ./dist
# After deploy
sentry-cli releases deploys $SENTRY_RELEASE new -e production
sentry-cli releases finalize $SENTRY_RELEASE
配额管理
// Client-side rate limiting
Sentry.init({
dsn: "...",
maxBreadcrumbs: 50,
maxValueLength: 1000,
// Limit events per session
beforeSend(event, hint) {
if (sessionEventCount++ > 100) {
return null; // Drop after 100 events
}
return event;
}
});
常见操作
调试集成问题
# Enable debug mode
Sentry.init({ debug: true });
# Test event delivery
sentry-cli send-event -m "Test message"
# Verify source maps
sentry-cli releases files <release> list
sentry-cli sourcemaps explain <event-id>
批量解决问题
# Via API
curl -X PUT -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "resolved"}' \
"https://sentry.io/api/0/projects/{org}/{project}/issues/?id=123&id=456"
导出事件
# Query events via Discover
curl -H "Authorization: Bearer $TOKEN" \
"https://sentry.io/api/0/organizations/{org}/events/?field=title&field=count()&query=event.type:error&statsPeriod=7d"
故障排查
| 问题 | 解决方案 |
|---|---|
| 未显示事件 | 检查 DSN,确认网络连接正常,启用 debug: true |
| Source Maps 无法正常工作 | 确认发布版本匹配,检查 URL 前缀,使用 sourcemaps explain |
| 事件量过大 | 实施采样,使用 beforeSend 进行筛选 |
| 性能开销过高 | 降低 tracesSampleRate,禁用不必要的集成 |
| 自托管 OOM | 增加内存,添加交换空间,进行水平扩展 |
Reference Documentation
- SDK Configuration: Detailed SDK options
- CLI Commands: Complete CLI reference
- API Endpoints: Full API documentation
- Self-Hosting: Deployment guide
- Alerting: Alert configuration patterns
评论
支持 Markdown