关于 add-error-tracking
add-error-tracking 是一项将 Temps 错误跟踪接入应用的技能,适合需要在多种语言和框架中配置错误报告的开发者。它使用兼容 Sentry 的 DSN 和官方 Sentry SDK,并为浏览器项目说明隧道配置。
主要功能
- 01按代码库识别平台
- 02使用官方 Sentry SDK 配置
- 03通过环境变量设置 DSN
- 04为浏览器 SDK 配置隧道
- 05提供多语言平台设置示例
- 06捕获自定义异常
适用场景
- 01为 Next.js 应用接入 Temps 错误跟踪
- 02在 Node.js 或 Python 服务中报告异常
- 03为浏览器应用配置同源事件隧道
- 04为移动端或后端项目配置错误 SDK
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ gotempsh/ temps --skill add-error-tracking安装后在 Claude Code 中输入/add-error-tracking确认已加载。
详细介绍
添加错误追踪
将 Temps 错误追踪(兼容 Sentry)集成到应用中。Temps DSN 可直接替换 Sentry DSN——使用适用于用户平台的官方 Sentry SDK,并通过环境变量将其指向 Temps DSN。
优先使用 Sentry 针对各框架提供的官方技能(如有)
Temps 与 Sentry 在线路协议上兼容,因此 Sentry 为其 SDK 发布的所有技能都可与 Temps DSN 配合使用。如果用户的 CLI 已安装以下技能之一,请引导他们使用该技能,只替换 DSN:
| 用户的平台 | Sentry 技能 | 来源 |
|---|---|---|
| Next.js | /sentry-nextjs-sdk | getsentry/sentry-for-ai |
| React(Vite、Remix 等) | /sentry-react-sdk | getsentry/sentry-for-ai |
| 原生浏览器 JS | /sentry-browser-sdk | getsentry/sentry-for-ai |
| Node.js | /sentry-node-sdk | getsentry/sentry-for-ai |
| React Native | /sentry-react-native-sdk | getsentry/sentry-for-ai |
| 通用(语言无关) | /sentry-sdk-setup | getsentry/sentry-for-ai |
对于 Sentry 没有专用技能的平台(Vue、Svelte、Angular、Python、Go、Rust、Ruby、Java、PHP、.NET、Flutter 等),请直接按照本文件中的设置说明操作。
务必通过环境变量设置 DSN,切勿将其硬编码。 用户应将环境变量指向自己的 Temps DSN,而不是 Sentry DSN。
检测平台
根据代码库推断平台:
package.json中包含"next"→ Next.js →@sentry/nextjspackage.json中包含"react",且使用 Vite/Remix/CRA → React →@sentry/reactpackage.json中包含"vue"或"nuxt"→ Vue →@sentry/vuepackage.json中包含"svelte"或"@sveltejs/kit"→ Svelte →@sentry/sveltekitpackage.json中包含"@angular/core"→ Angular →@sentry/angularpackage.json中包含"express"、"fastify"、"@nestjs/core"→ Node.js →@sentry/nodepackage.json中包含"react-native"或"expo"→ React Native →@sentry/react-nativerequirements.txt/pyproject.toml中包含 Flask、Django、FastAPI → Python →sentry-sdkgo.mod→ Go →github.com/getsentry/sentry-goCargo.toml→ Rust →sentryGemfile中包含rails→ Ruby →sentry-ruby+sentry-railspom.xml/build.gradle中包含 Spring → Java →sentry-spring-boot-starter-jakartacomposer.json中包含laravel/framework或symfony/*→ PHP →sentry/sentry.csproj中包含Microsoft.AspNetCore.*→ .NET →Sentry.AspNetCorepubspec.yaml中包含flutter→ Flutter →sentry_flutter
获取 DSN
用户的 Temps 项目在 错误追踪 → DSN 与设置 中提供 DSN。格式如下:
https://<public_key>@<temps-host>/<project_id>
如果用户尚未提供 DSN,请告知他们:
- 在 Temps 控制面板中打开项目
- 前往 错误追踪 → DSN 与设置
- 复制目标环境对应的 DSN
务必将 DSN 存储在环境变量中。具体变量名取决于平台(浏览器打包工具通常要求使用特定前缀,才能将变量暴露给客户端):
| 平台 | 环境变量名 |
|---|---|
| Next.js | NEXT_PUBLIC_SENTRY_DSN |
| Vite / React / Vue | VITE_SENTRY_DSN |
| SvelteKit | PUBLIC_SENTRY_DSN |
| Angular | SENTRY_DSN(通过 environment.ts 注入) |
| 其他所有平台(Node、Python、Go、Rust、Ruby、Java、PHP、.NET、Flutter) | SENTRY_DSN |
# .env
SENTRY_DSN=https://<public_key>@<temps-host>/<project_id>
浏览器 SDK:也要传入 tunnel
对于所有浏览器平台(Next.js 客户端配置、React、Vue、Svelte、原生 JS——不包括服务端 SDK,也不包括 React Native/Flutter),还要在同一次 Sentry.init 调用中传入
tunnel:
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
tunnel: process.env.NEXT_PUBLIC_SENTRY_TUNNEL,
});
原因:如果不设置 tunnel,SDK 会直接向 DSN 的主机(Temps 控制台)发送 POST 请求。这是来自应用自身域名的第三方跨源请求——广告拦截器通常会拦截此类请求,而且每个事件都要进行一次 CORS 预检。将 tunnel 设置为同源路径后,浏览器会改为向应用自身的域名发送请求;Temps 的代理会将 /api/_temps 下的所有请求转发到控制台,不受请求来自哪个项目域名的影响,因此在自定义域名和预览 URL 上都无需修改即可使用。
该值是固定路径,并非密钥——Temps 会自动将其作为环境变量注入,并与 DSN 一同注入,使用相同的打包工具专属公开前缀(因此,如果 DSN 会进入客户端包,tunnel 路径也会):
| 平台 | DSN 环境变量 | Tunnel 环境变量 |
|---|---|---|
| Next.js | NEXT_PUBLIC_SENTRY_DSN | NEXT_PUBLIC_SENTRY_TUNNEL |
| Vite / React / Vue | VITE_SENTRY_DSN | VITE_SENTRY_TUNNEL |
| SvelteKit | PUBLIC_SENTRY_DSN | PUBLIC_SENTRY_TUNNEL |
| Angular | SENTRY_DSN(通过 environment.ts) | (无——没有公开前缀约定;跳过 tunnel) |
如果部署在 Temps 之外(或由于其他原因未设置 tunnel 变量),有两种选择。省略 tunnel——SDK 会回退为直接向 DSN 主机发送请求,仍然可以正常工作,只是会产生跨源请求。或者,将 tunnel 指向 Temps 实例的绝对 tunnel URL,例如
tunnel: "https://your-temps-instance.example.com/api/_temps/sentry/envelope":
该端点会根据 SDK 嵌入事件信封中的 DSN 来解析项目,因此无需通过 Temps 提供应用服务。这样,即使应用不由 Temps 托管,tunnel 仍能抵御广告拦截器,但代价是会产生同源方案可以避免的跨源请求。
除非确实需要,否则浏览器项目应省略 Sentry.replayIntegration() 和 tracesSampleRate——Temps 目前尚未接收 Sentry 会话回放或性能事务数据,因此这些流量会被上传(通过 tunnel,消耗访客的带宽),随后在服务端丢弃。对于这些功能,请改用 Temps 自己的会话回放和分析 SDK(参见 add-session-recording 和 add-react-analytics 技能)。
平台配置
以下每个代码片段都会从环境变量读取 DSN——不要将其硬编码。
Next.js
npx @sentry/wizard@latest -i nextjs
或手动配置:
npm install @sentry/nextjs
// sentry.client.config.ts (or instrumentation-client.ts on newer @sentry/nextjs)
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
tunnel: process.env.NEXT_PUBLIC_SENTRY_TUNNEL,
});
在 sentry.server.config.ts 和 sentry.edge.config.ts 中设置相同的 dsn(不设置 tunnel,也不启用回放)——这些配置在服务端运行,会直接向控制台发送请求。
不要在 withSentryConfig 中设置 tunnelRoute——这是另一种机制(通过 Next.js 服务端路由转发),其文档明确指出它不适用于自托管 Sentry,而 Temps 使用的正是 Sentry DSN 兼容层。请使用上方展示的 tunnel 选项。
React(Vite、Remix、CRA)
npm install @sentry/react
// src/sentry.ts — import this first in main.tsx / root.tsx
import * as Sentry from '@sentry/react';
Sentry.init({
dsn: import.meta.env.VITE_SENTRY_DSN,
tunnel: import.meta.env.VITE_SENTRY_TUNNEL,
environment: import.meta.env.MODE,
});
使用 <Sentry.ErrorBoundary> 包裹应用根节点,以捕获 React 渲染错误。
Vue(Vue 3 / Nuxt)
npm install @sentry/vue
// src/main.ts
import { createApp } from 'vue';
import * as Sentry from '@sentry/vue';
import App from './App.vue';
const app = createApp(App);
Sentry.init({
app,
dsn: import.meta.env.VITE_SENTRY_DSN,
tunnel: import.meta.env.VITE_SENTRY_TUNNEL,
});
app.mount('#app');
Svelte / SvelteKit
npx @sentry/wizard@latest -i sveltekit
// src/hooks.client.ts
import * as Sentry from '@sentry/sveltekit';
import { PUBLIC_SENTRY_DSN, PUBLIC_SENTRY_TUNNEL } from '$env/static/public';
Sentry.init({
dsn: PUBLIC_SENTRY_DSN,
tunnel: PUBLIC_SENTRY_TUNNEL,
});
export const handleError = Sentry.handleErrorWithSentry();
在 src/hooks.server.ts 中使用 $env/dynamic/private 设置相同配置,以获取服务端 DSN。
Angular
npm install @sentry/angular
// src/main.ts
import * as Sentry from '@sentry/angular';
import { environment } from './environments/environment';
Sentry.init({
dsn: environment.sentryDsn,
tracesSampleRate: 1.0,
});
在构建时,将 environment.sentryDsn 的值设为 process.env.SENTRY_DSN。
Angular 不会注入公开前缀的 tunnel 变量(没有可供对照的打包工具约定)——此处跳过 tunnel;SDK 会直接向 DSN 主机发送请求。
原生 JavaScript(浏览器)
npm install @sentry/browser
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: import.meta.env.VITE_SENTRY_DSN,
tunnel: import.meta.env.VITE_SENTRY_TUNNEL,
});
Node.js
npm install @sentry/node
// Must be the first import in your entrypoint.
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
});
Express 配置:
import express from 'express';
import * as Sentry from '@sentry/node';
const app = express();
Sentry.setupExpressErrorHandler(app);
React Native
npx @sentry/wizard@latest -s -i reactNative
import * as Sentry from '@sentry/react-native';
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
});
export default Sentry.wrap(App);
Python
pip install sentry-sdk
import os
import sentry_sdk
sentry_sdk.init(
dsn=os.environ["SENTRY_DSN"],
environment=os.environ.get("ENV", "development"),
traces_sample_rate=1.0,
profiles_sample_rate=1.0,
)
框架集成:
# Flask
from sentry_sdk.integrations.flask import FlaskIntegration
sentry_sdk.init(dsn=os.environ["SENTRY_DSN"], integrations=[FlaskIntegration()])
# Django
from sentry_sdk.integrations.django import DjangoIntegration
sentry_sdk.init(dsn=os.environ["SENTRY_DSN"], integrations=[DjangoIntegration()])
# FastAPI
from sentry_sdk.integrations.starlette import StarletteIntegration
from sentry_sdk.integrations.fastapi import FastApiIntegration
sentry_sdk.init(
dsn=os.environ["SENTRY_DSN"],
integrations=[StarletteIntegration(), FastApiIntegration()],
)
Go
go get github.com/getsentry/sentry-go
package main
import (
"log"
"os"
"time"
"github.com/getsentry/sentry-go"
)
func main() {
err := sentry.Init(sentry.ClientOptions{
Dsn: os.Getenv("SENTRY_DSN"),
TracesSampleRate: 1.0,
Environment: os.Getenv("ENV"),
})
if err != nil {
log.Fatalf("sentry.Init: %s", err)
}
defer sentry.Flush(2 * time.Second)
}
Rust
cargo add sentry sentry-tracing
use std::env;
fn main() {
let _guard = sentry::init((
env::var("SENTRY_DSN").expect("SENTRY_DSN must be set"),
sentry::ClientOptions {
release: sentry::release_name!(),
traces_sample_rate: 1.0,
environment: env::var("ENV").ok().map(Into::into),
..Default::default()
},
));
// Your app entrypoint
}
Ruby(Rails)
bundle add sentry-ruby sentry-rails
# config/initializers/sentry.rb
require "sentry-ruby"
require "sentry-rails"
Sentry.init do |config|
config.dsn = ENV["SENTRY_DSN"]
config.environment = ENV.fetch("RAILS_ENV", "development")
config.traces_sample_rate = 1.0
end
Java(Spring Boot)
<dependency>
<groupId>io.sentry</groupId>
<artifactId>sentry-spring-boot-starter-jakarta</artifactId>
<version>7.14.0</version>
</dependency>
# application.properties — Spring reads ${SENTRY_DSN} from the environment
sentry.dsn=${SENTRY_DSN}
sentry.environment=${ENV:development}
sentry.traces-sample-rate=1.0
PHP
composer require sentry/sentry
<?php
\Sentry\init([
'dsn' => $_ENV['SENTRY_DSN'],
'environment' => $_ENV['APP_ENV'] ?? 'development',
'traces_sample_rate' => 1.0,
]);
对于 Laravel,请使用 sentry/sentry-laravel,并通过 config/sentry.php 读取 env('SENTRY_DSN') 进行配置。
.NET(ASP.NET Core)
dotnet add package Sentry.AspNetCore
// Program.cs
builder.WebHost.UseSentry(options =>
{
options.Dsn = Environment.GetEnvironmentVariable("SENTRY_DSN");
options.Environment = builder.Environment.EnvironmentName;
options.TracesSampleRate = 1.0;
});
Flutter
flutter pub add sentry_flutter
import 'package:flutter/widgets.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
Future<void> main() async {
await SentryFlutter.init(
(options) {
options.dsn = const String.fromEnvironment('SENTRY_DSN');
options.tracesSampleRate = 1.0;
},
appRunner: () => runApp(const MyApp()),
);
}
在构建时传入 DSN:flutter run --dart-define=SENTRY_DSN=$SENTRY_DSN。
捕获自定义错误
JavaScript / TypeScript
import * as Sentry from '@sentry/react'; // or /browser, /node, /nextjs, etc.
try {
doRiskyThing();
} catch (err) {
Sentry.captureException(err);
}
Sentry.captureMessage('Something notable happened', 'warning');
Python
try:
do_risky_thing()
except Exception as exc:
sentry_sdk.capture_exception(exc)
sentry_sdk.capture_message("Something notable happened", level="warning")
Go
sentry.CaptureException(err)
sentry.CaptureMessage("Something notable happened")
Rust
sentry::capture_error(&err);
sentry::capture_message("Something notable happened", sentry::Level::Warning);
Source maps(仅限 JS/TS)
在 CI 期间上传 source maps,这样 Temps 仪表板就能在堆栈跟踪中显示原始源代码。
npm install --save-dev @sentry/cli
sentry-cli sourcemaps inject ./dist
sentry-cli sourcemaps upload \
--url-prefix '~/' \
--release "$GIT_SHA" \
./dist
Temps 仪表板也支持通过界面中的 Error Tracking → Source Maps 上传 source maps。
验证
接入完成后:
- 在应用中主动抛出错误:
- JS / TS:
throw new Error('Temps error tracking test'); - Python:
raise Exception('Temps error tracking test') - Go:
sentry.CaptureException(errors.New("Temps test")) - Rust:
panic!("Temps test")(在由 Sentry 集成捕获的处理程序中)
- JS / TS:
- 运行应用,并触发会抛出错误的路径。
- 打开 Temps 仪表板中的 Error Tracking → Error Groups — 错误应在几秒内出现。
- 确认堆栈跟踪和环境信息均已填充。
常见问题
- 没有显示任何内容:请确认已加载 DSN 环境变量,并且 SDK 在任何可能抛出错误的代码运行前已初始化。对于 Node,
Sentry.init必须是第一个导入项。 - 堆栈跟踪已压缩:请上传 source maps(见上文)。
- 浏览器应用未上报:请确保环境变量使用打包工具的公开前缀(
NEXT_PUBLIC_、VITE_、PUBLIC_),以便它能进入客户端包。 - 生产环境缺少事件:请确认部署环境已设置 DSN 环境变量 — 本地
.env文件不会自动复制。 - 隧道请求返回 403:隧道端点会检查请求的
Origin(或Referer)是否与请求到达的域名匹配 — 这可以阻止脚本向他人的项目发送伪造事件,但也会拒绝任何会删除或重写Origin的请求代理或改写操作。请确认浏览器与应用之间没有任何环节移除该标头。 - 隧道请求返回 404:隧道会通过 Temps 的路由表,从
Host标头解析项目 — 这仅适用于实际部署在 Temps 上的域名。用于 Temps 未提供服务的域名上的tunnel环境变量(例如,使用其他环境的 URL 进行测试)没有可供解析的目标。