From b7d40bf1fbe7033f41fcc5255e0f661b5bc8ca22 Mon Sep 17 00:00:00 2001 From: Martin Sonnberger Date: Tue, 15 Sep 2026 13:55:00 +0200 Subject: [PATCH] docs(javascript): Document span streaming callbacks as the default Keep static-mode transaction APIs and examples alongside streamed spans. Fixes SDK-1473 --- .../javascript/common/configuration/apis.mdx | 26 +-- .../common/configuration/filtering.mdx | 74 +++---- .../common/configuration/options.mdx | 92 ++++---- .../data-management/sensitive-data/index.mdx | 6 +- .../transaction-name/index.mdx | 16 +- .../common/mcp-monitoring/index.mdx | 10 +- .../common/tracing/streamed-spans/index.mdx | 208 +++--------------- .../common/tracing/troubleshooting/index.mdx | 23 +- .../before-send-span/javascript.mdx | 23 +- .../before-send-transaction/javascript.mdx | 2 +- .../ignore-transactions/javascript.mdx | 1 + 11 files changed, 173 insertions(+), 308 deletions(-) diff --git a/docs/platforms/javascript/common/configuration/apis.mdx b/docs/platforms/javascript/common/configuration/apis.mdx index 8548854d27761..4a3bab37bdfef 100644 --- a/docs/platforms/javascript/common/configuration/apis.mdx +++ b/docs/platforms/javascript/common/configuration/apis.mdx @@ -134,13 +134,12 @@ Sentry.withScope((scope) => { }); ``` - - `beforeSend`, `beforeSendTransaction`, and `beforeSendSpan` are guaranteed to be run last, after all other event processors, (which means they get the final version of the event right before it's sent, hence the name). Event processors added with `addEventProcessor` are run in an undetermined order, which means changes to the event may still be made after the event processor runs. + + `beforeSend` runs after all event processors and receives the final error or message event before it is sent. Event processors added with `addEventProcessor` run in an undetermined order, so another processor may still change the event afterward. - There can only be a single `beforeSend` / `beforeSendTransaction` / `beforeSendSpan` callback, but you can add multiple event processors via `addEventProcessor()`. - - If you're using stream mode, use `beforeSendSpan`, since event processors are not applied to spans. + You can configure one `beforeSend` callback and add multiple event processors with `addEventProcessor()`. + Event processors do not run on streamed spans. Use `beforeSendSpan` to modify each finished span before it is sent. In static mode, event processors also run on transaction events, followed by `beforeSendTransaction`. You can configure one `beforeSendTransaction` callback. @@ -842,18 +841,15 @@ Sentry.reportPageLoaded(); These utilities can be used for more advanced tracing use cases. - - Convert a span to a JSON object. If you're using{" "} - stream mode, we - recommend using [`spanToStreamedSpanJSON`](#spanToStreamedSpanJSON) instead. + + Convert a span to a JSON object. If you're using {" "} + `traceLifecycle: 'static'`, + use [`spanToStaticSpanJSON`](#spanToStaticSpanJSON) to get the `SpanJSON` format. - - Convert a span to a JSON object. Only available in{" "} - stream mode. + + Convert a span to the static `SpanJSON` format. Use this when working with transaction data in + static mode. -## Filtering Transaction Events - - - The options in this section are only available in transaction mode. If you're - using stream mode, go to - [Filtering Spans](#filtering-spans). - - -To prevent certain transactions from being reported to Sentry, use the or configuration option, which allows you to provide a function to evaluate the current transaction and drop it if it's not one you want. - -### Using - -You can use the option to filter out transactions that match a certain pattern. This option receives a list of strings and regular expressions to match against the transaction name. When using strings, partial matches will be filtered out. If you need to filter by exact match, use regex patterns instead. - - - -See ignoreTransactions for details. - -### Using - -You can also use the tracesSampler option to prevent certain transactions from being reported to Sentry. - -See Sampling on information about how to use it. - -### Using `beforeSendTransaction` - - - -See beforeSendTransaction for details, and [Using Hints](#using-hints) for details on the `hint` object. - ## Filtering Spans -### Using - -Use the configuration option, which lets you provide a function to modify a span. -This function is called for the transaction (service span in stream mode) and all child spans. +Use `beforeSendSpan` to change span data and `ignoreSpans` to drop spans. To make sampling decisions when spans start, use `tracesSampler`. -If you want to drop the transaction/service span, including its child spans: - -- Use [`beforeSendTransaction`](#using-beforesendtransaction) in transaction mode. -- Use [`ignoreSpans`](#using-ignore-spans) in stream mode. +### Using - +Use the configuration option to modify each finished span before it is sent. This function is called for all spans, including service spans and their child spans. -If you're using stream mode, make sure to wrap with `Sentry.withStreamedSpan()`. +Check `span.is_segment` to modify only service spans. In static mode, wrap the callback with `Sentry.withStaticSpan()` to modify the transaction and its child spans using the `SpanJSON` format. - +To drop a service span and its child spans, use [`ignoreSpans`](#using-ignore-spans). `beforeSendSpan` cannot return `null` to drop spans. @@ -169,12 +133,14 @@ You can use the option to filter out You can also provide an object with `name`, `op`, and `attributes` properties to match on multiple conditions. At least one property must be provided. +In stream mode, rules run when the span starts, so later name and attribute changes do not affect matching. In static mode, rules use the final name and attributes when the transaction ends. Ignoring a service span drops its child spans; ignoring a child span reparents its children to the nearest ancestor. + ```javascript Sentry.init({ dsn: "___PUBLIC_DSN___", ignoreSpans: [ - "partial/match", - /^Exact Span Name$/, + { name: "partial/match", op: "http.server" }, + { name: /^Exact Span Name$/, op: "http.server" }, { name: /^GET \//, attributes: { @@ -185,8 +151,30 @@ Sentry.init({ }); ``` +Use the operation of your service span, such as `http.server`, `pageload`, or `navigation`, to avoid matching unrelated child spans with the same name. + See ignoreSpans for details. +## Filtering Transaction Events + +These options apply when `traceLifecycle: 'static'` is set. In the default stream mode, use [Filtering Spans](#filtering-spans). + +### Using + +Use `ignoreTransactions` to drop transactions whose names match a string or regular expression. Strings match part of the name. Use an anchored regular expression for an exact match. Matching transactions and their child spans are dropped. + + + +See `ignoreTransactions` for details. + +### Using `beforeSendTransaction` + +Use `beforeSendTransaction` to modify or drop a completed transaction before it is sent. Return the transaction event to send it, or `null` to drop it and its child spans. + + + +See `beforeSendTransaction` for details and [Using Hints](#using-hints) for the `hint` argument. + ## Filtering Breadcrumbs You can filter breadcrumbs by using the `beforeBreadcrumb` configuration option: diff --git a/docs/platforms/javascript/common/configuration/options.mdx b/docs/platforms/javascript/common/configuration/options.mdx index 00747954306fd..a1a5642aa2335 100644 --- a/docs/platforms/javascript/common/configuration/options.mdx +++ b/docs/platforms/javascript/common/configuration/options.mdx @@ -617,37 +617,15 @@ This is useful to prevent traces of unknown third-party services from being cont - - -This function is called with a transaction event object, and can return a modified transaction event object, or `null` to skip reporting the event. This can be used, for instance, for manual PII stripping before sending. - -Not available in stream mode. Instead, use [`ignoreSpans`](#ignoreSpans) to drop spans, or [`beforeSendSpan`](#beforeSendSpan) to modify spans. - - - - - -This function is called with a serialized span object and can return a modified span object. Use it, for example, to manually strip PII from spans or filter data from spans before they're sent to Sentry. It runs for all spans, including transactions and their child spans. - -Note that `beforeSendSpan` can only modify span data, meaning you cannot use it to drop spans. Use [`ignoreSpans`](#ignoreSpans) to drop spans, or [`beforeSendTransaction`](#beforeSendTransaction) to drop transactions. - -The `span` you receive as an argument is a serialized object, not a `Span` class instance. - -If you're using stream mode, wrap `beforeSendSpan` with `Sentry.withStreamedSpan()` — otherwise the SDK falls back to transaction mode. + - +Called for each finished span before it is sent to Sentry, including service spans and their child spans. Return the modified span to rename it or remove sensitive data. Check `span.is_segment` to apply changes only to service spans. -In stream mode, the span object is `StreamedSpanJSON` instead of `SpanJSON` and has different property names: +`beforeSendSpan` can only modify spans. It cannot drop them or return `null`. Use [`ignoreSpans`](#ignoreSpans) to drop spans. -| Transaction Mode (`SpanJSON`) | Stream Mode (`StreamedSpanJSON`) | -| ---------------------------------- | ----------------------------------- | -| `span.description` | `span.name` | -| `span.data` (processed attributes) | `span.attributes` (raw attributes) | -| `span.timestamp` (end time) | `span.end_timestamp` | -| `span.status` (optional string) | `span.status` (`'ok'` or `'error'`) | -| `span.op` | `span.attributes['sentry.op']` | +The callback receives a serialized `StreamedSpanJSON` object, not a `Span` instance. `Sentry.spanToJSON()` returns the same shape. - +With [`traceLifecycle: 'static'`](#traceLifecycle), wrap the callback with `Sentry.withStaticSpan()` to receive and return `SpanJSON`. The static callback runs for the transaction and its child spans. A callback that doesn't match the trace lifecycle is ignored. @@ -657,11 +635,17 @@ In stream mode, the span object is `StreamedSpanJSON` instead of `SpanJSON` and - + + +Deprecated. This callback has no effect in stream mode. Use [`beforeSendSpan`](#beforeSendSpan) to modify spans and check `span.is_segment` to target service spans. Use [`ignoreSpans`](#ignoreSpans) to drop spans. + +With [`traceLifecycle: 'static'`](#traceLifecycle), this callback receives a transaction event and an event hint after all event processors have run. Return the modified event to change its data, or `null` to drop the transaction and its child spans. - + -Not available in stream mode. Use [`ignoreSpans`](#ignoreSpans) instead. + + + @@ -669,18 +653,14 @@ Not available in stream mode. Use [`ignoreSpans`](#ignoreSpans) instead. A list of strings or regex patterns matching spans that shouldn't be sent to Sentry. When using strings, partial matches will be filtered out, so if you need to filter by exact match, use regex patterns instead. You can also provide an object with `name`, `op`, and `attributes` properties to match on multiple conditions. At least one property must be provided. -If a matching span is a transaction or service span, the entire local trace will be dropped. If a child span matches, its children will be reparented to the dropped span's parent span. +If a matching span is a service span, its child spans are also dropped. If a child span matches, its children will be reparented to the dropped span's parent span. By default, no spans are ignored. In stream mode, `ignoreSpans` is evaluated at span start, so only the span name and attributes available at that point are taken into account. Any name updates or additional attributes added while the span is active won't influence whether the span is dropped. - - -In transaction mode, `ignoreSpans` is evaluated at transaction end rather than at span start. Review your existing rules to make sure the attributes you're matching on are passed when the span is created. +In static mode, `ignoreSpans` is evaluated when the transaction ends, using the span's final name and attributes. -If you're auto-instrumenting and don't know what the initial name of a span is when it starts, enable SDK debug logging during development by setting `debug: true` when initializing the SDK. - - +To inspect the initial names of automatically created spans, enable SDK debug logging during development with `debug: true`. @@ -727,6 +707,20 @@ Sentry.init({ + + +Deprecated. This option has no effect in stream mode. Use [`ignoreSpans`](#ignoreSpans) to filter spans by name, operation, or attributes. + +With [`traceLifecycle: 'static'`](#traceLifecycle), this option filters transaction names against a list of strings and regular expressions. Strings match part of the name. Use a regular expression anchored with `^` and `$` for an exact match. A matching transaction and its child spans are dropped. + + + + + + + + + If set to `true`, the SDK adds the [W3C `traceparent` header](https://www.w3.org/TR/trace-context/) to outgoing Http requests made via `fetch` or `XMLHttpRequest`. @@ -756,22 +750,24 @@ Self-hosted Sentry users should set this option to `false`, as standalone `gen_a - + Controls how spans are sent to Sentry: -- In transaction mode (`'static'`, the default), all spans are collected in memory and sent to Sentry as a single transaction once the root span ends. -- In stream mode (`'stream'`), spans are sent in batches as they finish. +- In stream mode (`'stream'`, the default), spans are sent in batches as they finish. +- In transaction mode (`'static'`), spans are collected in memory and sent as a transaction once the root span ends. This mode is available for backwards compatibility. - - - -You don't need to use this option if you're using a browser-based SDK (for example, React or Vue) or a framework SDK that handles client-side rendering (for example Next.js or Remix). -Instead, enable stream mode by adding `spanStreamingIntegration` to your integrations when initializing the SDK. - - +To opt out of span streaming, set `traceLifecycle: 'static'`. If you use `beforeSendSpan`, wrap it with `Sentry.withStaticSpan()` to receive the `SpanJSON` format: - +```javascript +Sentry.init({ + traceLifecycle: "static", + beforeSendSpan: Sentry.withStaticSpan((span) => { + span.description = "[filtered]"; + return span; + }), +}); +``` diff --git a/docs/platforms/javascript/common/data-management/sensitive-data/index.mdx b/docs/platforms/javascript/common/data-management/sensitive-data/index.mdx index 2863a6c586237..02e8d0b9c9013 100644 --- a/docs/platforms/javascript/common/data-management/sensitive-data/index.mdx +++ b/docs/platforms/javascript/common/data-management/sensitive-data/index.mdx @@ -38,17 +38,17 @@ If you _do not_ wish to use the default PII behavior, you can also choose to ide ### Scrubbing in `beforeSend*` SDK Hooks -SDKs provide various `beforeSend*` hooks, which are invoked before an errors, messages, spans, logs or metrics are sent and can be used to modify event data to remove sensitive information. The following hooks are available: +SDKs provide various `beforeSend*` hooks, which are invoked before errors, messages, spans, logs, or metrics are sent and can be used to modify event data to remove sensitive information. The following hooks are available: - `beforeSend` applies to error and message events - `beforeSendSpan` applies to spans - `beforeSendLog` applies to logs - `beforeSendMetric` applies to metrics -- `beforeSendTransaction` applies to transactions (only in transaction mode) +- `beforeSendTransaction` applies to transaction events in static mode -If you're using span stream mode, `beforeSendTransaction` has no effect. Instead, use `beforeSendSpan` with the `withStreamedSpan` helper to modify streamed spans directly. +Use `beforeSendSpan` to remove sensitive data from spans, including service spans and child spans. In static mode, wrap the callback with `Sentry.withStaticSpan()` and use `beforeSendTransaction` to scrub transaction events. diff --git a/docs/platforms/javascript/common/enriching-events/transaction-name/index.mdx b/docs/platforms/javascript/common/enriching-events/transaction-name/index.mdx index 9096d38425ae3..679db4813f0ef 100644 --- a/docs/platforms/javascript/common/enriching-events/transaction-name/index.mdx +++ b/docs/platforms/javascript/common/enriching-events/transaction-name/index.mdx @@ -104,10 +104,22 @@ Learn more about ({ dsn: env.SENTRY_DSN, tracesSampleRate: 1.0, - traceLifecycle: "stream", }), worker ); ``` -Stream mode sends span records instead of assembling one transaction event with embedded spans. `beforeSendTransaction` and `ignoreTransactions` don't apply to streamed spans. See Streamed Spans for the `beforeSendSpan` and `ignoreSpans` configuration. +Use `beforeSendSpan` to modify each finished span's `name` and `attributes`, with an `is_segment` guard to target service spans. Use the object form of `ignoreSpans` to drop spans by name and operation. See Streamed Spans for examples. If you use `McpAgent`, wrap the `McpServer` returned by its `server` getter, and wrap the Agent class separately with `instrumentAgentWithSentry` to preserve request and RPC context. Agent instrumentation, MCP server wrapping, and span streaming solve different parts of the setup; none replaces the others. See Agents SDK. @@ -90,7 +89,7 @@ If you use `McpAgent`, wrap the `McpServer` returned by its `server` getter, and ## Hono on Cloudflare Workers -If your Hono app runs on Cloudflare Workers, MCP work can finish after the Worker returns its response. Set `traceLifecycle: "stream"` in the Hono Sentry middleware so each sampled span is sent when it finishes: +If your Hono app runs on Cloudflare Workers, MCP work can finish after the Worker returns its response. The Hono Sentry middleware uses span streaming by default, so each sampled span can be sent when it finishes: ```javascript {filename:index.js} import { sentry } from "@sentry/hono/cloudflare"; @@ -99,12 +98,11 @@ app.use( sentry(app, { dsn: "___PUBLIC_DSN___", tracesSampleRate: 1.0, - traceLifecycle: "stream", }) ); ``` -This changes how spans are delivered; it doesn't replace `wrapMcpServerWithSentry`. Stream mode requires `@sentry/hono` and `@sentry/cloudflare` version `10.49.0` or newer. See Streamed Spans for configuration and filtering differences. +You still need `wrapMcpServerWithSentry` to instrument MCP operations. See Streamed Spans for configuration and filtering differences. diff --git a/docs/platforms/javascript/common/tracing/streamed-spans/index.mdx b/docs/platforms/javascript/common/tracing/streamed-spans/index.mdx index 7dfa22672121e..48e888d4066ba 100644 --- a/docs/platforms/javascript/common/tracing/streamed-spans/index.mdx +++ b/docs/platforms/javascript/common/tracing/streamed-spans/index.mdx @@ -1,6 +1,6 @@ --- title: Streamed Spans -description: "Learn how to use stream mode to send spans to Sentry as they finish, removing the 1,000-span limit and making trace data visible sooner." +description: "Learn how the SDK sends spans in batches as they finish, and how to configure span attributes, filtering, and delivery." sidebar_order: 35 new: true notSupported: @@ -8,22 +8,21 @@ notSupported: - javascript.electron --- -By default, the Sentry JavaScript SDKs collect all spans in memory and send them to Sentry as a single transaction once the root span ends. This is called transaction mode. -Stream mode changes this by sending spans to Sentry in batches as they finish. Service spans, which represent a service's entry point, replace transactions as the main grouping for each service. +The Sentry JavaScript SDKs send spans in batches as they finish. This is called stream mode and is the default trace lifecycle. Service spans represent a service's entry point and group its child spans. -- **No 1,000-span limit.** In transaction mode, transactions are capped at 1,000 spans. Stream mode has no upper limit since spans are sent in batches. +- **No 1,000-span limit.** Spans are sent in batches, so a trace can contain more than 1,000 spans. - **Lower memory usage.** Spans are flushed periodically and don't need to be held in memory until the root span ends. This is especially useful for long-running processes like queue consumers or cron jobs. - **Faster visibility.** Span data arrives in Sentry as your application runs, instead of only after the entire operation completes. -- **No data loss from crashes.** If your process terminates unexpectedly, spans that were already flushed are preserved. In transaction mode, a crash before the root span ends means all span data is lost. +- **No data loss from crashes.** If your process terminates unexpectedly, spans that were already flushed are preserved. Spans still buffered in memory can be lost. You can find the following span types mentioned throughout this page: - **Root span**: The topmost span in a trace. It has no parent span and is always a service span. -- **Service span**: A parent-level span at the entry of a service. In transaction mode, this is called a transaction. +- **Service span**: A parent-level span at the entry of a service, identified by `is_segment` in its serialized data. - **Child span**: Any span nested under a parent span within the same trace. This graph shows how these span types relate to each other within a trace: @@ -39,49 +38,11 @@ Trace └── Child span ``` -Span stream mode will be enabled by default in version `11.0.0` of the SDK. -You can already opt into stream mode in version 10 by following the migration guide below. +## Configuration -## Prerequisites +Configure tracing in your app. The SDK uses `traceLifecycle: 'stream'` by default, with no additional integration required. -You need: - -- Tracing configured in - your app -- SDK version `>=10.66.0` - -## Migrate from Transaction Mode - -For most users, switching to stream mode requires no code changes beyond the initial opt-in. -If you use `beforeSendSpan` or `beforeSendTransaction`, follow these steps: - -1. [Enable stream mode](#enable-stream-mode) -2. [Wrap `beforeSendSpan` with `Sentry.withStreamedSpan()` to filter spans](#filter-spans) -3. [Replace `beforeSendTransaction` with `ignoreSpans` to drop spans](#drop-spans) -4. [Migrate tags (`Sentry.setTag(s)`) to attributes (`Sentry.setAttribute(s)`)](#shared-attributes) -5. [Verify the migration](#verify-your-setup) - -### Agent-Assisted Migration - -Copy the following prompt and paste it into your AI agent: - -```txt -Follow ___CURRENT_URL___ to enable and migrate to span streaming in the Sentry SDK. -``` - -## Enable Stream Mode - - - - - - - -Tracing modes are scoped per SDK, which means you can use, for example, stream mode in your frontend, and transaction mode in your backend, or vice versa. - - - - +To opt out of span streaming, set `traceLifecycle: 'static'`. With this setting, wrap `beforeSendSpan` with `Sentry.withStaticSpan()` to receive and return `SpanJSON`. Static mode also supports transaction filtering with `beforeSendTransaction` and `ignoreTransactions`. @@ -99,6 +60,8 @@ Each flush sends only the spans accumulated since the last flush, grouped into e ## Manual Instrumentation (Optional) +Create spans to measure operations that the SDK does not instrument automatically. + ### Start a Span @@ -212,18 +175,14 @@ Find more examples in our Sending Span ### Shared Attributes -Previously, transaction mode applied shared tags (`Sentry.setTag(s)`) to the service span (transaction). -In Stream mode, tags are no longer applied to spans. -Set shared attributes on a specific scope instead. -You don't need to remove tags from your code, since they still apply to errors. -Instead, add attributes for all data that's relevant for spans, logs metrics. +Shared attributes attach the same metadata to spans, logs, and metrics. Scope tags apply to errors and are not included in streamed spans. Use `Sentry.setAttribute` and `Sentry.setAttributes` to attach attributes that are automatically included in all spans (as well as your logs and metrics). -These work just like `Sentry.setTag` and `Sentry.setTags`, but they accept `string`, `number`, and `boolean` values. +They accept `string`, `number`, and `boolean` values. To attach attributes to a broader or narrower context, set them on a specific scope instead. Use the global scope for app-wide attributes and the current scope for a single operation. @@ -259,100 +218,61 @@ Sentry.withScope((scope) => { ## Breadcrumbs -In stream mode, breadcrumbs are no longer sent with spans. -They remain attached to errors, so you don't need to change how you record them. +Breadcrumbs are attached to errors. Streamed spans do not include breadcrumbs. ## Extended Configuration (Optional) +Modify span data before sending it or filter out spans you do not need. + ### Filter Spans -To modify or redact span data before it's sent, use `beforeSendSpan`. In stream mode, wrap it with `Sentry.withStreamedSpan()` so the SDK applies it to spans as they are flushed rather than only at transaction time. +To modify or redact span data before it's sent, use `beforeSendSpan` directly. The callback runs for each finished span and receives `StreamedSpanJSON`. + +Check `span.is_segment` to target only service spans. `Sentry.spanToJSON()` returns the same shape. - `beforeSendSpan` can only modify span data, and you cannot use it to drop + `beforeSendSpan` can only modify span data. It cannot return `null` to drop spans. Use [`ignoreSpans`](#drop-spans) instead. -The `span` object also has different property names in stream mode. For example, `span.op` becomes `span.attributes?.["sentry.op"]` and `span.description` becomes `span.name`. See the migration note below for the full list. - - - -```JavaScript -Sentry.init({ - dsn: "___PUBLIC_DSN___", - tracesSampleRate: 1.0, - traceLifecycle: "stream", - beforeSendSpan: Sentry.withStreamedSpan((span) => { - // In stream mode, 'op' is accessed via attributes - if (span.attributes?.["sentry.op"] === "db.query") { - // In stream mode, 'description' is now renamed to 'name' - span.name = "[filtered]"; - } - return span; - }), -}); -``` - - - - - - - ```javascript Sentry.init({ dsn: "___PUBLIC_DSN___", tracesSampleRate: 1.0, - integrations: [ - // other integrations - Sentry.spanStreamingIntegration(), - ], - beforeSendSpan: Sentry.withStreamedSpan((span) => { - // In stream mode, 'op' is accessed via attributes - if (span.attributes?.["sentry.op"] === "db.query") { - // In stream mode, 'description' is now renamed to 'name' + beforeSendSpan(span) { + if (span.attributes["sentry.op"] === "db.query") { span.name = "[filtered]"; } + if (span.is_segment) { + span.attributes["service.version"] = "1.0.0"; + } return span; - }), + }, }); ``` - - - - - -If you're using `beforeSendSpan`, wrap it with `Sentry.withStreamedSpan()` as shown above, otherwise the SDK falls back to transaction mode. - -Note that the `span` object is `StreamedSpanJSON` instead of `SpanJSON` and has different property names: - -| Transaction Mode (`SpanJSON`) | Stream Mode (`StreamedSpanJSON`) | -| ---------------------------------- | ----------------------------------- | -| `span.description` | `span.name` | -| `span.data` (processed attributes) | `span.attributes` (raw attributes) | -| `span.timestamp` (end time) | `span.end_timestamp` | -| `span.status` (optional string) | `span.status` (`'ok'` or `'error'`) | -| `span.op` | `span.attributes['sentry.op']` | - -If you're using `beforeSendTransaction` to drop spans, use [`ignoreSpans`](#drop-spans) instead, since `beforeSendTransaction` is not available in stream mode. +### Drop Spans - +Use the object form of `ignoreSpans` to match a service span's name and operation without dropping unrelated child spans with the same name: -### Drop Spans +```javascript +Sentry.init({ + ignoreSpans: [{ name: "GET /health", op: "http.server" }], +}); +``` -In stream mode, `ignoreSpans` is evaluated at span start, so only the span name and attributes available at that point are taken into account. Any name updates or additional attributes added while the span is active won't influence whether the span is dropped. +Use the operation of your service span, such as `http.server`, `pageload`, or `navigation`. `ignoreSpans` is evaluated at span start, so only names and attributes available at that point affect matching. Later updates do not affect whether a span is dropped. @@ -363,13 +283,10 @@ To prevent specific spans from being created, use the - ```javascript Sentry.init({ dsn: "___PUBLIC_DSN___", tracesSampleRate: 1.0, - traceLifecycle: "stream", ignoreSpans: [ // Drop spans whose name contains "healthcheck" "healthcheck", @@ -386,53 +303,13 @@ Sentry.init({ }); ``` - - - - - - -```javascript -Sentry.init({ - dsn: "___PUBLIC_DSN___", - tracesSampleRate: 1.0, - integrations: [ - // other integrations - Sentry.spanStreamingIntegration(), - ], - ignoreSpans: [ - // Drop spans whose name contains "healthcheck" - "healthcheck", - // Drop spans whose name matches a pattern - /^GET \/api\/v1\/internal/, - // Drop spans matching name and attribute conditions - { - name: /^GET \//, - attributes: { - "http.route": "/api/status", - }, - }, - ], -}); -``` - - - - - If a matching span is a service span, all of its child spans are dropped as well. If a child span matches, only that span is dropped and its children are reparented to the nearest ancestor. - - -In transaction mode, `ignoreSpans` is evaluated at transaction end rather than at span start. Review your existing rules to make sure the attributes and names you're matching on are passed when the span is created. - -If you're auto-instrumenting and don't know what the initial name of a span is when it starts, enable SDK debug logging during development by setting `debug: true` when initializing the SDK. - - +To inspect the initial names of automatically created spans, enable SDK debug logging during development with `debug: true`. ## Distributed Tracing (Optional) @@ -441,23 +318,10 @@ when the SDK can't instrument automatically, see - - - -- **Check the Sentry dashboard**: Spans should appear in the Traces view shortly after they complete. Traces look the same as in transaction mode, but without transactions. -- **Check for fallback warnings in your logs**: If the SDK logs warnings about falling back to transaction mode, your `beforeSendSpan` callback is likely missing the `Sentry.withStreamedSpan()` wrapper. - - - - +Check the Traces view in Sentry for spans shortly after they finish. Enable `debug: true` to see SDK warnings, including callbacks that do not match the configured trace lifecycle. -- **Check the Sentry dashboard**: Spans should appear in the Traces view shortly after they complete. Traces look similar to transaction mode, but contain only spans and no transactions. -- **Check for fallback warnings in your logs**: If the SDK logs warnings about falling back to transaction mode, your `beforeSendSpan` callback is likely missing the `Sentry.withStreamedSpan()` wrapper. -- **Check the network tab in your browser's DevTools**: Span envelopes should appear as individual requests with content type `application/vnd.sentry.items.span.v2+json` +In your browser's DevTools network tab, look for span envelopes with content type `application/vnd.sentry.items.span.v2+json`. diff --git a/docs/platforms/javascript/common/tracing/troubleshooting/index.mdx b/docs/platforms/javascript/common/tracing/troubleshooting/index.mdx index 0024a04c5810c..bda632c5aba4c 100644 --- a/docs/platforms/javascript/common/tracing/troubleshooting/index.mdx +++ b/docs/platforms/javascript/common/tracing/troubleshooting/index.mdx @@ -9,11 +9,20 @@ If you need help managing transactions or spans, start with this page. If you ne ## Group Transactions -When Sentry captures transactions, they are assigned a transaction name. This name is generally auto-generated by the Sentry SDK based on the framework integrations you are using. If you can't leverage the automatic transaction generation (or want to customize how transaction names are generated) you can use a global event processor that is registered when you initialize the SDK with your configuration. +The SDK groups spans by service span. Integrations usually name these spans automatically. To change a service span's name before it is sent, use `beforeSendSpan` and check `is_segment`: -For example: +```javascript +Sentry.init({ + beforeSendSpan(span) { + if (span.is_segment && span.attributes["http.route"] === "/users/:id") { + span.name = "GET /users/:id"; + } + return span; + }, +}); +``` - +Event processors do not apply to streamed spans. In static mode, use `beforeSendTransaction` to change `event.transaction`. See Transaction Name for other ways to set names. ## Control Data Truncation @@ -32,16 +41,16 @@ For example, a 200+ character tag like this: ## Traces Miss Spans, High Memory Usage, or Data Loss After Crashes -If you're hitting the 1,000-span limit, experiencing high memory usage from long-running processes, or losing span data when your process crashes, consider enabling stream mode. Stream mode sends spans to Sentry in batches as they finish rather than holding them in memory until the transaction ends. +With `traceLifecycle: 'static'`, the SDK holds spans in memory until the root span ends. This can cause high memory usage, hit the 1,000-span limit, or lose spans if the process crashes. Use the default `traceLifecycle: 'stream'` to send spans in batches as they finish. In stream mode, pass `beforeSendSpan` directly without a `withStaticSpan` wrapper. See Streamed Spans for more information. -## `ignoreSpans` Rules No Longer Work As Expected After Migrating to Stream Mode +## `ignoreSpans` Rules Do Not Match Spans -In stream mode, `ignoreSpans` is evaluated at span start rather than at transaction end as in transaction mode. This means rules that match on names and attributes added or updated while a span is active may no longer match the intended spans. Review your `ignoreSpans` rules after migrating to make sure the names and attributes you're matching on are available when the span is created. +The SDK evaluates `ignoreSpans` when a span starts. Names and attributes added or updated later do not affect matching. Make sure your rules match values available when the span is created. If you're auto-instrumenting and don't know what the initial name of a span is when it starts, enable SDK debug logging during development by setting `debug: true` when initializing the SDK. -Finally, make sure you've migrated any entries from `ignoreTransactions` to `ignoreSpans`, as `ignoreTransactions` is not applied in stream mode. +Use the object form of `ignoreSpans` to match both name and operation when you need to distinguish service spans from child spans with the same name. diff --git a/platform-includes/configuration/before-send-span/javascript.mdx b/platform-includes/configuration/before-send-span/javascript.mdx index 13b5f9623a3f7..82f419a6133b9 100644 --- a/platform-includes/configuration/before-send-span/javascript.mdx +++ b/platform-includes/configuration/before-send-span/javascript.mdx @@ -1,11 +1,11 @@ -```javascript {tabTitle:Transaction Mode (Default)} +```javascript {tabTitle:Stream Mode (Default)} {mdExpandTabs} Sentry.init({ dsn: "___PUBLIC_DSN___", beforeSendSpan(span) { - if (span.description === "should be renamed") { - span.description = "renamed span"; - span.data = { - ...span.data, + if (span.name === "should be renamed") { + span.name = "renamed span"; + span.attributes = { + ...span.attributes, myExtraAttribute: true, }; } @@ -15,14 +15,15 @@ Sentry.init({ }); ``` -```javascript {tabTitle:Stream Mode} +```javascript {tabTitle:Static Mode} Sentry.init({ dsn: "___PUBLIC_DSN___", - beforeSendSpan: Sentry.withStreamedSpan((span) => { - if (span.name === "should be renamed") { - span.name = "renamed span"; - span.attributes = { - ...span.attributes, + traceLifecycle: "static", + beforeSendSpan: Sentry.withStaticSpan((span) => { + if (span.description === "should be renamed") { + span.description = "renamed span"; + span.data = { + ...span.data, myExtraAttribute: true, }; } diff --git a/platform-includes/configuration/before-send-transaction/javascript.mdx b/platform-includes/configuration/before-send-transaction/javascript.mdx index c1d1a05093a2c..d49e4d6eab7de 100644 --- a/platform-includes/configuration/before-send-transaction/javascript.mdx +++ b/platform-includes/configuration/before-send-transaction/javascript.mdx @@ -1,9 +1,9 @@ ```javascript Sentry.init({ dsn: "___PUBLIC_DSN___", + traceLifecycle: "static", beforeSendTransaction(event) { if (event.transaction === "/unimportant/route") { - // Don't send the event to Sentry return null; } return event; diff --git a/platform-includes/configuration/ignore-transactions/javascript.mdx b/platform-includes/configuration/ignore-transactions/javascript.mdx index 1aa8541e84719..d1728e2f5bc5a 100644 --- a/platform-includes/configuration/ignore-transactions/javascript.mdx +++ b/platform-includes/configuration/ignore-transactions/javascript.mdx @@ -1,6 +1,7 @@ ```javascript Sentry.init({ dsn: "___PUBLIC_DSN___", + traceLifecycle: "static", ignoreTransactions: ["partial/match", /^Exact Transaction Name$/], }); ```