Skip to content

Commit 2b3cfae

Browse files
authored
feat(core): Automatically disable truncation when span streaming is enabled in OpenAI integration (#20227)
When span streaming is enabled, the `enableTruncation` option now defaults to `false` unless the user has explicitly set it. Closes: #20221
1 parent 2af59be commit 2b3cfae

File tree

6 files changed

+97
-2
lines changed

6 files changed

+97
-2
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as Sentry from '@sentry/node';
2+
import { loggingTransport } from '@sentry-internal/node-integration-tests';
3+
4+
Sentry.init({
5+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
6+
release: '1.0',
7+
tracesSampleRate: 1.0,
8+
sendDefaultPii: true,
9+
transport: loggingTransport,
10+
traceLifecycle: 'stream',
11+
integrations: [
12+
Sentry.openAIIntegration({
13+
enableTruncation: true,
14+
}),
15+
],
16+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as Sentry from '@sentry/node';
2+
import { loggingTransport } from '@sentry-internal/node-integration-tests';
3+
4+
Sentry.init({
5+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
6+
release: '1.0',
7+
tracesSampleRate: 1.0,
8+
sendDefaultPii: true,
9+
transport: loggingTransport,
10+
traceLifecycle: 'stream',
11+
});

dev-packages/node-integration-tests/suites/tracing/openai/scenario-no-truncation.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ async function run() {
7575
});
7676
});
7777

78+
// Flush is required when span streaming is enabled to ensure streamed spans are sent before the process exits
79+
await Sentry.flush();
7880
server.close();
7981
}
8082

dev-packages/node-integration-tests/suites/tracing/openai/test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,4 +1019,58 @@ describe('OpenAI integration', () => {
10191019
.completed();
10201020
});
10211021
});
1022+
1023+
const streamingLongContent = 'A'.repeat(50_000);
1024+
const streamingLongString = 'B'.repeat(50_000);
1025+
1026+
createEsmAndCjsTests(__dirname, 'scenario-no-truncation.mjs', 'instrument-streaming.mjs', (createRunner, test) => {
1027+
test('automatically disables truncation when span streaming is enabled', async () => {
1028+
await createRunner()
1029+
.expect({
1030+
span: container => {
1031+
const spans = container.items;
1032+
1033+
const chatSpan = spans.find(s =>
1034+
s.attributes?.[GEN_AI_INPUT_MESSAGES_ATTRIBUTE]?.value?.includes(streamingLongContent),
1035+
);
1036+
expect(chatSpan).toBeDefined();
1037+
1038+
const responsesSpan = spans.find(s =>
1039+
s.attributes?.[GEN_AI_INPUT_MESSAGES_ATTRIBUTE]?.value?.includes(streamingLongString),
1040+
);
1041+
expect(responsesSpan).toBeDefined();
1042+
},
1043+
})
1044+
.start()
1045+
.completed();
1046+
});
1047+
});
1048+
1049+
createEsmAndCjsTests(
1050+
__dirname,
1051+
'scenario-no-truncation.mjs',
1052+
'instrument-streaming-with-truncation.mjs',
1053+
(createRunner, test) => {
1054+
test('respects explicit enableTruncation: true even when span streaming is enabled', async () => {
1055+
await createRunner()
1056+
.expect({
1057+
span: container => {
1058+
const spans = container.items;
1059+
1060+
// With explicit enableTruncation: true, content should be truncated despite streaming.
1061+
// Find the chat span by matching the start of the truncated content (the 'A' repeated messages).
1062+
const chatSpan = spans.find(s =>
1063+
s.attributes?.[GEN_AI_INPUT_MESSAGES_ATTRIBUTE]?.value?.startsWith('[{"role":"user","content":"AAAA'),
1064+
);
1065+
expect(chatSpan).toBeDefined();
1066+
expect(chatSpan!.attributes[GEN_AI_INPUT_MESSAGES_ATTRIBUTE].value.length).toBeLessThan(
1067+
streamingLongContent.length,
1068+
);
1069+
},
1070+
})
1071+
.start()
1072+
.completed();
1073+
});
1074+
},
1075+
);
10221076
});

packages/core/src/tracing/ai/utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44
import { captureException } from '../../exports';
55
import { getClient } from '../../currentScopes';
6+
import { hasSpanStreamingEnabled } from '../spans/hasSpanStreamingEnabled';
67
import type { Span } from '../../types-hoist/span';
78
import { isThenable } from '../../utils/is';
89
import {
@@ -56,6 +57,16 @@ export function resolveAIRecordingOptions<T extends AIRecordingOptions>(options?
5657
} as T & Required<AIRecordingOptions>;
5758
}
5859

60+
/**
61+
* Resolves whether truncation should be enabled.
62+
* If the user explicitly set `enableTruncation`, that value is used.
63+
* Otherwise, truncation is disabled when span streaming is active.
64+
*/
65+
export function shouldEnableTruncation(enableTruncation: boolean | undefined): boolean {
66+
const client = getClient();
67+
return enableTruncation ?? !(client && hasSpanStreamingEnabled(client));
68+
}
69+
5970
/**
6071
* Build method path from current traversal
6172
*/

packages/core/src/tracing/openai/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
getJsonString,
2323
getTruncatedJsonString,
2424
resolveAIRecordingOptions,
25+
shouldEnableTruncation,
2526
wrapPromiseWithMethods,
2627
} from '../ai/utils';
2728
import { OPENAI_METHOD_REGISTRY } from './constants';
@@ -170,7 +171,7 @@ function instrumentMethod<T extends unknown[], R>(
170171
originalResult = originalMethod.apply(context, args);
171172

172173
if (options.recordInputs && params) {
173-
addRequestAttributes(span, params, operationName, options.enableTruncation ?? true);
174+
addRequestAttributes(span, params, operationName, shouldEnableTruncation(options.enableTruncation));
174175
}
175176

176177
// Return async processing
@@ -208,7 +209,7 @@ function instrumentMethod<T extends unknown[], R>(
208209
originalResult = originalMethod.apply(context, args);
209210

210211
if (options.recordInputs && params) {
211-
addRequestAttributes(span, params, operationName, options.enableTruncation ?? true);
212+
addRequestAttributes(span, params, operationName, shouldEnableTruncation(options.enableTruncation));
212213
}
213214

214215
return originalResult.then(

0 commit comments

Comments
 (0)