Skip to content

Commit 43585d9

Browse files
nicohrubecclaude
andcommitted
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) <noreply@anthropic.com>
1 parent a28a549 commit 43585d9

5 files changed

Lines changed: 8 additions & 7 deletions

File tree

packages/core/src/tracing/google-genai/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ export function addPrivateRequestAttributes(
149149
if (operationName === 'embeddings') {
150150
const contents = params.contents;
151151
if (contents != null) {
152-
span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, typeof contents === 'string' ? contents : JSON.stringify(contents));
152+
span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, stringify(contents, String));
153153
}
154154
return;
155155
}

packages/core/src/tracing/langchain/embeddings.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE,
1515
} from '../ai/gen-ai-attributes';
1616
import { resolveAIRecordingOptions } from '../ai/utils';
17+
import { stringify } from '../../utils/string';
1718
import { LANGCHAIN_ORIGIN } from './constants';
1819
import type { LangChainOptions } from './types';
1920

@@ -73,7 +74,7 @@ export function _INTERNAL_getLangChainEmbeddingsSpanOptions(
7374
const modelName = attributes[GEN_AI_REQUEST_MODEL] || 'unknown';
7475

7576
if (recordInputs && input != null) {
76-
attributes[GEN_AI_EMBEDDINGS_INPUT] = typeof input === 'string' ? input : JSON.stringify(input);
77+
attributes[GEN_AI_EMBEDDINGS_INPUT] = stringify(input, String);
7778
}
7879

7980
return {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '
44
import { SPAN_STATUS_ERROR } from '../../tracing';
55
import { startSpanManual } from '../../tracing/trace';
66
import type { Span, SpanAttributeValue } from '../../types/span';
7+
import { stringify } from '../../utils/string';
78
import {
89
GEN_AI_OPERATION_NAME,
910
GEN_AI_REQUEST_MODEL,
@@ -327,7 +328,7 @@ export function createLangChainCallbackHandler(options: LangChainOptions = {}):
327328
const content =
328329
outputObj && typeof outputObj === 'object' && 'content' in outputObj ? outputObj.content : output;
329330
span.setAttributes({
330-
[GEN_AI_TOOL_CALL_RESULT]: typeof content === 'string' ? content : JSON.stringify(content),
331+
[GEN_AI_TOOL_CALL_RESULT]: stringify(content, String),
331332
});
332333
}
333334
exitSpan(runId);

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,7 @@ export function addRequestAttributes(
105105
return;
106106
}
107107

108-
// Store strings as-is, arrays/objects as JSON
109-
span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, typeof input === 'string' ? input : JSON.stringify(input));
108+
span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, stringify(input, String));
110109
return;
111110
}
112111

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export function addRequestAttributes(
107107
return;
108108
}
109109

110-
span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, typeof text === 'string' ? text : JSON.stringify(text));
110+
span.setAttribute(GEN_AI_EMBEDDINGS_INPUT, stringify(text, String));
111111
return;
112112
}
113113

@@ -168,7 +168,7 @@ export function setOutputMessagesAttribute(
168168
type: 'tool_call',
169169
id: call.id,
170170
name,
171-
arguments: typeof args === 'string' ? args : JSON.stringify(args ?? {}),
171+
arguments: stringify(args ?? {}, String),
172172
});
173173
}
174174
}

0 commit comments

Comments
 (0)