From a5c479ea51e17cab702cfbf8526ba382580252e7 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Fri, 10 Apr 2026 14:18:04 +0900 Subject: [PATCH 1/5] feat(core): Add `enableTruncation` option to LangGraph integration This PR adds an `enableTruncation` option to the LangGraph integration that allows users to disable input message truncation. It defaults to `true` to preserve existing behavior. Also refactors to use the shared getTruncatedJsonString/getJsonString utilities. Closes: #20139 --- .../langgraph/instrument-no-truncation.mjs | 15 +++++++ .../langgraph/scenario-no-truncation.mjs | 42 +++++++++++++++++++ .../suites/tracing/langgraph/test.ts | 28 +++++++++++++ packages/core/src/tracing/langgraph/index.ts | 14 +++++-- packages/core/src/tracing/langgraph/types.ts | 5 +++ 5 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 dev-packages/node-integration-tests/suites/tracing/langgraph/instrument-no-truncation.mjs create mode 100644 dev-packages/node-integration-tests/suites/tracing/langgraph/scenario-no-truncation.mjs diff --git a/dev-packages/node-integration-tests/suites/tracing/langgraph/instrument-no-truncation.mjs b/dev-packages/node-integration-tests/suites/tracing/langgraph/instrument-no-truncation.mjs new file mode 100644 index 000000000000..4b1d5eb0dc25 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/langgraph/instrument-no-truncation.mjs @@ -0,0 +1,15 @@ +import * as Sentry from '@sentry/node'; +import { loggingTransport } from '@sentry-internal/node-integration-tests'; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + sendDefaultPii: true, + transport: loggingTransport, + integrations: [ + Sentry.langGraphIntegration({ + enableTruncation: false, + }), + ], +}); diff --git a/dev-packages/node-integration-tests/suites/tracing/langgraph/scenario-no-truncation.mjs b/dev-packages/node-integration-tests/suites/tracing/langgraph/scenario-no-truncation.mjs new file mode 100644 index 000000000000..b9ccb8087a93 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/langgraph/scenario-no-truncation.mjs @@ -0,0 +1,42 @@ +import { END, MessagesAnnotation, START, StateGraph } from '@langchain/langgraph'; +import * as Sentry from '@sentry/node'; + +async function run() { + await Sentry.startSpan({ op: 'function', name: 'langgraph-test' }, async () => { + const mockLlm = () => { + return { + messages: [ + { + role: 'assistant', + content: 'Mock LLM response', + response_metadata: { + model_name: 'mock-model', + finish_reason: 'stop', + tokenUsage: { + promptTokens: 20, + completionTokens: 10, + totalTokens: 30, + }, + }, + }, + ], + }; + }; + + const graph = new StateGraph(MessagesAnnotation) + .addNode('agent', mockLlm) + .addEdge(START, 'agent') + .addEdge('agent', END) + .compile({ name: 'weather_assistant' }); + + // Long content that would normally be truncated + const longContent = 'A'.repeat(50_000); + await graph.invoke({ + messages: [{ role: 'user', content: longContent }], + }); + }); + + await Sentry.flush(2000); +} + +run(); diff --git a/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts b/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts index 0b03e59bbfbf..70f10f1e84be 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts @@ -364,4 +364,32 @@ describe('LangGraph integration', () => { await createRunner().ignore('event').expect({ transaction: EXPECTED_TRANSACTION_RESUME }).start().completed(); }); }); + + const longContent = 'A'.repeat(50_000); + + const EXPECTED_TRANSACTION_NO_TRUNCATION = { + transaction: 'langgraph-test', + spans: expect.arrayContaining([ + expect.objectContaining({ + data: expect.objectContaining({ + [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: expect.stringContaining(longContent), + }), + }), + ]), + }; + + createEsmAndCjsTests( + __dirname, + 'scenario-no-truncation.mjs', + 'instrument-no-truncation.mjs', + (createRunner, test) => { + test('does not truncate input messages when enableTruncation is false', async () => { + await createRunner() + .ignore('event') + .expect({ transaction: EXPECTED_TRANSACTION_NO_TRUNCATION }) + .start() + .completed(); + }); + }, + ); }); diff --git a/packages/core/src/tracing/langgraph/index.ts b/packages/core/src/tracing/langgraph/index.ts index c010520d10cc..5230b43bb54d 100644 --- a/packages/core/src/tracing/langgraph/index.ts +++ b/packages/core/src/tracing/langgraph/index.ts @@ -12,8 +12,12 @@ import { GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, } from '../ai/gen-ai-attributes'; -import { truncateGenAiMessages } from '../ai/messageTruncation'; -import { extractSystemInstructions, resolveAIRecordingOptions } from '../ai/utils'; +import { + extractSystemInstructions, + getJsonString, + getTruncatedJsonString, + resolveAIRecordingOptions, +} from '../ai/utils'; import type { LangChainMessage } from '../langchain/types'; import { normalizeLangChainMessages } from '../langchain/utils'; import { startSpan } from '../trace'; @@ -146,10 +150,12 @@ function instrumentCompiledGraphInvoke( span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions); } - const truncatedMessages = truncateGenAiMessages(filteredMessages as unknown[]); + const enableTruncation = options.enableTruncation ?? true; const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0; span.setAttributes({ - [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: JSON.stringify(truncatedMessages), + [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: enableTruncation + ? getTruncatedJsonString(filteredMessages) + : getJsonString(filteredMessages), [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength, }); } diff --git a/packages/core/src/tracing/langgraph/types.ts b/packages/core/src/tracing/langgraph/types.ts index b16f9718c69e..021099f369b1 100644 --- a/packages/core/src/tracing/langgraph/types.ts +++ b/packages/core/src/tracing/langgraph/types.ts @@ -7,6 +7,11 @@ export interface LangGraphOptions { * Enable or disable output recording. */ recordOutputs?: boolean; + /** + * Enable or disable truncation of recorded input messages. + * Defaults to `true`. + */ + enableTruncation?: boolean; } /** From 632fe0eeab2d0422e53d0482a1b289b1b1de9a45 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Fri, 10 Apr 2026 14:37:46 +0900 Subject: [PATCH 2/5] Bump size limit --- .size-limit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.size-limit.js b/.size-limit.js index 1e6e8d951464..4100751f2c40 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -276,7 +276,7 @@ module.exports = [ path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '250 KB', + limit: '251 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed', From d8673e3f46c1790cf782d209ae4d5151414ee489 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Fri, 10 Apr 2026 11:57:23 +0200 Subject: [PATCH 3/5] Revert "Bump size limit" This reverts commit 632fe0eeab2d0422e53d0482a1b289b1b1de9a45. --- .size-limit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.size-limit.js b/.size-limit.js index 4100751f2c40..1e6e8d951464 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -276,7 +276,7 @@ module.exports = [ path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '251 KB', + limit: '250 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed', From 2a810c42d1c04e79ad6555186f180252e0d09de9 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Fri, 10 Apr 2026 11:58:33 +0200 Subject: [PATCH 4/5] multi-message scenario test --- .../suites/tracing/langgraph/instrument-no-truncation.mjs | 2 ++ .../suites/tracing/langgraph/scenario-no-truncation.mjs | 8 ++++++-- .../suites/tracing/langgraph/test.ts | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/dev-packages/node-integration-tests/suites/tracing/langgraph/instrument-no-truncation.mjs b/dev-packages/node-integration-tests/suites/tracing/langgraph/instrument-no-truncation.mjs index 4b1d5eb0dc25..91b4e4b1bae5 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langgraph/instrument-no-truncation.mjs +++ b/dev-packages/node-integration-tests/suites/tracing/langgraph/instrument-no-truncation.mjs @@ -9,6 +9,8 @@ Sentry.init({ transport: loggingTransport, integrations: [ Sentry.langGraphIntegration({ + recordInputs: true, + recordOutputs: true, enableTruncation: false, }), ], diff --git a/dev-packages/node-integration-tests/suites/tracing/langgraph/scenario-no-truncation.mjs b/dev-packages/node-integration-tests/suites/tracing/langgraph/scenario-no-truncation.mjs index b9ccb8087a93..982e7a69de53 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langgraph/scenario-no-truncation.mjs +++ b/dev-packages/node-integration-tests/suites/tracing/langgraph/scenario-no-truncation.mjs @@ -29,10 +29,14 @@ async function run() { .addEdge('agent', END) .compile({ name: 'weather_assistant' }); - // Long content that would normally be truncated + // Multiple messages with long content (would normally be truncated and popped to last message only) const longContent = 'A'.repeat(50_000); await graph.invoke({ - messages: [{ role: 'user', content: longContent }], + messages: [ + { role: 'user', content: longContent }, + { role: 'assistant', content: 'Some reply' }, + { role: 'user', content: 'Follow-up question' }, + ], }); }); diff --git a/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts b/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts index 70f10f1e84be..32b873bb5dd7 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts @@ -4,6 +4,7 @@ import { GEN_AI_AGENT_NAME_ATTRIBUTE, GEN_AI_CONVERSATION_ID_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, + GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_PIPELINE_NAME_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, @@ -373,6 +374,7 @@ describe('LangGraph integration', () => { expect.objectContaining({ data: expect.objectContaining({ [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: expect.stringContaining(longContent), + [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: 3, }), }), ]), From 5fa2f5c8b8cb45a47f0aaab3d9b3b0f47c21e97d Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Fri, 10 Apr 2026 12:05:31 +0200 Subject: [PATCH 5/5] exact match --- .../node-integration-tests/suites/tracing/langgraph/test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts b/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts index 32b873bb5dd7..329cb914851a 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts @@ -373,7 +373,11 @@ describe('LangGraph integration', () => { spans: expect.arrayContaining([ expect.objectContaining({ data: expect.objectContaining({ - [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: expect.stringContaining(longContent), + [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: JSON.stringify([ + { role: 'user', content: longContent }, + { role: 'assistant', content: 'Some reply' }, + { role: 'user', content: 'Follow-up question' }, + ]), [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: 3, }), }),