11import { describe , expect , it } from 'vitest' ;
2- import {
3- SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT ,
4- SEMANTIC_ATTRIBUTE_SENTRY_OP ,
5- SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ,
6- SEMANTIC_ATTRIBUTE_SENTRY_RELEASE ,
7- SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME ,
8- SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION ,
9- SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID ,
10- SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME ,
11- SEMANTIC_ATTRIBUTE_USER_EMAIL ,
12- SEMANTIC_ATTRIBUTE_USER_ID ,
13- SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS ,
14- SEMANTIC_ATTRIBUTE_USER_USERNAME ,
15- } from '../../../../src' ;
16- import type { Event } from '../../../../src/types-hoist/event' ;
172import type { SpanJSON } from '../../../../src/types-hoist/span' ;
183import { spanJsonToSerializedStreamedSpan } from '../../../../src/tracing/spans/spanJsonToStreamedSpan' ;
19- import { getDefaultTestClientOptions , TestClient } from '../../../mocks/client' ;
204
215function makeSpanJSON ( overrides : Partial < SpanJSON > = { } ) : SpanJSON {
226 return {
@@ -28,31 +12,6 @@ function makeSpanJSON(overrides: Partial<SpanJSON> = {}): SpanJSON {
2812 } ;
2913}
3014
31- function makeTransactionEvent ( overrides : Partial < Event > = { } ) : Event {
32- return {
33- type : 'transaction' ,
34- transaction : 'GET /api/chat' ,
35- release : '1.0.0' ,
36- environment : 'production' ,
37- contexts : {
38- trace : {
39- span_id : 'root0000deadbeef' ,
40- trace_id : '00112233445566778899aabbccddeeff' ,
41- } ,
42- } ,
43- ...overrides ,
44- } ;
45- }
46-
47- function makeClient ( options : Partial < Parameters < typeof getDefaultTestClientOptions > [ 0 ] > = { } ) : TestClient {
48- return new TestClient (
49- getDefaultTestClientOptions ( {
50- dsn : 'https://dsn@ingest.f00.f00/1' ,
51- ...options ,
52- } ) ,
53- ) ;
54- }
55-
5615describe ( 'spanJsonToSerializedStreamedSpan' , ( ) => {
5716 it ( 'maps basic SpanJSON fields to StreamedSpan fields' , ( ) => {
5817 const span = makeSpanJSON ( {
@@ -64,7 +23,7 @@ describe('spanJsonToSerializedStreamedSpan', () => {
6423 parent_span_id : 'parent00deadbeef' ,
6524 } ) ;
6625
67- const result = spanJsonToSerializedStreamedSpan ( span , makeTransactionEvent ( ) , makeClient ( ) ) ;
26+ const result = spanJsonToSerializedStreamedSpan ( span ) ;
6827
6928 expect ( result . name ) . toBe ( 'chat gpt-4' ) ;
7029 expect ( result . start_timestamp ) . toBe ( 1000 ) ;
@@ -77,14 +36,12 @@ describe('spanJsonToSerializedStreamedSpan', () => {
7736 } ) ;
7837
7938 it ( 'uses empty string for name when description is undefined' , ( ) => {
80- const span = makeSpanJSON ( { description : undefined } ) ;
81- const result = spanJsonToSerializedStreamedSpan ( span , makeTransactionEvent ( ) , makeClient ( ) ) ;
39+ const result = spanJsonToSerializedStreamedSpan ( makeSpanJSON ( { description : undefined } ) ) ;
8240 expect ( result . name ) . toBe ( '' ) ;
8341 } ) ;
8442
8543 it ( 'uses start_timestamp as end_timestamp when timestamp is undefined' , ( ) => {
86- const span = makeSpanJSON ( { timestamp : undefined } ) ;
87- const result = spanJsonToSerializedStreamedSpan ( span , makeTransactionEvent ( ) , makeClient ( ) ) ;
44+ const result = spanJsonToSerializedStreamedSpan ( makeSpanJSON ( { timestamp : undefined } ) ) ;
8845 expect ( result . end_timestamp ) . toBe ( 1000 ) ;
8946 } ) ;
9047
@@ -99,24 +56,11 @@ describe('spanJsonToSerializedStreamedSpan', () => {
9956 ] ;
10057
10158 for ( const [ v1Status , expected ] of cases ) {
102- const span = makeSpanJSON ( { status : v1Status } ) ;
103- const result = spanJsonToSerializedStreamedSpan ( span , makeTransactionEvent ( ) , makeClient ( ) ) ;
59+ const result = spanJsonToSerializedStreamedSpan ( makeSpanJSON ( { status : v1Status } ) ) ;
10460 expect ( result . status ) . toBe ( expected ) ;
10561 }
10662 } ) ;
10763
108- it ( 'folds op and origin into attributes' , ( ) => {
109- const span = makeSpanJSON ( {
110- op : 'gen_ai.chat' ,
111- origin : 'auto.ai.openai' ,
112- } ) ;
113-
114- const result = spanJsonToSerializedStreamedSpan ( span , makeTransactionEvent ( ) , makeClient ( ) ) ;
115-
116- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] ) . toEqual ( { type : 'string' , value : 'gen_ai.chat' } ) ;
117- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] ) . toEqual ( { type : 'string' , value : 'auto.ai.openai' } ) ;
118- } ) ;
119-
12064 it ( 'preserves existing span data attributes' , ( ) => {
12165 const span = makeSpanJSON ( {
12266 data : {
@@ -127,111 +71,20 @@ describe('spanJsonToSerializedStreamedSpan', () => {
12771 } ,
12872 } ) ;
12973
130- const result = spanJsonToSerializedStreamedSpan ( span , makeTransactionEvent ( ) , makeClient ( ) ) ;
74+ const result = spanJsonToSerializedStreamedSpan ( span ) ;
13175
13276 expect ( result . attributes ?. [ 'gen_ai.system' ] ) . toEqual ( { type : 'string' , value : 'openai' } ) ;
13377 expect ( result . attributes ?. [ 'gen_ai.request.model' ] ) . toEqual ( { type : 'string' , value : 'gpt-4' } ) ;
13478 expect ( result . attributes ?. [ 'gen_ai.usage.input_tokens' ] ) . toEqual ( { type : 'integer' , value : 100 } ) ;
13579 expect ( result . attributes ?. [ 'gen_ai.usage.output_tokens' ] ) . toEqual ( { type : 'integer' , value : 50 } ) ;
13680 } ) ;
13781
138- it ( 'enriches with transaction event context' , ( ) => {
139- const span = makeSpanJSON ( ) ;
140- const event = makeTransactionEvent ( {
141- release : '2.0.0' ,
142- environment : 'staging' ,
143- transaction : 'POST /api/generate' ,
144- contexts : { trace : { span_id : 'segment0deadbeef' } } ,
145- } ) ;
146-
147- const result = spanJsonToSerializedStreamedSpan ( span , event , makeClient ( ) ) ;
148-
149- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_SENTRY_RELEASE ] ) . toEqual ( { type : 'string' , value : '2.0.0' } ) ;
150- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT ] ) . toEqual ( { type : 'string' , value : 'staging' } ) ;
151- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME ] ) . toEqual ( {
152- type : 'string' ,
153- value : 'POST /api/generate' ,
154- } ) ;
155- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID ] ) . toEqual ( {
156- type : 'string' ,
157- value : 'segment0deadbeef' ,
158- } ) ;
159- } ) ;
160-
161- it ( 'enriches with SDK metadata' , ( ) => {
162- const client = makeClient ( ) ;
163- client . getOptions ( ) . _metadata = { sdk : { name : 'sentry.javascript.node' , version : '9.0.0' } } ;
164-
165- const span = makeSpanJSON ( ) ;
166- const result = spanJsonToSerializedStreamedSpan ( span , makeTransactionEvent ( ) , client ) ;
167-
168- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME ] ) . toEqual ( {
169- type : 'string' ,
170- value : 'sentry.javascript.node' ,
171- } ) ;
172- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION ] ) . toEqual ( { type : 'string' , value : '9.0.0' } ) ;
173- } ) ;
174-
175- it ( 'adds user attributes when sendDefaultPii is true' , ( ) => {
176- const client = makeClient ( { sendDefaultPii : true } ) ;
177- const event = makeTransactionEvent ( {
178- user : { id : 'u123' , email : 'a@b.com' , ip_address : '1.2.3.4' , username : 'alice' } ,
179- } ) ;
180-
181- const span = makeSpanJSON ( ) ;
182- const result = spanJsonToSerializedStreamedSpan ( span , event , client ) ;
183-
184- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_USER_ID ] ) . toEqual ( { type : 'string' , value : 'u123' } ) ;
185- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_USER_EMAIL ] ) . toEqual ( { type : 'string' , value : 'a@b.com' } ) ;
186- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS ] ) . toEqual ( { type : 'string' , value : '1.2.3.4' } ) ;
187- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_USER_USERNAME ] ) . toEqual ( { type : 'string' , value : 'alice' } ) ;
188- } ) ;
189-
190- it ( 'does not add user attributes when sendDefaultPii is false' , ( ) => {
191- const client = makeClient ( { sendDefaultPii : false } ) ;
192- const event = makeTransactionEvent ( {
193- user : { id : 'u123' , email : 'a@b.com' } ,
194- } ) ;
195-
196- const span = makeSpanJSON ( ) ;
197- const result = spanJsonToSerializedStreamedSpan ( span , event , client ) ;
198-
199- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_USER_ID ] ) . toBeUndefined ( ) ;
200- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_USER_EMAIL ] ) . toBeUndefined ( ) ;
201- } ) ;
202-
203- it ( 'does not overwrite pre-existing span data attributes with enrichment' , ( ) => {
204- const span = makeSpanJSON ( {
205- data : {
206- [ SEMANTIC_ATTRIBUTE_SENTRY_RELEASE ] : 'span-level-release' ,
207- [ SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT ] : 'span-level-env' ,
208- } ,
209- } ) ;
210-
211- const event = makeTransactionEvent ( {
212- release : 'event-level-release' ,
213- environment : 'event-level-env' ,
214- } ) ;
215-
216- const result = spanJsonToSerializedStreamedSpan ( span , event , makeClient ( ) ) ;
217-
218- // Span-level values should win
219- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_SENTRY_RELEASE ] ) . toEqual ( {
220- type : 'string' ,
221- value : 'span-level-release' ,
222- } ) ;
223- expect ( result . attributes ?. [ SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT ] ) . toEqual ( {
224- type : 'string' ,
225- value : 'span-level-env' ,
226- } ) ;
227- } ) ;
228-
22982 it ( 'carries over links' , ( ) => {
23083 const span = makeSpanJSON ( {
23184 links : [ { trace_id : 'aabb' , span_id : 'ccdd' , sampled : true , attributes : { foo : 'bar' } } ] ,
23285 } ) ;
23386
234- const result = spanJsonToSerializedStreamedSpan ( span , makeTransactionEvent ( ) , makeClient ( ) ) ;
87+ const result = spanJsonToSerializedStreamedSpan ( span ) ;
23588
23689 expect ( result . links ) . toEqual ( [
23790 { trace_id : 'aabb' , span_id : 'ccdd' , sampled : true , attributes : { foo : { type : 'string' , value : 'bar' } } } ,
0 commit comments