1- import { SEMANTIC_ATTRIBUTE_SENTRY_OP , SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core' ;
21import { expect , it } from 'vitest' ;
32import {
43 GEN_AI_OPERATION_NAME_ATTRIBUTE ,
@@ -18,67 +17,69 @@ import { createRunner } from '../../../runner';
1817// want to test that the instrumentation does not break in our
1918// cloudflare SDK.
2019
21- it ( 'traces Google GenAI chat creation and message sending' , async ( ) => {
20+ it ( 'traces Google GenAI chat creation and message sending' , async ( { signal } ) => {
2221 const runner = createRunner ( __dirname )
2322 . ignore ( 'event' )
2423 . expect ( envelope => {
24+ // Transaction item (first item in envelope)
2525 const transactionEvent = envelope [ 1 ] ?. [ 0 ] ?. [ 1 ] as any ;
26-
2726 expect ( transactionEvent . transaction ) . toBe ( 'GET /' ) ;
28- expect ( transactionEvent . spans ) . toEqual (
29- expect . arrayContaining ( [
30- // chat.sendMessage
31- expect . objectContaining ( {
32- data : expect . objectContaining ( {
33- [ GEN_AI_OPERATION_NAME_ATTRIBUTE ] : 'chat' ,
34- [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'gen_ai.chat' ,
35- [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.ai.google_genai' ,
36- [ GEN_AI_SYSTEM_ATTRIBUTE ] : 'google_genai' ,
37- [ GEN_AI_REQUEST_MODEL_ATTRIBUTE ] : 'gemini-1.5-pro' ,
38- [ GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ] : 8 ,
39- [ GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ] : 12 ,
40- [ GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE ] : 20 ,
41- } ) ,
42- description : 'chat gemini-1.5-pro' ,
43- op : 'gen_ai.chat' ,
44- origin : 'auto.ai.google_genai' ,
45- } ) ,
46- // models.generateContent
47- expect . objectContaining ( {
48- data : expect . objectContaining ( {
49- [ GEN_AI_OPERATION_NAME_ATTRIBUTE ] : 'generate_content' ,
50- [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'gen_ai.generate_content' ,
51- [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.ai.google_genai' ,
52- [ GEN_AI_SYSTEM_ATTRIBUTE ] : 'google_genai' ,
53- [ GEN_AI_REQUEST_MODEL_ATTRIBUTE ] : 'gemini-1.5-flash' ,
54- [ GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE ] : 0.7 ,
55- [ GEN_AI_REQUEST_TOP_P_ATTRIBUTE ] : 0.9 ,
56- [ GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE ] : 100 ,
57- [ GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ] : 8 ,
58- [ GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ] : 12 ,
59- [ GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE ] : 20 ,
60- } ) ,
61- description : 'generate_content gemini-1.5-flash' ,
62- op : 'gen_ai.generate_content' ,
63- origin : 'auto.ai.google_genai' ,
64- } ) ,
65- // models.embedContent
66- expect . objectContaining ( {
67- data : expect . objectContaining ( {
68- [ GEN_AI_OPERATION_NAME_ATTRIBUTE ] : 'embeddings' ,
69- [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'gen_ai.embeddings' ,
70- [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.ai.google_genai' ,
71- [ GEN_AI_SYSTEM_ATTRIBUTE ] : 'google_genai' ,
72- [ GEN_AI_REQUEST_MODEL_ATTRIBUTE ] : 'text-embedding-004' ,
73- } ) ,
74- description : 'embeddings text-embedding-004' ,
75- op : 'gen_ai.embeddings' ,
76- origin : 'auto.ai.google_genai' ,
77- } ) ,
78- ] ) ,
79- ) ;
27+
28+ // Span container item (second item in same envelope)
29+ const container = envelope [ 1 ] ?. [ 1 ] ?. [ 1 ] as any ;
30+ expect ( container ) . toBeDefined ( ) ;
31+ expect ( container . items ) . toHaveLength ( 3 ) ;
32+ const [ firstSpan , secondSpan , thirdSpan ] = container . items ;
33+
34+ // [0] chat gemini-1.5-pro
35+ expect ( firstSpan ! . name ) . toBe ( 'chat gemini-1.5-pro' ) ;
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.google_genai' } ) ;
40+ expect ( firstSpan ! . attributes [ GEN_AI_SYSTEM_ATTRIBUTE ] ) . toEqual ( { type : 'string' , value : 'google_genai' } ) ;
41+ expect ( firstSpan ! . attributes [ GEN_AI_REQUEST_MODEL_ATTRIBUTE ] ) . toEqual ( {
42+ type : 'string' ,
43+ value : 'gemini-1.5-pro' ,
44+ } ) ;
45+ expect ( firstSpan ! . attributes [ GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ] ) . toEqual ( { type : 'integer' , value : 8 } ) ;
46+ expect ( firstSpan ! . attributes [ GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ] ) . toEqual ( { type : 'integer' , value : 12 } ) ;
47+ expect ( firstSpan ! . attributes [ GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE ] ) . toEqual ( { type : 'integer' , value : 20 } ) ;
48+
49+ // [1] generate_content gemini-1.5-flash
50+ expect ( secondSpan ! . name ) . toBe ( 'generate_content gemini-1.5-flash' ) ;
51+ expect ( secondSpan ! . status ) . toBe ( 'ok' ) ;
52+ expect ( secondSpan ! . attributes [ GEN_AI_OPERATION_NAME_ATTRIBUTE ] ) . toEqual ( {
53+ type : 'string' ,
54+ value : 'generate_content' ,
55+ } ) ;
56+ expect ( secondSpan ! . attributes [ 'sentry.op' ] ) . toEqual ( { type : 'string' , value : 'gen_ai.generate_content' } ) ;
57+ expect ( secondSpan ! . attributes [ 'sentry.origin' ] ) . toEqual ( { type : 'string' , value : 'auto.ai.google_genai' } ) ;
58+ expect ( secondSpan ! . attributes [ GEN_AI_SYSTEM_ATTRIBUTE ] ) . toEqual ( { type : 'string' , value : 'google_genai' } ) ;
59+ expect ( secondSpan ! . attributes [ GEN_AI_REQUEST_MODEL_ATTRIBUTE ] ) . toEqual ( {
60+ type : 'string' ,
61+ value : 'gemini-1.5-flash' ,
62+ } ) ;
63+ expect ( secondSpan ! . attributes [ GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE ] ) . toEqual ( { type : 'double' , value : 0.7 } ) ;
64+ expect ( secondSpan ! . attributes [ GEN_AI_REQUEST_TOP_P_ATTRIBUTE ] ) . toEqual ( { type : 'double' , value : 0.9 } ) ;
65+ expect ( secondSpan ! . attributes [ GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE ] ) . toEqual ( { type : 'integer' , value : 100 } ) ;
66+ expect ( secondSpan ! . attributes [ GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ] ) . toEqual ( { type : 'integer' , value : 8 } ) ;
67+ expect ( secondSpan ! . attributes [ GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ] ) . toEqual ( { type : 'integer' , value : 12 } ) ;
68+ expect ( secondSpan ! . attributes [ GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE ] ) . toEqual ( { type : 'integer' , value : 20 } ) ;
69+
70+ // [2] embeddings text-embedding-004
71+ expect ( thirdSpan ! . name ) . toBe ( 'embeddings text-embedding-004' ) ;
72+ expect ( thirdSpan ! . status ) . toBe ( 'ok' ) ;
73+ expect ( thirdSpan ! . attributes [ GEN_AI_OPERATION_NAME_ATTRIBUTE ] ) . toEqual ( { type : 'string' , value : 'embeddings' } ) ;
74+ expect ( thirdSpan ! . attributes [ 'sentry.op' ] ) . toEqual ( { type : 'string' , value : 'gen_ai.embeddings' } ) ;
75+ expect ( thirdSpan ! . attributes [ 'sentry.origin' ] ) . toEqual ( { type : 'string' , value : 'auto.ai.google_genai' } ) ;
76+ expect ( thirdSpan ! . attributes [ GEN_AI_SYSTEM_ATTRIBUTE ] ) . toEqual ( { type : 'string' , value : 'google_genai' } ) ;
77+ expect ( thirdSpan ! . attributes [ GEN_AI_REQUEST_MODEL_ATTRIBUTE ] ) . toEqual ( {
78+ type : 'string' ,
79+ value : 'text-embedding-004' ,
80+ } ) ;
8081 } )
81- . start ( ) ;
82+ . start ( signal ) ;
8283 await runner . makeRequest ( 'get' , '/' ) ;
8384 await runner . completed ( ) ;
8485} ) ;
0 commit comments