@@ -3,6 +3,7 @@ import { captureException } from '../../exports';
33import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes' ;
44import { startSpan } from '../../tracing/trace' ;
55import type { Span , SpanAttributeValue } from '../../types-hoist/span' ;
6+ import { getActiveSpan , getRootSpan , spanToJSON } from '../../utils/spanUtils' ;
67import {
78 GEN_AI_OPERATION_NAME_ATTRIBUTE ,
89 GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE ,
@@ -25,7 +26,7 @@ import {
2526 CHAT_PATH ,
2627 CHATS_CREATE_METHOD ,
2728 GOOGLE_GENAI_INTEGRATION_NAME ,
28- GOOGLE_GENAI_MODEL_PROPERTY ,
29+ GOOGLE_GENAI_SCOPE_MODEL_KEY ,
2930 GOOGLE_GENAI_SYSTEM_NAME ,
3031} from './constants' ;
3132import type {
@@ -39,21 +40,35 @@ import type {
3940import { shouldInstrument } from './utils' ;
4041
4142/**
42- * Extract model from parameters or context
43- * For chat instances, the model is stored during chat creation and retrieved from context
43+ * Store model information on the root span for later retrieval by chat.sendMessage
4444 */
45- export function extractModel ( params : Record < string , unknown > , context ?: unknown ) : string {
45+ function storeModelOnRootSpan ( model : string ) : void {
46+ const activeSpan = getActiveSpan ( ) ;
47+ if ( activeSpan ) {
48+ const rootSpan = getRootSpan ( activeSpan ) ;
49+ rootSpan . setAttributes ( {
50+ [ GOOGLE_GENAI_SCOPE_MODEL_KEY ] : model ,
51+ } ) ;
52+ }
53+ }
54+
55+ /**
56+ * Extract model from parameters or root span attributes
57+ * For chat instances, the model is stored on the root span during chat creation
58+ */
59+ export function extractModel ( params : Record < string , unknown > , _context ?: unknown ) : string {
4660 if ( 'model' in params && typeof params . model === 'string' ) {
4761 return params . model ;
4862 }
4963
50- // For chat instances, try to get the model from the chat context
51- // This is because the model is set during chat creation
52- // and not passed as a parameter to the chat.sendMessage method
53- if ( context && typeof context === 'object' ) {
54- const chatObj = context as Record < string , unknown > ;
55- if ( chatObj [ GOOGLE_GENAI_MODEL_PROPERTY ] && typeof chatObj [ GOOGLE_GENAI_MODEL_PROPERTY ] === 'string' ) {
56- return chatObj [ GOOGLE_GENAI_MODEL_PROPERTY ] as string ;
64+ // Try to get model from root span attributes
65+ const activeSpan = getActiveSpan ( ) ;
66+ if ( activeSpan ) {
67+ const rootSpan = getRootSpan ( activeSpan ) ;
68+ const spanData = spanToJSON ( rootSpan ) ;
69+ const modelFromSpan = spanData . data ?. [ GOOGLE_GENAI_SCOPE_MODEL_KEY ] ;
70+ if ( typeof modelFromSpan === 'string' ) {
71+ return modelFromSpan ;
5772 }
5873 }
5974
@@ -238,12 +253,11 @@ function instrumentMethod<T extends unknown[], R>(
238253 if ( finalOptions . recordInputs && args [ 0 ] && typeof args [ 0 ] === 'object' ) {
239254 addPrivateRequestAttributes ( span , args [ 0 ] as Record < string , unknown > ) ;
240255 }
241- const result = ( originalMethod as ( ...args : T ) => R ) . apply ( context , args ) as R ;
256+ const result = ( originalMethod as ( ...args : T ) => R ) . apply ( context , args ) ;
242257
243- if ( typeof model === 'string' && model !== 'unknown' && typeof result === 'object' ) {
244- // We store the model in the result object so that it can be accessed later
245- // This is because the model is not passed as a parameter to the chat.sendMessage method
246- ( result as Record < string , unknown > ) [ GOOGLE_GENAI_MODEL_PROPERTY ] = model ;
258+ if ( typeof model === 'string' && model !== 'unknown' ) {
259+ // Store model information on root span for later retrieval by chat.sendMessage
260+ storeModelOnRootSpan ( model ) ;
247261 }
248262
249263 // No response attributes for create (returns object of chat instance, not generated content)
@@ -255,7 +269,7 @@ function instrumentMethod<T extends unknown[], R>(
255269 throw error ;
256270 }
257271 } ,
258- ) as R ;
272+ ) ;
259273 }
260274
261275 // Async/content-producing path
@@ -273,15 +287,15 @@ function instrumentMethod<T extends unknown[], R>(
273287
274288 const result = await Promise . resolve ( ( originalMethod as ( ...args : T ) => Promise < R > ) . apply ( context , args ) ) ;
275289 addResponseAttributes ( span , result as GoogleGenAIResponse , finalOptions . recordOutputs ) ;
276- return result as R ;
290+ return result ;
277291 } catch ( error ) {
278292 captureException ( error , {
279293 mechanism : { handled : false , type : 'auto.ai.google_genai' , data : { function : methodPath } } ,
280294 } ) ;
281295 throw error ;
282296 }
283297 } ,
284- ) as Promise < R > ;
298+ ) ;
285299 } ;
286300
287301 return run ;
0 commit comments