MCPcopy Index your code
hub / github.com/getsentry/sentry-javascript / apply

Function apply

packages/core/src/tracing/langgraph/utils.ts:78–154  ·  view source on GitHub ↗
(target, thisArg, args: unknown[])

Source from the content-addressed store, hash-verified

76
77 const wrappedInvoke = new Proxy(originalInvoke as (...args: unknown[]) => unknown, {
78 apply(target, thisArg, args: unknown[]): unknown {
79 const spanAttributes: SpanAttributes = {
80 [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGGRAPH_ORIGIN,
81 [SEMANTIC_ATTRIBUTE_SENTRY_OP]: GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE,
82 [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'execute_tool',
83 [GEN_AI_TOOL_NAME_ATTRIBUTE]: toolName,
84 [GEN_AI_TOOL_TYPE_ATTRIBUTE]: 'function',
85 };
86
87 // Read agent name from LangChain's propagated config metadata at call time,
88 // so shared tools get the correct agent name for each invocation
89 const callConfig = args[1] as Record<string, unknown> | undefined;
90 const callAgentName = (callConfig?.metadata as Record<string, unknown>)?.lc_agent_name ?? agentName;
91 if (typeof callAgentName === 'string') {
92 spanAttributes[GEN_AI_AGENT_NAME_ATTRIBUTE] = callAgentName;
93 }
94
95 if (toolDescription) {
96 spanAttributes[GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE] = toolDescription;
97 }
98
99 // LangGraph ToolNode passes { name, args, id, type: "tool_call" }
100 const input = args[0] as Record<string, unknown> | undefined;
101 if (typeof input === 'object' && !!input) {
102 if ('id' in input && typeof input.id === 'string') {
103 spanAttributes[GEN_AI_TOOL_CALL_ID_ATTRIBUTE] = input.id;
104 }
105
106 if (options.recordInputs) {
107 const toolArgs = 'args' in input && typeof input.args === 'object' ? input.args : input;
108 try {
109 spanAttributes[GEN_AI_TOOL_INPUT_ATTRIBUTE] = JSON.stringify(toolArgs);
110 } catch {
111 // skip if not serializable
112 }
113 }
114 }
115
116 return startSpan(
117 {
118 op: GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE,
119 name: `execute_tool ${toolName}`,
120 attributes: spanAttributes,
121 },
122 async span => {
123 try {
124 const result = await Reflect.apply(target, thisArg, args);
125
126 if (options.recordOutputs) {
127 try {
128 // ToolMessage objects wrap the result in .content
129 const resultObj = result as Record<string, unknown> | undefined;
130 const content =
131 resultObj && typeof resultObj === 'object' && 'content' in resultObj ? resultObj.content : result;
132 span.setAttribute(
133 GEN_AI_TOOL_OUTPUT_ATTRIBUTE,
134 typeof content === 'string' ? content : JSON.stringify(content),
135 );

Callers

nothing calls this directly

Calls 5

startSpanFunction · 0.90
captureExceptionFunction · 0.90
setAttributeMethod · 0.65
setStatusMethod · 0.65
applyMethod · 0.45

Tested by

no test coverage detected