Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott

### Important Changes

- **feat(core): Enable `streamGenAiSpans` by default ([#21732](https://github.com/getsentry/sentry-javascript/pull/21732))**

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we even call this out? or maybe shorten this to basically only call out the bit about truncation? because that's the only actionable part for users

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's also actionable to know what this does so they can make a decision to turn it off instead of having to go find what this flag even is.


The SDK now extracts all `gen_ai` spans out of a transaction and sends them as v2 envelope items by default. This prevents gen_ai spans from being dropped when the transaction payload exceeds size limits. Because they are no longer constrained by transaction size limits, AI message data is also no longer truncated by default. Set `enableTruncation: true` on the respective AI integration to re-enable truncation. To keep the previous behavior, set `streamGenAiSpans: false`.

Self-hosted Sentry users should opt out with `streamGenAiSpans: false`, since streamed gen_ai spans may not be ingested by their Sentry instance.

## 10.60.0

### Other Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Sentry.init({
release: '1.0',
tracesSampleRate: 1.0,
dataCollection: { genAI: { inputs: true, outputs: true } },
// This suite asserts on gen_ai spans embedded in the transaction, so opt out of span streaming.
streamGenAiSpans: false,
transport: loggingTransport,
beforeSendTransaction: event => {
// Filter out mock express server transactions
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/tracing/ai/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export function resolveAIRecordingOptions<T extends AIRecordingOptions>(options?
* Otherwise, truncation is disabled whenever gen_ai spans are sent through the span streaming / v2
* span path, i.e. full span streaming (`traceLifecycle: 'stream'`) or `streamGenAiSpans`. That path
* is not subject to the transaction payload-size limits that truncation works around, so the full
* message data can be retained.
* message data can be retained. `streamGenAiSpans` is opt-out (on unless explicitly set to `false`).
*/
export function shouldEnableTruncation(enableTruncation: boolean | undefined): boolean {
if (enableTruncation !== undefined) {
Expand All @@ -75,7 +75,7 @@ export function shouldEnableTruncation(enableTruncation: boolean | undefined): b
return true;
}

return !hasSpanStreamingEnabled(client) && !client.getOptions().streamGenAiSpans;
return !hasSpanStreamingEnabled(client) && client.getOptions().streamGenAiSpans === false;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/tracing/spans/extractGenAiSpans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function extractGenAiSpansFromEvent(event: Event, client: Client): SpanCo
event.type !== 'transaction' ||
!event.spans?.length ||
!event.sdkProcessingMetadata?.hasGenAiSpans ||
!client.getOptions().streamGenAiSpans ||
client.getOptions().streamGenAiSpans === false ||
hasSpanStreamingEnabled(client)
) {
return undefined;
Expand Down
10 changes: 5 additions & 5 deletions packages/core/src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,16 +565,16 @@ export interface ClientOptions<TO extends BaseTransportOptions = BaseTransportOp
orgId?: `${number}` | number;

/**
* If set to `true`, gen_ai spans will be extracted from transactions and sent as v2 span envelope items.
* Unless set to `false`, gen_ai spans will be extracted from transactions and sent as v2 span envelope items.
*
* This enables streaming gen_ai spans, avoiding payload size limits of usual transactions.
*
* Because the v2 span format is not subject to the transaction payload-size limits that gen_ai message
* truncation exists to work around, enabling this option also disables gen_ai input truncation (and the
* inline-media redaction that rides along with it) by default. Set `enableTruncation: true` on the
* respective AI integration to opt back into truncation.
* truncation exists to work around, this also disables gen_ai input truncation by default. Set
* `enableTruncation: true` on the respective AI integration to opt back into truncation, or set this
* option to `false` to send gen_ai spans as part of the transaction (which re-enables truncation by default).
*
* @default false
* @default true
*/
streamGenAiSpans?: boolean;

Expand Down
8 changes: 7 additions & 1 deletion packages/core/test/lib/tracing/ai/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ describe('shouldEnableTruncation', () => {
getCurrentScope().clear();
getIsolationScope().clear();
getGlobalScope().clear();
getCurrentScope().setClient(undefined);
});

afterEach(() => {
Expand All @@ -110,8 +111,13 @@ describe('shouldEnableTruncation', () => {
expect(shouldEnableTruncation(undefined)).toBe(true);
});

it('defaults to true with a default client (no streaming)', () => {
it('defaults to false with a default client (streamGenAiSpans is opt-out)', () => {
setupClient();
expect(shouldEnableTruncation(undefined)).toBe(false);
});

it('defaults to true when streamGenAiSpans is explicitly disabled', () => {
setupClient({ streamGenAiSpans: false });
expect(shouldEnableTruncation(undefined)).toBe(true);
});

Expand Down
13 changes: 11 additions & 2 deletions packages/core/test/lib/tracing/spans/extractGenAiSpans.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ function makeClient(options: Partial<Parameters<typeof getDefaultTestClientOptio
return new TestClient(
getDefaultTestClientOptions({
dsn: 'https://dsn@ingest.f00.f00/1',
streamGenAiSpans: true,
...options,
}),
);
Expand Down Expand Up @@ -121,7 +120,17 @@ describe('extractGenAiSpansFromEvent', () => {
expect(extractGenAiSpansFromEvent(event, makeClient())).toBeUndefined();
});

it('returns undefined when streamGenAiSpans is not enabled', () => {
it('extracts gen_ai spans by default when streamGenAiSpans is unset', () => {
const event = makeTransactionEvent([makeSpanJSON({ op: 'gen_ai.chat', span_id: 'genai001' })], true);

const result = extractGenAiSpansFromEvent(event, makeClient());

expect(result).toBeDefined();
expect(result![0].item_count).toBe(1);
expect(event.spans).toHaveLength(0);
});

it('returns undefined when streamGenAiSpans is explicitly disabled', () => {
const event = makeTransactionEvent([makeSpanJSON({ op: 'gen_ai.chat' })]);
const client = makeClient({ streamGenAiSpans: false });

Expand Down
Loading