mcpField
S
sentry-span-streaming-js

sentry-span-streaming-js

github.com/getsentry开发272502 次安装今天更新
代码仓库

关于 sentry-span-streaming-js

用于将 JavaScript Sentry SDK 项目从基于事务的追踪迁移到 span 流式传输的技能。它涵盖浏览器、服务端和框架配置,以及回调与属性调整,并提供构建和运行时检查。

主要功能

  1. 01检测 JavaScript SDK 环境与配置
  2. 02为浏览器和服务端 SDK 启用流式传输
  3. 03调整 span 回调和标签属性
  4. 04替换事务回调与过滤器
  5. 05验证构建和 span 流式传送

适用场景

  1. 01将 JavaScript 应用迁移为逐个发送 span
  2. 02更新 beforeSendSpan 和 beforeSendTransaction 行为
  3. 03检查 span 可见性及回退警告

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/getsentry/sentry-for-ai --skill sentry-span-streaming-js

安装后在 Claude Code 中输入/sentry-span-streaming-js确认已加载。

详细介绍

所有技能 > 功能设置 > Span 流式传输(JavaScript)

Sentry Span 流式传输迁移(JavaScript)

从默认的基于事务的跟踪生命周期(static)迁移到 Span 流式传输(stream):Span 完成后会逐个发送,而不是在最后批量打包到一个事务中。

本技能涵盖 JavaScript SDK(Browser、Node.js、Bun、Deno、Cloudflare)。Python 请参阅 Span 流式传输(Python)。Dart/Flutter 请参阅 Span 流式传输(Dart)。

在以下情况下调用本技能

  • 用户要求在 JavaScript 项目中“启用 Span 流式传输”或“迁移到 Span 流式传输”
  • 用户想从基于事务的 Span 传递方式切换到流式传递
  • 用户提到 traceLifecycle、spanStreamingIntegration 或 withStreamedSpan
  • 用户想降低 Span 传递延迟或按 Span 进行处理

阶段 1:检测

1.1 检测环境
# Detect if browser, server, or both
grep -rn "from '@sentry/browser'\|from '@sentry/react'\|from '@sentry/vue'\|from '@sentry/angular'\|from '@sentry/svelte'\|from '@sentry/nextjs'\|from '@sentry/nuxt'\|from '@sentry/sveltekit'\|from '@sentry/remix'\|from '@sentry/solidstart'\|from '@sentry/astro'\|from '@sentry/react-router'" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null | head -20

grep -rn "from '@sentry/node'\|from '@sentry/bun'\|from '@sentry/deno'\|from '@sentry/cloudflare'" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null | head -20
1.2 查找现有的 Sentry 配置
# Find Sentry.init calls
grep -rn "Sentry\.init\|init({" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null | head -20

# Find beforeSendSpan usage
grep -rn "beforeSendSpan" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null

# Find beforeSendTransaction usage
grep -rn "beforeSendTransaction" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null

# Find ignoreSpans usage
grep -rn "ignoreSpans" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null
1.3 对环境分类

根据检测结果,将每个 Sentry.init 调用分类如下:

环境包迁移路径
Browser@sentry/browser、@sentry/react、@sentry/vue、@sentry/angular、@sentry/svelte添加 spanStreamingIntegration()
服务端@sentry/node、@sentry/bun、@sentry/deno、@sentry/cloudflare添加 traceLifecycle: 'stream'
框架(两端)@sentry/nextjs、@sentry/nuxt、@sentry/sveltekit、@sentry/remix、@sentry/astro、@sentry/solidstart、@sentry/react-router分别迁移客户端和服务端配置

阶段 2:迁移

前提条件: Sentry JavaScript SDK 版本为 >=10.66.0,且已启用跟踪(配置了 tracesSampleRate 或 tracesSampler)。

对每个 Sentry.init 调用应用更改。逐一处理上面找到的文件。

2.1 启用 Span 流式传输
服务端 SDK

在 Sentry.init() 中添加 traceLifecycle: 'stream':

// Before
Sentry.init({
  dsn: '...',
  tracesSampleRate: 1.0,
});

