From 43585d949db219bf77b35715290f2fa4e620966b Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 29 Jul 2026 15:35:26 +0200 Subject: [PATCH] ref(core): Use `stringify` helper for AI span attribute serialization Replace the manual `typeof x === 'string' ? x : JSON.stringify(x)` pattern with the `stringify` helper from `@sentry/core` across the AI integrations. The helper wraps `JSON.stringify` in a try/catch, so non-serializable values (circular references, `BigInt`) fall back to `'[unserializable]'` instead of throwing and dropping the span attributes. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/core/src/tracing/google-genai/index.ts | 2 +- packages/core/src/tracing/langchain/embeddings.ts | 3 ++- packages/core/src/tracing/langchain/index.ts | 3 ++- packages/core/src/tracing/openai/index.ts | 3 +-- packages/core/src/tracing/workers-ai/utils.ts | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/core/src/tracing/google-genai/index.ts b/packages/core/src/tracing/google-genai/index.ts index 578bf1719e75..a05e1ae2d023 100644 --- a/packages/core/src/tracing/google-genai/index.ts +++ b/packages/core/src/tracing/google-genai/index.ts @@ -149,7 +149,7 @@ export function addPrivateRequestAttributes( if (operationName === 'embeddings') { const contents = params.contents; if (contents != null) { - span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, typeof contents === 'string' ? contents : JSON.stringify(contents)); + span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, stringify(contents, String)); } return; } diff --git a/packages/core/src/tracing/langchain/embeddings.ts b/packages/core/src/tracing/langchain/embeddings.ts index fe6fac2c7a9a..796d0785a3da 100644 --- a/packages/core/src/tracing/langchain/embeddings.ts +++ b/packages/core/src/tracing/langchain/embeddings.ts @@ -14,6 +14,7 @@ import { GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE, } from '../ai/gen-ai-attributes'; import { resolveAIRecordingOptions } from '../ai/utils'; +import { stringify } from '../../utils/string'; import { LANGCHAIN_ORIGIN } from './constants'; import type { LangChainOptions } from './types'; @@ -73,7 +74,7 @@ export function _INTERNAL_getLangChainEmbeddingsSpanOptions( const modelName = attributes[GEN_AI_REQUEST_MODEL] || 'unknown'; if (recordInputs && input != null) { - attributes[GEN_AI_EMBEDDINGS_INPUT] = typeof input === 'string' ? input : JSON.stringify(input); + attributes[GEN_AI_EMBEDDINGS_INPUT] = stringify(input, String); } return { diff --git a/packages/core/src/tracing/langchain/index.ts b/packages/core/src/tracing/langchain/index.ts index 769c471e0ea3..ea58cc94faee 100644 --- a/packages/core/src/tracing/langchain/index.ts +++ b/packages/core/src/tracing/langchain/index.ts @@ -4,6 +4,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from ' import { SPAN_STATUS_ERROR } from '../../tracing'; import { startSpanManual } from '../../tracing/trace'; import type { Span, SpanAttributeValue } from '../../types/span'; +import { stringify } from '../../utils/string'; import { GEN_AI_OPERATION_NAME, GEN_AI_REQUEST_MODEL, @@ -327,7 +328,7 @@ export function createLangChainCallbackHandler(options: LangChainOptions = {}): const content = outputObj && typeof outputObj === 'object' && 'content' in outputObj ? outputObj.content : output; span.setAttributes({ - [GEN_AI_TOOL_CALL_RESULT]: typeof content === 'string' ? content : JSON.stringify(content), + [GEN_AI_TOOL_CALL_RESULT]: stringify(content, String), }); } exitSpan(runId); diff --git a/packages/core/src/tracing/openai/index.ts b/packages/core/src/tracing/openai/index.ts index f15854b9c178..db86d62cceff 100644 --- a/packages/core/src/tracing/openai/index.ts +++ b/packages/core/src/tracing/openai/index.ts @@ -105,8 +105,7 @@ export function addRequestAttributes( return; } - // Store strings as-is, arrays/objects as JSON - span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, typeof input === 'string' ? input : JSON.stringify(input)); + span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, stringify(input, String)); return; } diff --git a/packages/core/src/tracing/workers-ai/utils.ts b/packages/core/src/tracing/workers-ai/utils.ts index 8caea5e6c0bc..833332848ed1 100644 --- a/packages/core/src/tracing/workers-ai/utils.ts +++ b/packages/core/src/tracing/workers-ai/utils.ts @@ -107,7 +107,7 @@ export function addRequestAttributes( return; } - span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, typeof text === 'string' ? text : JSON.stringify(text)); + span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, stringify(text, String)); return; } @@ -168,7 +168,7 @@ export function setOutputMessagesAttribute( type: 'tool_call', id: call.id, name, - arguments: typeof args === 'string' ? args : JSON.stringify(args ?? {}), + arguments: stringify(args ?? {}, String), }); } }