|
1 | 1 | import { expect, test } from '@playwright/test'; |
2 | | -import { waitForRequest } from '@sentry-internal/test-utils'; |
| 2 | +import { waitForStreamedSpan } from '@sentry-internal/test-utils'; |
3 | 3 |
|
4 | 4 | test('sends spans for MCP tool calls via MCPAgent (DurableObject)', async ({ baseURL }) => { |
5 | 5 | const privateMessage = 'cloudflare-agent-private-capture-policy-message'; |
6 | | - const mcpToolWaiter = waitForRequest('cloudflare-mcp-agent', event => { |
7 | | - const transaction = event.envelope[1][0][1]; |
8 | | - return ( |
9 | | - typeof transaction !== 'string' && |
10 | | - 'transaction' in transaction && |
11 | | - transaction.transaction === 'tools/call my-tool' |
12 | | - ); |
13 | | - }); |
| 6 | + const mcpSpanPromise = waitForStreamedSpan('cloudflare-mcp-agent', span => span.name === 'tools/call my-tool'); |
14 | 7 |
|
15 | 8 | // Step 1: Initialize the MCP session |
16 | 9 | const initResponse = await fetch(`${baseURL}/mcp`, { |
@@ -76,30 +69,29 @@ test('sends spans for MCP tool calls via MCPAgent (DurableObject)', async ({ bas |
76 | 69 | expect(response.status).toBe(200); |
77 | 70 | await expect(response.text()).resolves.toContain(`Tool my-tool: ${privateMessage}`); |
78 | 71 |
|
79 | | - const mcpData = await mcpToolWaiter; |
80 | | - const mcpEvent = mcpData.envelope[1][0][1]; |
81 | | - const traceData = mcpEvent.contexts?.trace?.data; |
| 72 | + const mcpSpan = await mcpSpanPromise; |
82 | 73 |
|
83 | | - expect(mcpEvent.contexts?.trace?.trace_id).toBe(mcpData.envelope[0].trace.trace_id); |
84 | | - expect(mcpEvent.contexts?.trace).toEqual({ |
85 | | - trace_id: expect.any(String), |
86 | | - parent_span_id: expect.any(String), |
87 | | - span_id: expect.any(String), |
88 | | - op: 'mcp.server', |
89 | | - origin: 'auto.function.mcp_server', |
| 74 | + expect(mcpSpan).toEqual({ |
| 75 | + trace_id: expect.stringMatching(/^[a-f0-9]{32}$/), |
| 76 | + parent_span_id: expect.stringMatching(/^[a-f0-9]{16}$/), |
| 77 | + span_id: expect.stringMatching(/^[a-f0-9]{16}$/), |
| 78 | + name: 'tools/call my-tool', |
| 79 | + start_timestamp: expect.any(Number), |
| 80 | + end_timestamp: expect.any(Number), |
90 | 81 | status: 'ok', |
91 | | - data: expect.objectContaining({ |
92 | | - 'sentry.origin': 'auto.function.mcp_server', |
93 | | - 'sentry.op': 'mcp.server', |
94 | | - 'mcp.method.name': 'tools/call', |
95 | | - 'mcp.tool.name': 'my-tool', |
96 | | - 'mcp.tool.extra': 'from-mcpagent', |
97 | | - 'mcp.tool.result.content_count': 1, |
98 | | - 'mcp.tool.result.content_type': 'text', |
| 82 | + is_segment: true, |
| 83 | + attributes: expect.objectContaining({ |
| 84 | + 'sentry.origin': { value: 'auto.function.mcp_server', type: 'string' }, |
| 85 | + 'sentry.op': { value: 'mcp.server', type: 'string' }, |
| 86 | + 'mcp.method.name': { value: 'tools/call', type: 'string' }, |
| 87 | + 'mcp.tool.name': { value: 'my-tool', type: 'string' }, |
| 88 | + 'mcp.tool.extra': { value: 'from-mcpagent', type: 'string' }, |
| 89 | + 'mcp.tool.result.content_count': { value: 1, type: 'integer' }, |
| 90 | + 'mcp.tool.result.content_type': { value: 'text', type: 'string' }, |
99 | 91 | }), |
100 | 92 | }); |
101 | | - expect(traceData?.['mcp.request.argument.message']).toBeUndefined(); |
102 | | - expect(traceData?.['mcp.tool.result.content']).toBeUndefined(); |
103 | | - expect(traceData?.['mcp.tool.input']).toBeUndefined(); |
104 | | - expect(JSON.stringify(traceData)).not.toContain(privateMessage); |
| 93 | + expect(mcpSpan.attributes['mcp.request.argument.message']).toBeUndefined(); |
| 94 | + expect(mcpSpan.attributes['mcp.tool.result.content']).toBeUndefined(); |
| 95 | + expect(mcpSpan.attributes['mcp.tool.input']).toBeUndefined(); |
| 96 | + expect(JSON.stringify(mcpSpan.attributes)).not.toContain(privateMessage); |
105 | 97 | }); |
0 commit comments