// After
Sentry.init({
  dsn: '...',
  tracesSampleRate: 1.0,
  traceLifecycle: 'stream',
});
浏览器端 SDK

在 integrations 数组中添加 Sentry.spanStreamingIntegration()。该集成会自动启用 traceLifecycle: 'stream',无需手动设置。

// Before
Sentry.init({
  dsn: '...',
  integrations: [
    Sentry.browserTracingIntegration(),
  ],
  tracesSampleRate: 1.0,
});

// After
Sentry.init({
  dsn: '...',
  integrations: [
    Sentry.spanStreamingIntegration(),
    Sentry.browserTracingIntegration(),
  ],
  tracesSampleRate: 1.0,
});

spanStreamingIntegration() 与其他集成的顺序无关紧要。

框架 SDK(客户端 + 服务端)

将浏览器迁移方式应用于客户端配置文件,将服务端迁移方式应用于服务端配置文件。常见模式如下:

框架客户端配置服务端配置
Next.jssentry.client.config.tssentry.server.config.ts、sentry.edge.config.ts
Nuxt模块中的客户端 Sentry.init模块中的服务端 Sentry.init
SvelteKitsrc/hooks.client.tssrc/hooks.server.ts
Remixentry.client.tsxentry.server.tsx
Astro客户端初始化服务端初始化
2.2 迁移 beforeSendSpan

如果用户有 beforeSendSpan 回调,必须使用 Sentry.withStreamedSpan() 对其进行包装,才能在流式模式下正常工作。若不使用此包装,SDK 会回退到静态模式。

回调的结构也会发生变化:

  • description 现在是 name
  • data 现在是 attributes
  • Span 对象从 SpanJSON 变为 StreamedSpanJSON
// Before (static mode)
Sentry.init({
  beforeSendSpan: (span) => {
    if (span.description?.includes('/health')) {
      span.description = '[filtered]';
    }
    // 'data' contains span attributes
    delete span.data?.['http.request.body'];
    return span;
  },
});

// After (streaming mode)
Sentry.init({
  beforeSendSpan: Sentry.withStreamedSpan((span) => {
    if (span.name?.includes('/health')) {
      span.name = '[filtered]';
    }
    // 'attributes' replaces 'data'
    if (span.attributes) {
      delete span.attributes['http.request.body'];
    }
    return span;
  }),
});

回调中的主要差异:

静态(SpanJSON)流式(StreamedSpanJSON)
span.descriptionspan.name
span.data(处理后的属性)span.attributes(原始属性)
span.timestamp(结束时间)span.end_timestamp
span.status(可选字符串)span.status('ok' 或 'error')
span.opspan.attributes['sentry.op']

从 beforeSendSpan 返回 null 不会丢弃 Span;该返回值会被忽略,并记录一条警告。

2.3 将 setTag(s) 迁移到 setAttribute(s)

在流式模式下,标签不再适用于流式 span——只有属性适用。凡是用户通过 Sentry.setTag / Sentry.setTags 或 scope.setTag / scope.setTags 设置标签的地方(例如通过 withScope()、getCurrentScope()、getGlobalScope()),都添加对应的 setAttribute / setAttributes 调用,并使用相同的键值对,以确保数据仍能传递到 span。

标签仍可用于错误,因此保留现有的 setTag(s) 调用,并在旁边添加属性调用——不要用其中一个替换另一个。

查找现有用法:

grep -rn "\.setTag\b\|\.setTags\b\|setTag(\|setTags(" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" 2>/dev/null

执行迁移。大多数 setTag(s) 调用都位于也会生成 span 的代码路径中,因此除非调用明显仅用于错误报告,否则默认添加对应的属性调用。

// Before
Sentry.setTag('feature', 'checkout');
Sentry.setTags({ tier: 'premium', region: 'eu' });

// After — keep the tags, add matching attributes
Sentry.setTag('feature', 'checkout');
Sentry.setAttribute('feature', 'checkout');

Sentry.setTags({ tier: 'premium', region: 'eu' });
Sentry.setAttributes({ tier: 'premium', region: 'eu' });

基于 scope 的调用也同样适用:

