@@ -37,6 +37,9 @@ const {
3737
3838const { ObservabilityOptions} = require ( '../src/instrument' ) ;
3939
40+ const selectSql = 'SELECT 1' ;
41+ const updateSql = 'UPDATE FOO SET BAR=1 WHERE BAZ=2' ;
42+
4043/** A simple result set for SELECT 1. */
4144function createSelect1ResultSet ( ) : protobuf . ResultSet {
4245 const fields = [
@@ -85,8 +88,6 @@ async function setup(
8588 ) ;
8689 } ) ;
8790
88- const selectSql = 'SELECT 1' ;
89- const updateSql = 'UPDATE FOO SET BAR=1 WHERE BAZ=2' ;
9091 spannerMock . putStatementResult (
9192 selectSql ,
9293 mock . StatementResult . resultSet ( createSelect1ResultSet ( ) )
@@ -205,7 +206,6 @@ describe('EndToEnd', () => {
205206
206207 traceExporter . forceFlush ( ) ;
207208 const spans = traceExporter . getFinishedSpans ( ) ;
208- assert . strictEqual ( spans . length , 1 , 'Exactly 1 span expected' ) ;
209209
210210 const actualSpanNames : string [ ] = [ ] ;
211211 const actualEventNames : string [ ] = [ ] ;
@@ -216,14 +216,19 @@ describe('EndToEnd', () => {
216216 } ) ;
217217 } ) ;
218218
219- const expectedSpanNames = [ 'CloudSpanner.Database.getSnapshot' ] ;
219+ const expectedSpanNames = [
220+ 'CloudSpanner.Snapshot.begin' ,
221+ 'CloudSpanner.Database.getSnapshot' ,
222+ 'CloudSpanner.Snapshot.runStream' ,
223+ 'CloudSpanner.Snapshot.run' ,
224+ ] ;
220225 assert . deepStrictEqual (
221226 actualSpanNames ,
222227 expectedSpanNames ,
223228 `span names mismatch:\n\tGot: ${ actualSpanNames } \n\tWant: ${ expectedSpanNames } `
224229 ) ;
225230
226- const expectedEventNames = [ ] ;
231+ const expectedEventNames = [ 'Begin Transaction' ] ;
227232 assert . deepStrictEqual (
228233 actualEventNames ,
229234 expectedEventNames ,
@@ -279,7 +284,6 @@ describe('EndToEnd', () => {
279284 . on ( 'end' , ( ) => {
280285 traceExporter . forceFlush ( ) ;
281286 const spans = traceExporter . getFinishedSpans ( ) ;
282- assert . strictEqual ( spans . length , 1 , 'Exactly 1 span expected' ) ;
283287
284288 const actualSpanNames : string [ ] = [ ] ;
285289 const actualEventNames : string [ ] = [ ] ;
@@ -290,7 +294,10 @@ describe('EndToEnd', () => {
290294 } ) ;
291295 } ) ;
292296
293- const expectedSpanNames = [ 'CloudSpanner.Database.runStream' ] ;
297+ const expectedSpanNames = [
298+ 'CloudSpanner.Snapshot.runStream' ,
299+ 'CloudSpanner.Database.runStream' ,
300+ ] ;
294301 assert . deepStrictEqual (
295302 actualSpanNames ,
296303 expectedSpanNames ,
@@ -313,7 +320,6 @@ describe('EndToEnd', () => {
313320
314321 traceExporter . forceFlush ( ) ;
315322 const spans = traceExporter . getFinishedSpans ( ) ;
316- assert . strictEqual ( spans . length , 2 , 'Exactly 2 spans expected' ) ;
317323
318324 // Sort the spans by duration.
319325 spans . sort ( ( spanA , spanB ) => {
@@ -330,6 +336,7 @@ describe('EndToEnd', () => {
330336 } ) ;
331337
332338 const expectedSpanNames = [
339+ 'CloudSpanner.Snapshot.runStream' ,
333340 'CloudSpanner.Database.runStream' ,
334341 'CloudSpanner.Database.run' ,
335342 ] ;
@@ -375,7 +382,6 @@ describe('EndToEnd', () => {
375382
376383 traceExporter . forceFlush ( ) ;
377384 const spans = traceExporter . getFinishedSpans ( ) ;
378- assert . strictEqual ( spans . length , 1 , 'Exactly 1 span expected' ) ;
379385
380386 const actualEventNames : string [ ] = [ ] ;
381387 const actualSpanNames : string [ ] = [ ] ;
@@ -386,7 +392,11 @@ describe('EndToEnd', () => {
386392 } ) ;
387393 } ) ;
388394
389- const expectedSpanNames = [ 'CloudSpanner.Database.runTransaction' ] ;
395+ const expectedSpanNames = [
396+ 'CloudSpanner.Database.runTransaction' ,
397+ 'CloudSpanner.Snapshot.runStream' ,
398+ 'CloudSpanner.Snapshot.run' ,
399+ ] ;
390400 assert . deepStrictEqual (
391401 actualSpanNames ,
392402 expectedSpanNames ,
@@ -413,7 +423,6 @@ describe('EndToEnd', () => {
413423
414424 traceExporter . forceFlush ( ) ;
415425 const spans = traceExporter . getFinishedSpans ( ) ;
416- assert . strictEqual ( spans . length , 1 , 'Exactly 1 span expected' ) ;
417426
418427 const actualEventNames : string [ ] = [ ] ;
419428 const actualSpanNames : string [ ] = [ ] ;
@@ -424,14 +433,21 @@ describe('EndToEnd', () => {
424433 } ) ;
425434 } ) ;
426435
427- const expectedSpanNames = [ 'CloudSpanner.Database.writeAtLeastOnce' ] ;
436+ const expectedSpanNames = [
437+ 'CloudSpanner.Transaction.commit' ,
438+ 'CloudSpanner.Database.writeAtLeastOnce' ,
439+ ] ;
428440 assert . deepStrictEqual (
429441 actualSpanNames ,
430442 expectedSpanNames ,
431443 `span names mismatch:\n\tGot: ${ actualSpanNames } \n\tWant: ${ expectedSpanNames } `
432444 ) ;
433445
434- const expectedEventNames = [ 'Using Session' ] ;
446+ const expectedEventNames = [
447+ 'Starting Commit' ,
448+ 'Commit Done' ,
449+ 'Using Session' ,
450+ ] ;
435451 assert . deepStrictEqual (
436452 actualEventNames ,
437453 expectedEventNames ,
@@ -522,6 +538,226 @@ describe('ObservabilityOptions injection and propagation', async () => {
522538 done ( ) ;
523539 } ) ;
524540
541+ afterEach ( async ( ) => {
542+ await injectedTracerProvider . forceFlush ( ) ;
543+ injectedTraceExporter . reset ( ) ;
544+ } ) ;
545+
546+ let database : Database ;
547+ beforeEach ( ( ) => {
548+ const instance = spanner . instance ( 'instance' ) ;
549+ database = instance . database ( 'db' ) ;
550+ } ) ;
551+
552+ describe ( 'Transaction' , ( ) => {
553+ const traceExporter = injectedTraceExporter ;
554+
555+ it ( 'run' , done => {
556+ database . getTransaction ( ( err , tx ) => {
557+ assert . ifError ( err ) ;
558+
559+ tx ! . run ( 'SELECT 1' , ( err , rows ) => {
560+ traceExporter . forceFlush ( ) ;
561+
562+ const spans = traceExporter . getFinishedSpans ( ) ;
563+
564+ const actualSpanNames : string [ ] = [ ] ;
565+ const actualEventNames : string [ ] = [ ] ;
566+ spans . forEach ( span => {
567+ actualSpanNames . push ( span . name ) ;
568+ span . events . forEach ( event => {
569+ actualEventNames . push ( event . name ) ;
570+ } ) ;
571+ } ) ;
572+
573+ const expectedSpanNames = [
574+ 'CloudSpanner.Database.getTransaction' ,
575+ 'CloudSpanner.Snapshot.runStream' ,
576+ 'CloudSpanner.Snapshot.run' ,
577+ ] ;
578+ assert . deepStrictEqual (
579+ actualSpanNames ,
580+ expectedSpanNames ,
581+ `span names mismatch:\n\tGot: ${ actualSpanNames } \n\tWant: ${ expectedSpanNames } `
582+ ) ;
583+
584+ const expectedEventNames = [
585+ 'Requesting 25 sessions' ,
586+ 'Creating 25 sessions' ,
587+ 'Requested for 25 sessions returned 25' ,
588+ 'Acquiring session' ,
589+ 'Waiting for a session to become available' ,
590+ 'Acquired session' ,
591+ 'Using Session' ,
592+ 'Transaction Creation Done' ,
593+ ] ;
594+ assert . strictEqual (
595+ actualEventNames . every ( value => expectedEventNames . includes ( value ) ) ,
596+ true ,
597+ `Unexpected events:\n\tGot: ${ actualEventNames } \n\tWant: ${ expectedEventNames } `
598+ ) ;
599+
600+ done ( ) ;
601+ } ) ;
602+ } ) ;
603+ } ) ;
604+
605+ it ( 'Transaction.begin+Dml.runUpdate' , done => {
606+ database . getTransaction ( ( err , tx ) => {
607+ assert . ifError ( err ) ;
608+
609+ // Firstly erase the prior spans so that we can have only Transaction spans.
610+ traceExporter . reset ( ) ;
611+
612+ tx ! . begin ( ) ;
613+ tx ! . runUpdate ( updateSql , ( err , rowCount ) => {
614+ assert . ifError ( err ) ;
615+
616+ traceExporter . forceFlush ( ) ;
617+
618+ const spans = traceExporter . getFinishedSpans ( ) ;
619+ assert . strictEqual ( spans . length , 4 ) ;
620+
621+ const actualSpanNames : string [ ] = [ ] ;
622+ const actualEventNames : string [ ] = [ ] ;
623+ spans . forEach ( span => {
624+ actualSpanNames . push ( span . name ) ;
625+ span . events . forEach ( event => {
626+ actualEventNames . push ( event . name ) ;
627+ } ) ;
628+ } ) ;
629+
630+ const expectedSpanNames = [
631+ 'CloudSpanner.Snapshot.begin' ,
632+ 'CloudSpanner.Snapshot.runStream' ,
633+ 'CloudSpanner.Snapshot.run' ,
634+ 'CloudSpanner.Dml.runUpdate' ,
635+ ] ;
636+ assert . deepStrictEqual (
637+ actualSpanNames ,
638+ expectedSpanNames ,
639+ `span names mismatch:\n\tGot: ${ actualSpanNames } \n\tWant: ${ expectedSpanNames } `
640+ ) ;
641+
642+ const expectedEventNames = [
643+ 'Begin Transaction' ,
644+ 'Transaction Creation Done' ,
645+ ] ;
646+ assert . strictEqual (
647+ actualEventNames . every ( value => expectedEventNames . includes ( value ) ) ,
648+ true ,
649+ `Unexpected events:\n\tGot: ${ actualEventNames } \n\tWant: ${ expectedEventNames } `
650+ ) ;
651+
652+ done ( ) ;
653+ } ) ;
654+ } ) ;
655+ } ) ;
656+
657+ it ( 'runStream' , done => {
658+ let rowCount = 0 ;
659+ database . getTransaction ( ( err , tx ) => {
660+ assert . ifError ( err ) ;
661+ tx !
662+ . runStream ( selectSql )
663+ . on ( 'data' , ( ) => rowCount ++ )
664+ . on ( 'error' , assert . ifError )
665+ . on ( 'stats' , _stats => { } )
666+ . on ( 'end' , ( ) => {
667+ tx ! . end ( ) ;
668+
669+ traceExporter . forceFlush ( ) ;
670+
671+ const spans = traceExporter . getFinishedSpans ( ) ;
672+
673+ const actualSpanNames : string [ ] = [ ] ;
674+ const actualEventNames : string [ ] = [ ] ;
675+ spans . forEach ( span => {
676+ actualSpanNames . push ( span . name ) ;
677+ span . events . forEach ( event => {
678+ actualEventNames . push ( event . name ) ;
679+ } ) ;
680+ } ) ;
681+
682+ const expectedSpanNames = [
683+ 'CloudSpanner.Database.getTransaction' ,
684+ 'CloudSpanner.Snapshot.runStream' ,
685+ ] ;
686+ assert . deepStrictEqual (
687+ actualSpanNames ,
688+ expectedSpanNames ,
689+ `span names mismatch:\n\tGot: ${ actualSpanNames } \n\tWant: ${ expectedSpanNames } `
690+ ) ;
691+
692+ const expectedEventNames = [ 'Using Session' ] ;
693+ assert . deepStrictEqual (
694+ actualEventNames ,
695+ expectedEventNames ,
696+ `Unexpected events:\n\tGot: ${ actualEventNames } \n\tWant: ${ expectedEventNames } `
697+ ) ;
698+
699+ done ( ) ;
700+ } ) ;
701+ } ) ;
702+ } ) ;
703+
704+ it ( 'rollback' , done => {
705+ database . getTransaction ( ( err , tx ) => {
706+ assert . ifError ( err ) ;
707+
708+ // Firstly erase the prior spans so that we can have only Transaction spans.
709+ traceExporter . reset ( ) ;
710+
711+ tx ! . begin ( ) ;
712+
713+ tx ! . runUpdate ( updateSql , async ( err , rowCount ) => {
714+ assert . ifError ( err ) ;
715+ tx ! . rollback ( err => {
716+ traceExporter . forceFlush ( ) ;
717+
718+ const spans = traceExporter . getFinishedSpans ( ) ;
719+
720+ const actualSpanNames : string [ ] = [ ] ;
721+ const actualEventNames : string [ ] = [ ] ;
722+ spans . forEach ( span => {
723+ actualSpanNames . push ( span . name ) ;
724+ span . events . forEach ( event => {
725+ actualEventNames . push ( event . name ) ;
726+ } ) ;
727+ } ) ;
728+
729+ const expectedSpanNames = [
730+ 'CloudSpanner.Snapshot.begin' ,
731+ 'CloudSpanner.Snapshot.runStream' ,
732+ 'CloudSpanner.Snapshot.run' ,
733+ 'CloudSpanner.Dml.runUpdate' ,
734+ 'CloudSpanner.Transaction.rollback' ,
735+ ] ;
736+ assert . deepStrictEqual (
737+ actualSpanNames ,
738+ expectedSpanNames ,
739+ `span names mismatch:\n\tGot: ${ actualSpanNames } \n\tWant: ${ expectedSpanNames } `
740+ ) ;
741+
742+ const expectedEventNames = [
743+ 'Begin Transaction' ,
744+ 'Transaction Creation Done' ,
745+ ] ;
746+ assert . strictEqual (
747+ actualEventNames . every ( value =>
748+ expectedEventNames . includes ( value )
749+ ) ,
750+ true ,
751+ `Unexpected events:\n\tGot: ${ actualEventNames } \n\tWant: ${ expectedEventNames } `
752+ ) ;
753+
754+ done ( ) ;
755+ } ) ;
756+ } ) ;
757+ } ) ;
758+ } ) ;
759+ } ) ;
760+
525761 it ( 'Propagates spans to the injected not global TracerProvider' , done => {
526762 const instance = spanner . instance ( 'instance' ) ;
527763 const database = instance . database ( 'database' ) ;
@@ -558,6 +794,7 @@ describe('ObservabilityOptions injection and propagation', async () => {
558794 } ) ;
559795
560796 const expectedSpanNames = [
797+ 'CloudSpanner.Snapshot.runStream' ,
561798 'CloudSpanner.Database.runStream' ,
562799 'CloudSpanner.Database.run' ,
563800 ] ;
0 commit comments