From 8d97d9574f94a062e7208e405a38a0a835fc0dfa Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 17 Jun 2025 11:47:23 -0400 Subject: [PATCH 1/2] ref(node): Add `renameAttributeKey` helper to Vercel AI integration --- .../integrations/tracing/vercelai/index.ts | 55 +++++++++---------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/packages/node/src/integrations/tracing/vercelai/index.ts b/packages/node/src/integrations/tracing/vercelai/index.ts index 5c7a0ed5d959..97025f691329 100644 --- a/packages/node/src/integrations/tracing/vercelai/index.ts +++ b/packages/node/src/integrations/tracing/vercelai/index.ts @@ -64,8 +64,8 @@ const _vercelAIIntegration = ((options: VercelAiOptions = {}) => { ) { addOriginToSpan(span, 'auto.vercelai.otel'); span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.execute_tool'); - span.setAttribute('gen_ai.tool.call.id', attributes[AI_TOOL_CALL_ID_ATTRIBUTE]); - span.setAttribute('gen_ai.tool.name', attributes[AI_TOOL_CALL_NAME_ATTRIBUTE]); + renameAttributeKey(attributes, AI_TOOL_CALL_ID_ATTRIBUTE, 'gen_ai.tool.call.id'); + renameAttributeKey(attributes, AI_TOOL_CALL_NAME_ATTRIBUTE, 'gen_ai.tool.name'); span.updateName(`execute_tool ${attributes[AI_TOOL_CALL_NAME_ATTRIBUTE]}`); return; } @@ -92,11 +92,9 @@ const _vercelAIIntegration = ((options: VercelAiOptions = {}) => { span.setAttribute('ai.pipeline.name', functionId); } - if (attributes[AI_PROMPT_ATTRIBUTE]) { - span.setAttribute('gen_ai.prompt', attributes[AI_PROMPT_ATTRIBUTE]); - } + renameAttributeKey(attributes, AI_PROMPT_ATTRIBUTE, 'gen_ai.prompt'); if (attributes[AI_MODEL_ID_ATTRIBUTE] && !attributes[GEN_AI_RESPONSE_MODEL_ATTRIBUTE]) { - span.setAttribute(GEN_AI_RESPONSE_MODEL_ATTRIBUTE, attributes[AI_MODEL_ID_ATTRIBUTE]); + renameAttributeKey(attributes, AI_MODEL_ID_ATTRIBUTE, GEN_AI_RESPONSE_MODEL_ATTRIBUTE); } span.setAttribute('ai.streaming', name.includes('stream')); @@ -182,14 +180,12 @@ const _vercelAIIntegration = ((options: VercelAiOptions = {}) => { continue; } - if (attributes[AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE] != undefined) { - attributes[GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] = attributes[AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE]; - delete attributes[AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE]; - } - if (attributes[AI_USAGE_PROMPT_TOKENS_ATTRIBUTE] != undefined) { - attributes[GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE] = attributes[AI_USAGE_PROMPT_TOKENS_ATTRIBUTE]; - delete attributes[AI_USAGE_PROMPT_TOKENS_ATTRIBUTE]; - } + renameAttributeKey( + attributes, + AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE, + GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE, + ); + renameAttributeKey(attributes, AI_USAGE_PROMPT_TOKENS_ATTRIBUTE, GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE); if ( typeof attributes[GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] === 'number' && typeof attributes[GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE] === 'number' @@ -199,22 +195,10 @@ const _vercelAIIntegration = ((options: VercelAiOptions = {}) => { } // Rename AI SDK attributes to standardized gen_ai attributes - if (attributes[AI_PROMPT_MESSAGES_ATTRIBUTE] != undefined) { - attributes['gen_ai.request.messages'] = attributes[AI_PROMPT_MESSAGES_ATTRIBUTE]; - delete attributes[AI_PROMPT_MESSAGES_ATTRIBUTE]; - } - if (attributes[AI_RESPONSE_TEXT_ATTRIBUTE] != undefined) { - attributes['gen_ai.response.text'] = attributes[AI_RESPONSE_TEXT_ATTRIBUTE]; - delete attributes[AI_RESPONSE_TEXT_ATTRIBUTE]; - } - if (attributes[AI_RESPONSE_TOOL_CALLS_ATTRIBUTE] != undefined) { - attributes['gen_ai.response.tool_calls'] = attributes[AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]; - delete attributes[AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]; - } - if (attributes[AI_PROMPT_TOOLS_ATTRIBUTE] != undefined) { - attributes['gen_ai.request.available_tools'] = attributes[AI_PROMPT_TOOLS_ATTRIBUTE]; - delete attributes[AI_PROMPT_TOOLS_ATTRIBUTE]; - } + renameAttributeKey(attributes, AI_PROMPT_MESSAGES_ATTRIBUTE, 'gen_ai.request.messages'); + renameAttributeKey(attributes, AI_RESPONSE_TEXT_ATTRIBUTE, 'gen_ai.response.text'); + renameAttributeKey(attributes, AI_RESPONSE_TOOL_CALLS_ATTRIBUTE, 'gen_ai.response.tool_calls'); + renameAttributeKey(attributes, AI_PROMPT_TOOLS_ATTRIBUTE, 'gen_ai.request.available_tools'); } } @@ -274,3 +258,14 @@ const _vercelAIIntegration = ((options: VercelAiOptions = {}) => { * }); */ export const vercelAIIntegration = defineIntegration(_vercelAIIntegration); + +/** + * Renames an attribute key in the provided attributes object if the old key exists. + * This function safely handles null and undefined values. + */ +function renameAttributeKey(attributes: Record, oldKey: string, newKey: string): void { + if (attributes[oldKey] != null) { + attributes[newKey] = attributes[oldKey]; + delete attributes[oldKey]; + } +} From 00e4e15324dcfe14ff763651327e58ebc436ced2 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 17 Jun 2025 12:31:47 -0400 Subject: [PATCH 2/2] revert breaking changes --- .../node/src/integrations/tracing/vercelai/index.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/node/src/integrations/tracing/vercelai/index.ts b/packages/node/src/integrations/tracing/vercelai/index.ts index 97025f691329..9557d62b5e04 100644 --- a/packages/node/src/integrations/tracing/vercelai/index.ts +++ b/packages/node/src/integrations/tracing/vercelai/index.ts @@ -64,8 +64,8 @@ const _vercelAIIntegration = ((options: VercelAiOptions = {}) => { ) { addOriginToSpan(span, 'auto.vercelai.otel'); span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.execute_tool'); - renameAttributeKey(attributes, AI_TOOL_CALL_ID_ATTRIBUTE, 'gen_ai.tool.call.id'); - renameAttributeKey(attributes, AI_TOOL_CALL_NAME_ATTRIBUTE, 'gen_ai.tool.name'); + span.setAttribute('gen_ai.tool.call.id', attributes[AI_TOOL_CALL_ID_ATTRIBUTE]); + span.setAttribute('gen_ai.tool.name', attributes[AI_TOOL_CALL_NAME_ATTRIBUTE]); span.updateName(`execute_tool ${attributes[AI_TOOL_CALL_NAME_ATTRIBUTE]}`); return; } @@ -92,9 +92,11 @@ const _vercelAIIntegration = ((options: VercelAiOptions = {}) => { span.setAttribute('ai.pipeline.name', functionId); } - renameAttributeKey(attributes, AI_PROMPT_ATTRIBUTE, 'gen_ai.prompt'); + if (attributes[AI_PROMPT_ATTRIBUTE]) { + span.setAttribute('gen_ai.prompt', attributes[AI_PROMPT_ATTRIBUTE]); + } if (attributes[AI_MODEL_ID_ATTRIBUTE] && !attributes[GEN_AI_RESPONSE_MODEL_ATTRIBUTE]) { - renameAttributeKey(attributes, AI_MODEL_ID_ATTRIBUTE, GEN_AI_RESPONSE_MODEL_ATTRIBUTE); + span.setAttribute(GEN_AI_RESPONSE_MODEL_ATTRIBUTE, attributes[AI_MODEL_ID_ATTRIBUTE]); } span.setAttribute('ai.streaming', name.includes('stream'));