|
1 | 1 | import { captureException } from '../../exports'; |
2 | 2 | import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes'; |
3 | 3 | import { SPAN_STATUS_ERROR } from '../../tracing'; |
4 | | -import type { Span } from '../../types-hoist/span'; |
5 | 4 | import { |
6 | 5 | GEN_AI_AGENT_NAME_ATTRIBUTE, |
| 6 | + GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE, |
7 | 7 | GEN_AI_OPERATION_NAME_ATTRIBUTE, |
8 | 8 | GEN_AI_PIPELINE_NAME_ATTRIBUTE, |
9 | 9 | GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, |
10 | 10 | GEN_AI_REQUEST_MESSAGES_ATTRIBUTE, |
11 | | - GEN_AI_RESPONSE_TEXT_ATTRIBUTE, |
12 | | - GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE, |
13 | 11 | } from '../../utils/ai/gen-ai-attributes'; |
14 | 12 | import { truncateGenAiMessages } from '../../utils/ai/messageTruncation'; |
15 | 13 | import type { LangChainMessage } from '../../utils/langchain/types'; |
16 | 14 | import { normalizeLangChainMessages } from '../../utils/langchain/utils'; |
17 | 15 | import { startSpan } from '../trace'; |
18 | 16 | import { LANGGRAPH_ORIGIN } from './constants'; |
19 | | -import type { CompiledGraph, LangGraphOptions, LangGraphTool } from './types'; |
20 | | -import { extractModelMetadata, extractTokenUsageFromMetadata, extractToolCalls } from './utils'; |
| 17 | +import type { CompiledGraph, LangGraphOptions } from './types'; |
| 18 | +import { extractToolsFromCompiledGraph, setResponseAttributes } from './utils'; |
21 | 19 |
|
22 | 20 | /** |
23 | 21 | * Instruments StateGraph's compile method to create spans for agent creation and invocation |
24 | 22 | * |
25 | 23 | * Wraps the compile() method to: |
26 | 24 | * - Create a `gen_ai.create_agent` span when compile() is called |
27 | | - * - Automatically wrap the invoke() method on the returned compiled graph |
| 25 | + * - Automatically wrap the invoke() method on the returned compiled graph with a `gen_ai.invoke_agent` span |
28 | 26 | * |
29 | 27 | */ |
30 | 28 | export function instrumentStateGraphCompile( |
@@ -101,7 +99,7 @@ function instrumentCompiledGraphInvoke( |
101 | 99 | name: 'invoke_agent', |
102 | 100 | attributes: { |
103 | 101 | [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGGRAPH_ORIGIN, |
104 | | - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.invoke_agent', |
| 102 | + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE, |
105 | 103 | [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'invoke_agent', |
106 | 104 | }, |
107 | 105 | }, |
@@ -156,64 +154,3 @@ function instrumentCompiledGraphInvoke( |
156 | 154 | }, |
157 | 155 | }) as (...args: unknown[]) => Promise<unknown>; |
158 | 156 | } |
159 | | - |
160 | | -/** |
161 | | - * Extract tools from compiled graph structure |
162 | | - * |
163 | | - * Tools are stored in: compiledGraph.builder.nodes.tools.runnable.tools |
164 | | - */ |
165 | | -function extractToolsFromCompiledGraph(compiledGraph: CompiledGraph): unknown[] | null { |
166 | | - if (!compiledGraph.builder?.nodes?.tools?.runnable?.tools) { |
167 | | - return null; |
168 | | - } |
169 | | - |
170 | | - const tools = compiledGraph.builder?.nodes?.tools?.runnable?.tools; |
171 | | - |
172 | | - if (!tools || !Array.isArray(tools) || tools.length === 0) { |
173 | | - return null; |
174 | | - } |
175 | | - |
176 | | - // Extract name, description, and schema from each tool's lc_kwargs |
177 | | - return tools.map((tool: LangGraphTool) => ({ |
178 | | - name: tool.lc_kwargs?.name, |
179 | | - description: tool.lc_kwargs?.description, |
180 | | - schema: tool.lc_kwargs?.schema, |
181 | | - })); |
182 | | -} |
183 | | - |
184 | | -/** |
185 | | - * Set response attributes on the span |
186 | | - */ |
187 | | -function setResponseAttributes(span: Span, inputMessages: LangChainMessage[] | null, result: unknown): void { |
188 | | - // Extract messages from result |
189 | | - const resultObj = result as { messages?: LangChainMessage[] } | undefined; |
190 | | - const outputMessages = resultObj?.messages; |
191 | | - |
192 | | - if (!outputMessages || !Array.isArray(outputMessages)) { |
193 | | - return; |
194 | | - } |
195 | | - |
196 | | - // Get new messages (delta between input and output) |
197 | | - const inputCount = inputMessages?.length ?? 0; |
198 | | - const newMessages = outputMessages.length > inputCount ? outputMessages.slice(inputCount) : []; |
199 | | - |
200 | | - if (newMessages.length === 0) { |
201 | | - return; |
202 | | - } |
203 | | - |
204 | | - // Normalize the new messages |
205 | | - const normalizedNewMessages = normalizeLangChainMessages(newMessages); |
206 | | - span.setAttribute(GEN_AI_RESPONSE_TEXT_ATTRIBUTE, JSON.stringify(normalizedNewMessages)); |
207 | | - |
208 | | - // Extract and set tool calls from new messages |
209 | | - const toolCalls = extractToolCalls(normalizedNewMessages); |
210 | | - if (toolCalls) { |
211 | | - span.setAttribute(GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE, JSON.stringify(toolCalls)); |
212 | | - } |
213 | | - |
214 | | - // Extract metadata from messages |
215 | | - for (const message of newMessages) { |
216 | | - extractTokenUsageFromMetadata(span, message); |
217 | | - extractModelMetadata(span, message); |
218 | | - } |
219 | | -} |
0 commit comments