Skip to content

Commit 6ef5ce0

Browse files
committed
some refacotor
1 parent f79ba78 commit 6ef5ce0

File tree

5 files changed

+48
-39
lines changed

5 files changed

+48
-39
lines changed

dev-packages/node-integration-tests/suites/tracing/google-genai/scenario.mjs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ class MockGoogleGenAI {
2222
content: {
2323
parts: [
2424
{
25-
text: params.contents
26-
? 'The capital of France is Paris.'
27-
: 'Mock response from Google GenAI!',
25+
text: params.contents ? 'The capital of France is Paris.' : 'Mock response from Google GenAI!',
2826
},
2927
],
3028
role: 'model',

packages/core/src/utils/ai/gen-ai-attributes.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -178,15 +178,3 @@ export const OPENAI_OPERATIONS = {
178178
* The response timestamp from Anthropic AI (ISO string)
179179
*/
180180
export const ANTHROPIC_AI_RESPONSE_TIMESTAMP_ATTRIBUTE = 'anthropic.response.timestamp';
181-
182-
// =============================================================================
183-
// GOOGLE GENAI OPERATIONS
184-
// =============================================================================
185-
186-
/**
187-
* Google GenAI API operations
188-
*/
189-
export const GOOGLE_GENAI_OPERATIONS = {
190-
GENERATE_CONTENT: 'generateContent',
191-
STREAM_GENERATE_CONTENT: 'streamGenerateContent',
192-
} as const;

packages/core/src/utils/google-genai/constants.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ export const GOOGLE_GENAI_INTEGRATION_NAME = 'Google_GenAI';
55
export const GOOGLE_GENAI_INSTRUMENTED_METHODS = ['models.generateContent', 'chats.create', 'sendMessage'] as const;
66

77
// Constants for internal use
8-
export const GOOGLE_GENAI_MODEL_PROPERTY = '_sentryGoogleGenAIModel';
98
export const GOOGLE_GENAI_SYSTEM_NAME = 'google_genai';
109
export const CHATS_CREATE_METHOD = 'chats.create';
1110
export const CHAT_PATH = 'chat';
11+
12+
// Span attribute key for storing chat context
13+
export const GOOGLE_GENAI_SCOPE_MODEL_KEY = 'google_genai.chat.model';

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

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { captureException } from '../../exports';
33
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';
44
import { startSpan } from '../../tracing/trace';
55
import type { Span, SpanAttributeValue } from '../../types-hoist/span';
6+
import { getActiveSpan, getRootSpan, spanToJSON } from '../../utils/spanUtils';
67
import {
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';
3132
import type {
@@ -39,21 +40,35 @@ import type {
3940
import { 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;

packages/node/src/integrations/tracing/google-genai/instrumentation.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@ import {
44
InstrumentationBase,
55
InstrumentationNodeModuleDefinition,
66
} from '@opentelemetry/instrumentation';
7-
import type { GoogleGenAIClient, GoogleGenAIOptions, Integration } from '@sentry/core';
7+
import type { GoogleGenAIClient, Integration } from '@sentry/core';
88
import { getCurrentScope, GOOGLE_GENAI_INTEGRATION_NAME, instrumentGoogleGenAIClient, SDK_VERSION } from '@sentry/core';
99

1010
const supportedVersions = ['>=0.10.0 <2'];
1111

12+
interface GoogleGenAIOptions {
13+
recordInputs?: boolean;
14+
recordOutputs?: boolean;
15+
}
16+
1217
export interface GoogleGenAIIntegration extends Integration {
1318
options: GoogleGenAIOptions;
1419
}
@@ -28,9 +33,11 @@ function determineRecordingSettings(
2833
integrationOptions: GoogleGenAIOptions | undefined,
2934
defaultEnabled: boolean,
3035
): { recordInputs: boolean; recordOutputs: boolean } {
31-
const recordInputs = integrationOptions?.recordInputs ?? defaultEnabled;
32-
const recordOutputs = integrationOptions?.recordOutputs ?? defaultEnabled;
33-
return { recordInputs, recordOutputs };
36+
if (!integrationOptions?.recordInputs || !integrationOptions.recordOutputs) {
37+
return { recordInputs: defaultEnabled, recordOutputs: defaultEnabled };
38+
}
39+
40+
return { recordInputs: integrationOptions.recordInputs, recordOutputs: integrationOptions.recordOutputs };
3441
}
3542

3643
/**

0 commit comments

Comments
 (0)