// Before
Sentry.withScope((scope) => {
  scope.setTag('job', 'sync-orders');
  // ...
});
Sentry.getCurrentScope().setTag('job', 'sync-orders')

// After
Sentry.withScope((scope) => {
  scope.setTag('job', 'sync-orders');
  scope.setAttribute('job', 'sync-orders');
  // ...
});
Sentry.getCurrentScope().setTag('job', 'sync-orders')
Sentry.getCurrentScope().setAttribute('job', 'sync-orders')

SDK >=10.66.0 起提供 setAttribute(s)——执行此步骤前,请确认满足版本要求。

2.4 移除或替换 beforeSendTransaction

beforeSendTransaction 在流式模式下不起作用。span 会单独发送,而不是批量发送为 transaction。

// Before
Sentry.init({
  beforeSendTransaction: (event) => {
    // This entire callback is ignored in streaming mode
    if (event.transaction === '/health') {
      return null;
    }
    return event;
  },
});

根据 beforeSendTransaction 的用途选择迁移方式:

用途流式模式替代方案
按名称/路由丢弃 span使用 ignoreSpans 选项
发送前修改 span 数据使用 withStreamedSpan 配合 beforeSendSpan
按 transaction 名称筛选使用带有字符串/RegExp 模式的 ignoreSpans
为 transaction 添加标签/上下文使用 withStreamedSpan 配合 beforeSendSpan

迁移其逻辑后,从 Sentry.init() 中移除 beforeSendTransaction 选项。

2.5 配置 ignoreSpans(可选)

ignoreSpans 在静态模式和流式模式下均有效,但筛选器会在 span 生命周期的不同阶段进行评估:

  • 流式模式: 在 span 开始时进行评估。仅考虑 span 开始时可用的数据——span 名称和创建时设置的属性。
  • 静态模式: 在根 span 结束时进行评估。仅考虑该时刻可用的数据——span 名称和属性。

在两种模式下,匹配成功都会阻止记录或发送该 span。由于筛选器最早可能在 span 开始时运行(流式模式),因此只有 span 名称和 span 开始时设置的属性可以保证可用——不要依赖 span 生命周期后期添加的属性。

Sentry.init({
  traceLifecycle: 'stream',
  ignoreSpans: [
    // String match against span name
    '/health',
    '/ready',

    // RegExp match against span name
    /^OPTIONS /,

    // Object filter — all conditions must match
    {
      op: 'middleware.handle',
      name: /^corsMiddleware/,
    },

    // Filter by attributes (string = substring match, RegExp for patterns)
    {
      op: 'http.server',
      attributes: {
        'http.route': /^\/internal\//,
      },
    },
  ],
});

筛选对象属性:

属性类型匹配对象
namestring | RegExpspan 名称(描述)
opstring | RegExpspan 操作
attributesRecord<string, string | RegExp | number | boolean | Array>span 属性

筛选对象中指定多个属性时,所有属性都必须匹配,才会忽略该 span。

2.6 设置浏览器性能分析(可选)

在浏览器中使用 Span 流式传输时,请使用 v2 性能分析选项,而不是旧版 profilesSampleRate。旧版选项已弃用,且无法与 Span 流式传输生命周期集成。

添加 browserProfilingIntegration(),并配置以下两个 v2 选项:

// Before (legacy profiling — do NOT use with span streaming)
Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration(),
  ],
  tracesSampleRate: 1.0,
  profilesSampleRate: 0.5, // deprecated
});

// After (v2 profiling with span streaming)
Sentry.init({
  integrations: [
    Sentry.spanStreamingIntegration(),
    Sentry.browserTracingIntegration(),
    Sentry.browserProfilingIntegration(),
  ],
  tracesSampleRate: 1.0,
  profileSessionSampleRate: 1.0,
  profileLifecycle: 'trace',
});

v2 性能分析选项:

选项类型描述
profileSessionSampleRatenumber(0–1)启用性能分析的用户会话百分比。默认值:0(禁用)。
profileLifecycle'trace' | 'manual''trace':存在已采样的根 Span 时,性能分析器会自动运行。'manual':通过 Sentry.uiProfiler.startProfiler() / stopProfiler() 显式启动/停止性能分析器。默认值:'manual'。

