|
1 | 1 | import { expect, it } from 'vitest'; |
2 | 2 | import { |
3 | 3 | GEN_AI_OPERATION_NAME_ATTRIBUTE, |
| 4 | + GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE, |
4 | 5 | GEN_AI_REQUEST_MODEL_ATTRIBUTE, |
5 | 6 | GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE, |
6 | 7 | GEN_AI_RESPONSE_ID_ATTRIBUTE, |
7 | 8 | GEN_AI_RESPONSE_MODEL_ATTRIBUTE, |
8 | 9 | GEN_AI_SYSTEM_ATTRIBUTE, |
9 | 10 | GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE, |
10 | 11 | GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE, |
| 12 | + GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE, |
11 | 13 | } from '../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; |
12 | 14 | import { createRunner } from '../../../runner'; |
13 | 15 |
|
14 | | -// These tests are not exhaustive because the instrumentation is |
15 | | -// already tested in the node integration tests and we merely |
16 | | -// want to test that the instrumentation does not break in our |
17 | | -// cloudflare SDK. |
| 16 | +// This test runs the `@anthropic-ai/sdk` on the Workers runtime (with a |
| 17 | +// canned fetch) to verify the instrumentation works end-to-end on Cloudflare, |
| 18 | +// not just against a hand-written mock client. |
18 | 19 |
|
19 | | -it('traces a basic message creation request', async ({ signal }) => { |
| 20 | +it('traces a basic message creation request with the anthropic SDK', async ({ signal }) => { |
20 | 21 | const runner = createRunner(__dirname) |
21 | 22 | .ignore('event') |
22 | 23 | .expect(envelope => { |
23 | | - // Transaction item (first item in envelope) |
24 | 24 | const transactionEvent = envelope[1]?.[0]?.[1] as any; |
25 | 25 | expect(transactionEvent.transaction).toBe('GET /'); |
26 | 26 |
|
27 | | - // Span container item (second item in same envelope) |
28 | 27 | const container = envelope[1]?.[1]?.[1] as any; |
29 | 28 | expect(container).toBeDefined(); |
30 | | - |
31 | 29 | expect(container.items).toHaveLength(1); |
32 | | - const [firstSpan] = container.items; |
33 | 30 |
|
34 | | - // [0] chat claude-3-haiku-20240307 |
35 | | - expect(firstSpan!.name).toBe('chat claude-3-haiku-20240307'); |
36 | | - expect(firstSpan!.status).toBe('ok'); |
37 | | - expect(firstSpan!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toEqual({ type: 'string', value: 'chat' }); |
38 | | - expect(firstSpan!.attributes['sentry.op']).toEqual({ type: 'string', value: 'gen_ai.chat' }); |
39 | | - expect(firstSpan!.attributes['sentry.origin']).toEqual({ type: 'string', value: 'auto.ai.anthropic' }); |
40 | | - expect(firstSpan!.attributes[GEN_AI_SYSTEM_ATTRIBUTE]).toEqual({ type: 'string', value: 'anthropic' }); |
41 | | - expect(firstSpan!.attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE]).toEqual({ |
42 | | - type: 'string', |
43 | | - value: 'claude-3-haiku-20240307', |
44 | | - }); |
45 | | - expect(firstSpan!.attributes[GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE]).toEqual({ type: 'double', value: 0.7 }); |
46 | | - expect(firstSpan!.attributes[GEN_AI_RESPONSE_MODEL_ATTRIBUTE]).toEqual({ |
47 | | - type: 'string', |
48 | | - value: 'claude-3-haiku-20240307', |
| 31 | + expect(container.items[0]).toEqual({ |
| 32 | + trace_id: expect.any(String), |
| 33 | + span_id: expect.any(String), |
| 34 | + parent_span_id: expect.any(String), |
| 35 | + name: 'chat claude-3-haiku-20240307', |
| 36 | + start_timestamp: expect.any(Number), |
| 37 | + end_timestamp: expect.any(Number), |
| 38 | + status: 'ok', |
| 39 | + is_segment: false, |
| 40 | + attributes: { |
| 41 | + 'sentry.origin': { value: 'auto.ai.anthropic', type: 'string' }, |
| 42 | + 'sentry.op': { value: 'gen_ai.chat', type: 'string' }, |
| 43 | + [GEN_AI_SYSTEM_ATTRIBUTE]: { value: 'anthropic', type: 'string' }, |
| 44 | + [GEN_AI_OPERATION_NAME_ATTRIBUTE]: { value: 'chat', type: 'string' }, |
| 45 | + [GEN_AI_REQUEST_MODEL_ATTRIBUTE]: { value: 'claude-3-haiku-20240307', type: 'string' }, |
| 46 | + [GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE]: { value: 0.7, type: 'double' }, |
| 47 | + [GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE]: { value: 100, type: 'integer' }, |
| 48 | + [GEN_AI_RESPONSE_ID_ATTRIBUTE]: { value: 'msg_mock123', type: 'string' }, |
| 49 | + [GEN_AI_RESPONSE_MODEL_ATTRIBUTE]: { value: 'claude-3-haiku-20240307', type: 'string' }, |
| 50 | + [GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE]: { value: 10, type: 'integer' }, |
| 51 | + [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: { value: 15, type: 'integer' }, |
| 52 | + [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: { value: 25, type: 'integer' }, |
| 53 | + }, |
49 | 54 | }); |
50 | | - expect(firstSpan!.attributes[GEN_AI_RESPONSE_ID_ATTRIBUTE]).toEqual({ type: 'string', value: 'msg_mock123' }); |
51 | | - expect(firstSpan!.attributes[GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE]).toEqual({ type: 'integer', value: 10 }); |
52 | | - expect(firstSpan!.attributes[GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]).toEqual({ type: 'integer', value: 15 }); |
53 | 55 | }) |
54 | 56 | .start(signal); |
55 | 57 | await runner.makeRequest('get', '/'); |
|
0 commit comments