@@ -15,6 +15,7 @@ import { withTelemetryContext } from '../../../shared/telemetry/util'
15
15
import { SinonSandbox } from 'sinon'
16
16
import sinon from 'sinon'
17
17
import { stubPerformance } from '../../utilities/performance'
18
+ import * as crypto from '../../../shared/crypto'
18
19
19
20
describe ( 'TelemetrySpan' , function ( ) {
20
21
let clock : ReturnType < typeof installFakeClock >
@@ -291,7 +292,17 @@ describe('TelemetryTracer', function () {
291
292
} )
292
293
293
294
describe ( 'nested run()' , function ( ) {
295
+ let uuidStub : sinon . SinonStub
294
296
const nestedName = 'nested_metric' as MetricName
297
+ const testId = 'foo-foo-foo-foo-foo'
298
+ const flowName = 'testTraceFlow'
299
+
300
+ beforeEach ( ( ) => {
301
+ uuidStub = sandbox . stub ( crypto , 'randomUUID' )
302
+
303
+ // in the first call we set the trace id in subsequent calls we get the span ids
304
+ uuidStub . returns ( testId )
305
+ } )
295
306
296
307
it ( 'can record metadata in nested spans' , function ( ) {
297
308
tracer . run ( metricName , ( span1 ) => {
@@ -310,18 +321,18 @@ describe('TelemetryTracer', function () {
310
321
it ( 'removes spans when exiting an execution context' , function ( ) {
311
322
tracer . run ( metricName , ( ) => {
312
323
tracer . run ( nestedName , ( ) => {
313
- assert . strictEqual ( tracer . spans . length , 2 )
324
+ assert . strictEqual ( tracer . spans . length , 3 )
314
325
} )
315
326
316
- assert . strictEqual ( tracer . spans . length , 1 )
327
+ assert . strictEqual ( tracer . spans . length , 2 )
317
328
} )
318
329
} )
319
330
320
331
it ( 'adds spans during a nested execution, closing them when after' , function ( ) {
321
332
tracer . run ( metricName , ( ) => {
322
- tracer . run ( nestedName , ( ) => assert . strictEqual ( tracer . spans . length , 2 ) )
323
- tracer . run ( nestedName , ( ) => assert . strictEqual ( tracer . spans . length , 2 ) )
324
- assert . strictEqual ( tracer . spans . length , 1 )
333
+ tracer . run ( nestedName , ( ) => assert . strictEqual ( tracer . spans . length , 3 ) )
334
+ tracer . run ( nestedName , ( ) => assert . strictEqual ( tracer . spans . length , 3 ) )
335
+ assert . strictEqual ( tracer . spans . length , 2 )
325
336
} )
326
337
327
338
assert . strictEqual ( tracer . spans . length , 0 )
@@ -330,16 +341,102 @@ describe('TelemetryTracer', function () {
330
341
it ( 'supports nesting the same event name' , function ( ) {
331
342
tracer . run ( metricName , ( ) => {
332
343
tracer . run ( metricName , ( ) => {
333
- assert . strictEqual ( tracer . spans . length , 2 )
334
- assert . ok ( tracer . spans . every ( ( s ) => s . name === metricName ) )
344
+ assert . strictEqual ( tracer . spans . length , 3 )
345
+ assert . ok ( tracer . spans . filter ( ( m ) => m . name !== 'root' ) . every ( ( s ) => s . name === metricName ) )
335
346
} )
336
347
} )
337
348
} )
338
349
339
- it ( 'attaches the parent event name to the child span' , function ( ) {
350
+ it ( 'attaches the parent id to the child span' , function ( ) {
340
351
tracer . run ( metricName , ( ) => tracer . run ( nestedName , ( ) => { } ) )
341
352
assertTelemetry ( metricName , { result : 'Succeeded' } )
342
- assertTelemetry ( nestedName , { result : 'Succeeded' , parentMetric : metricName } as any )
353
+ assertTelemetry ( nestedName , { result : 'Succeeded' , parentId : testId } as any )
354
+ } )
355
+
356
+ it ( 'should set trace id' , function ( ) {
357
+ telemetry . trace_event . run ( ( span ) => {
358
+ span . record ( { name : flowName } )
359
+ assert . deepStrictEqual ( telemetry . activeSpan ?. getMetricId ( ) , testId )
360
+ } )
361
+ const event = getMetrics ( 'trace_event' )
362
+ assert . deepStrictEqual ( event [ 0 ] . traceId , testId )
363
+ assert . deepStrictEqual ( event [ 0 ] . name , 'testTraceFlow' )
364
+ } )
365
+
366
+ it ( 'trace id is propogated to children' , function ( ) {
367
+ const metricsIds = {
368
+ trace_event : {
369
+ metricId : 'traceEvent' ,
370
+ traceId : testId ,
371
+ parentId : undefined ,
372
+ } ,
373
+ amazonq_startConversation : {
374
+ metricId : 'amazonq_startConversation' ,
375
+ traceId : testId ,
376
+ parentId : 'traceEvent' ,
377
+ } ,
378
+ amazonq_addMessage : {
379
+ metricId : 'amazonq_addMessage' ,
380
+ traceId : testId ,
381
+ parentId : 'amazonq_startConversation' ,
382
+ } ,
383
+ vscode_executeCommand : {
384
+ metricId : 'vscode_executeCommand' ,
385
+ traceId : testId ,
386
+ parentId : 'traceEvent' ,
387
+ } ,
388
+ amazonq_enterFocusConversation : {
389
+ metricId : 'amazonq_enterFocusConversation' ,
390
+ traceId : testId ,
391
+ parentId : 'vscode_executeCommand' ,
392
+ } ,
393
+ amazonq_exitFocusConversation : {
394
+ metricId : 'amazonq_exitFocusConversation' ,
395
+ traceId : testId ,
396
+ parentId : 'amazonq_enterFocusConversation' ,
397
+ } ,
398
+ amazonq_closeChat : {
399
+ metricId : 'amazonq_closeChat' ,
400
+ traceId : testId ,
401
+ parentId : 'traceEvent' ,
402
+ } ,
403
+ }
404
+
405
+ /**
406
+ * randomUUID calls:
407
+ * The first is called on the root event that never gets emitted
408
+ * The second is called when generating the traceId
409
+ * The rest are called when generating the spanIds
410
+ */
411
+ uuidStub . onCall ( 1 ) . returns ( testId )
412
+ let index = 2
413
+ for ( const v of Object . values ( metricsIds ) ) {
414
+ uuidStub . onCall ( index ) . returns ( v . metricId )
415
+ index ++
416
+ }
417
+
418
+ telemetry . trace_event . run ( ( ) => {
419
+ telemetry . amazonq_startConversation . run ( ( ) => {
420
+ telemetry . amazonq_addMessage . run ( ( ) => { } )
421
+ } )
422
+ telemetry . vscode_executeCommand . run ( ( ) => {
423
+ telemetry . amazonq_enterFocusConversation . run ( ( ) => {
424
+ telemetry . amazonq_exitFocusConversation . run ( ( ) => { } )
425
+ } )
426
+ } )
427
+ telemetry . amazonq_closeChat . emit ( {
428
+ result : 'Succeeded' ,
429
+ } )
430
+ } )
431
+
432
+ const spanEntries = Object . entries ( metricsIds )
433
+ for ( let x = 0 ; x < spanEntries . length ; x ++ ) {
434
+ const [ metricName , { metricId, traceId, parentId } ] = spanEntries [ x ]
435
+ const metric = getMetrics ( metricName as keyof MetricShapes ) [ 0 ] as any
436
+ assert . deepStrictEqual ( metric . traceId , traceId )
437
+ assert . deepStrictEqual ( metric . metricId , metricId )
438
+ assert . deepStrictEqual ( metric . parentId , parentId )
439
+ }
343
440
} )
344
441
} )
345
442
0 commit comments