profileLifecycle: 'trace' 要求启用追踪(tracesSampleRate 或 tracesSampler)。根 Span 开始时,性能分析器会启动;所有已采样的根 Span 均结束后,性能分析器会停止。Profile 分块每 60 秒独立发送一次,或在最后一个根 Span 结束时发送。

请勿混用旧版和 v2 选项。如果设置了 profilesSampleRate,profileSessionSampleRate 将不起作用,且 SDK 会记录警告。


第 3 阶段:验证

应用更改后,请验证迁移是否正常工作。

3.1 构建检查
# TypeScript check
npx tsc --noEmit 2>&1 | head -30

# Build
npm run build 2>&1 | tail -20
3.2 运行时验证

指导用户在浏览器开发者工具或服务日志中进行验证:

  1. 检查网络选项卡:Span 信封应作为单独请求出现,内容类型为 application/vnd.sentry.items.span.v2+json,而不是事务信封
  2. 检查 Sentry 仪表板:Span 完成后不久就应出现在 Traces 视图中,无需等待整个事务结束
  3. 检查回退警告:如果 SDK 记录了回退到静态模式的警告,则 beforeSendSpan 回调可能缺少 withStreamedSpan 包装器
3.3 常见问题
症状原因修复方法
SDK 回退到静态模式beforeSendSpan 未使用 withStreamedSpan 包装包装回调:Sentry.withStreamedSpan(callback)
未调用 beforeSendTransaction流式模式下的预期行为将逻辑迁移到 beforeSendSpan 或 ignoreSpans
Span 仍以事务形式到达未设置 traceLifecycle,或缺少集成服务端:添加 traceLifecycle: 'stream';浏览器:添加 spanStreamingIntegration()
span.description 上出现类型错误StreamedSpanJSON 使用 name 而非 description在回调中将 span.description 改为 span.name
span.data 上出现类型错误StreamedSpanJSON 使用 attributes 而非 data在回调中将 span.data 改为 span.attributes
profileSessionSampleRate 无效同时设置了旧版 profilesSampleRate移除 profilesSampleRate,仅使用 profileSessionSampleRate + profileLifecycle
Span 缺少标签标签不适用于流式传输的 Span在现有 setTag(s) 调用旁添加对应的 setAttribute(s) 调用

快速参考

最简服务端配置
import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: '__DSN__',
  tracesSampleRate: 1.0,
  traceLifecycle: 'stream',
});
最简浏览器配置
import * as Sentry from '@sentry/browser';

Sentry.init({
  dsn: '__DSN__',
  integrations: [
    Sentry.spanStreamingIntegration(),
    Sentry.browserTracingIntegration(),
  ],
  tracesSampleRate: 1.0,
});
含性能分析的浏览器配置
import * as Sentry from '@sentry/browser';

Sentry.init({
  dsn: '__DSN__',
  integrations: [
    Sentry.spanStreamingIntegration(),
    Sentry.browserTracingIntegration(),
    Sentry.browserProfilingIntegration(),
  ],
  tracesSampleRate: 1.0,
  profileSessionSampleRate: 1.0,
  profileLifecycle: 'trace',
});
完整迁移清单
  • SDK 版本为 >=10.66.0
  • 服务端配置:已添加 traceLifecycle: 'stream'
  • 浏览器配置:已添加 spanStreamingIntegration()
  • beforeSendSpan 回调已使用 Sentry.withStreamedSpan() 包装
  • beforeSendSpan 回调已更新:description -> name,data -> attributes
  • setTag(s) / scope.setTag(s) 调用已配套添加对应的 setAttribute(s) 调用
  • beforeSendTransaction 逻辑已迁移到 beforeSendSpan 或 ignoreSpans
  • 已从配置中移除 beforeSendTransaction
  • (如果启用了性能分析)已将 profilesSampleRate 替换为 profileSessionSampleRate + profileLifecycle
  • (如果启用了性能分析)已将 browserProfilingIntegration() 添加到 integrations
  • 构建通过,且没有类型错误
  • Sentry 仪表板中可见 Span

评论

支持 Markdown