Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,8 @@ describe('OpenAI Tool Calls integration', () => {
type: 'string',
value: 'gpt-4',
});
expect(chatToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
// Tool definitions are gen AI input data, so `genAI.inputs: false` drops them.
expect(chatToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toBeUndefined();
expect(chatToolsSpan!.attributes[GEN_AI_RESPONSE_MODEL]).toEqual({
type: 'string',
value: 'gpt-4',
Expand Down Expand Up @@ -164,10 +162,7 @@ describe('OpenAI Tool Calls integration', () => {
type: 'boolean',
value: true,
});
expect(streamingChatToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
expect(streamingChatToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toBeUndefined();
expect(streamingChatToolsSpan!.attributes[GEN_AI_RESPONSE_MODEL]).toEqual({
type: 'string',
value: 'gpt-4',
Expand Down Expand Up @@ -224,10 +219,7 @@ describe('OpenAI Tool Calls integration', () => {
value: 'gpt-4',
});
expect(responsesToolsSpan!.attributes[GEN_AI_REQUEST_STREAM_ATTRIBUTE]).toBeUndefined();
expect(responsesToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
expect(responsesToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toBeUndefined();
expect(responsesToolsSpan!.attributes[GEN_AI_RESPONSE_MODEL]).toEqual({
type: 'string',
value: 'gpt-4',
Expand Down Expand Up @@ -283,10 +275,7 @@ describe('OpenAI Tool Calls integration', () => {
type: 'boolean',
value: true,
});
expect(streamingResponsesToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
expect(streamingResponsesToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toBeUndefined();
expect(streamingResponsesToolsSpan!.attributes[GEN_AI_RESPONSE_MODEL]).toEqual({
type: 'string',
value: 'gpt-4',
Expand Down
10 changes: 7 additions & 3 deletions packages/server-utils/src/ai/anthropic-ai/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ const INSTRUMENTED_METHODS = new WeakSet<object>();
/**
* Extract request attributes from method arguments
*/
export function extractRequestAttributes(args: unknown[], operationName: string): Record<string, unknown> {
export function extractRequestAttributes(
args: unknown[],
operationName: string,
recordInputs: boolean,
): Record<string, unknown> {
const attributes: Record<string, unknown> = {
[GEN_AI_PROVIDER_NAME]: 'anthropic',
[GEN_AI_OPERATION_NAME]: operationName,
Expand All @@ -57,7 +61,7 @@ export function extractRequestAttributes(args: unknown[], operationName: string)

if (args.length > 0 && typeof args[0] === 'object' && args[0] !== null) {
const params = args[0] as Record<string, unknown>;
if (params.tools && Array.isArray(params.tools)) {
if (recordInputs && params.tools && Array.isArray(params.tools)) {
attributes[GEN_AI_TOOL_DEFINITIONS] = JSON.stringify(params.tools);
}

Expand Down Expand Up @@ -259,7 +263,7 @@ function instrumentMethod<T extends unknown[], R>(
}

const operationName = instrumentedMethod.operation || 'unknown';
const requestAttributes = extractRequestAttributes(args, operationName);
const requestAttributes = extractRequestAttributes(args, operationName, !!options.recordInputs);
const model = requestAttributes[GEN_AI_REQUEST_MODEL] || 'unknown';
const client = getClient();
// With span streaming, omit the `'unknown'` model sentinel so the name stays low-cardinality.
Expand Down
10 changes: 8 additions & 2 deletions packages/server-utils/src/ai/google-genai/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export function extractRequestAttributes(
operationName: string,
params?: Record<string, unknown>,
context?: unknown,
recordInputs = true,
): Record<string, SpanAttributeValue> {
const attributes: Record<string, SpanAttributeValue> = {
[GEN_AI_PROVIDER_NAME]: GOOGLE_GENAI_SYSTEM_NAME,
Expand All @@ -119,7 +120,7 @@ export function extractRequestAttributes(
Object.assign(attributes, extractConfigAttributes(config));

// Extract available tools from config
if ('tools' in config && Array.isArray(config.tools)) {
if (recordInputs && 'tools' in config && Array.isArray(config.tools)) {
const functionDeclarations = config.tools.flatMap(
(tool: { functionDeclarations: unknown[] }) => tool.functionDeclarations,
);
Expand Down Expand Up @@ -301,7 +302,12 @@ function instrumentMethod<T extends unknown[], R>(
const operationName = instrumentedMethod.operation || 'unknown';
const params = args[0] as Record<string, unknown> | undefined;
const attributeParams = resolveChatParams(operationName, params, context);
const requestAttributes = extractRequestAttributes(operationName, attributeParams, context);
const requestAttributes = extractRequestAttributes(
operationName,
attributeParams,
context,
!!options.recordInputs,
);
const model = requestAttributes[GEN_AI_REQUEST_MODEL] || 'unknown';
const client = getClient();
// With span streaming, omit the `'unknown'` model sentinel so the name stays low-cardinality.
Expand Down
2 changes: 1 addition & 1 deletion packages/server-utils/src/ai/langchain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export function createLangChainCallbackHandler(options: LangChainOptions = {}):
metadata,
);

const toolDefsJson = extractToolDefinitions(extraParams);
const toolDefsJson = recordInputs ? extractToolDefinitions(extraParams) : undefined;
if (toolDefsJson) {
attributes[GEN_AI_TOOL_DEFINITIONS] = toolDefsJson;
}
Expand Down
12 changes: 8 additions & 4 deletions packages/server-utils/src/ai/langgraph/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,15 @@ const SENTRY_PATCHED = '__sentry_patched__';
*/
export function instrumentStateGraphCompile(
originalCompile: (...args: unknown[]) => CompiledGraph,
options: LangGraphOptions,
rawOptions: LangGraphOptions,
): (...args: unknown[]) => CompiledGraph {
if (Object.prototype.hasOwnProperty.call(originalCompile, SENTRY_PATCHED)) {
return originalCompile;
}

// This is exported, so callers can hand us an options object with no recording flags set. Resolving
// here (rather than only in `instrumentStateGraph`) keeps that path on the `dataCollection` defaults.
const options = resolveAIRecordingOptions(rawOptions);
Comment thread
s1gr1d marked this conversation as resolved.
const sentryHandler = createLangChainCallbackHandler(options);

const wrapped = new Proxy(originalCompile, {
Expand Down Expand Up @@ -142,15 +145,16 @@ export function instrumentCompiledGraphInvoke(
);
}

const recordInputs = options.recordInputs;
const recordOutputs = options.recordOutputs;

// Extract available tools from the graph instance
const tools = extractToolsFromCompiledGraph(graphInstance);
const tools = recordInputs ? extractToolsFromCompiledGraph(graphInstance) : null;
Comment thread
sentry[bot] marked this conversation as resolved.
if (tools) {
span.setAttribute(GEN_AI_TOOL_DEFINITIONS, JSON.stringify(tools));
}

// Parse input messages
const recordInputs = options.recordInputs;
const recordOutputs = options.recordOutputs;
const inputMessages =
args.length > 0 ? ((args[0] as { messages?: LangChainMessage[] } | null)?.messages ?? []) : [];

Expand Down
10 changes: 7 additions & 3 deletions packages/server-utils/src/ai/openai/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ function extractAvailableTools(params: Record<string, unknown>): string | undefi
/**
* Extract request attributes from method arguments
*/
export function extractRequestAttributes(args: unknown[], operationName: string): Record<string, unknown> {
export function extractRequestAttributes(
args: unknown[],
operationName: string,
recordInputs: boolean,
): Record<string, unknown> {
const attributes: Record<string, unknown> = {
[GEN_AI_PROVIDER_NAME]: 'openai',
[GEN_AI_OPERATION_NAME]: operationName,
Expand All @@ -69,7 +73,7 @@ export function extractRequestAttributes(args: unknown[], operationName: string)
if (args.length > 0 && typeof args[0] === 'object' && args[0] !== null) {
const params = args[0] as Record<string, unknown>;

const availableTools = extractAvailableTools(params);
const availableTools = recordInputs ? extractAvailableTools(params) : undefined;
if (availableTools) {
attributes[GEN_AI_TOOL_DEFINITIONS] = availableTools;
}
Expand Down Expand Up @@ -140,7 +144,7 @@ function instrumentMethod<T extends unknown[], R>(
): (...args: T) => Promise<R> {
return function instrumentedCall(...args: T): Promise<R> {
const operationName = instrumentedMethod.operation || 'unknown';
const requestAttributes = extractRequestAttributes(args, operationName);
const requestAttributes = extractRequestAttributes(args, operationName, !!options.recordInputs);
const model = (requestAttributes[GEN_AI_REQUEST_MODEL] as string) || 'unknown';

const params = args[0] as Record<string, unknown> | undefined;
Expand Down
2 changes: 1 addition & 1 deletion packages/server-utils/src/integrations/anthropic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ function createGenAiSpan(

const { recordInputs } = resolveAIRecordingOptions(options);

const attributes = extractRequestAttributes(args, operation);
const attributes = extractRequestAttributes(args, operation, recordInputs);
const model = (attributes[GEN_AI_REQUEST_MODEL] as string) || 'unknown';
attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN;
const client = getClient();
Expand Down
2 changes: 1 addition & 1 deletion packages/server-utils/src/integrations/google-genai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ function createGenAiSpan(

const { recordInputs } = resolveAIRecordingOptions(options);

const attributes = extractRequestAttributes(operation, params, data.self);
const attributes = extractRequestAttributes(operation, params, data.self, recordInputs);
const model = (attributes[GEN_AI_REQUEST_MODEL] as string) || 'unknown';
attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN;
const client = getClient();
Expand Down
2 changes: 1 addition & 1 deletion packages/server-utils/src/integrations/openai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function createGenAiSpan(data: OpenAiChatChannelContext, operation: string, opti

const { recordInputs } = resolveAIRecordingOptions(options);

const attributes = extractRequestAttributes(args, operation);
const attributes = extractRequestAttributes(args, operation, recordInputs);
attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN;
const model = (params?.model as string) || 'unknown';
const client = getClient();
Expand Down
Loading