@@ -648,4 +648,104 @@ describe('Trace', () => {
648648 assert . strictEqual ( linkFlags , 0x301 ) ; // TraceFlags (0x01) | HAS_IS_REMOTE | IS_REMOTE
649649 } ) ;
650650 } ) ;
651+
652+ describe ( 'span/link flags matrix' , ( ) => {
653+ const cases = [
654+ { tf : 0x00 , local : 0x100 , remote : 0x300 } ,
655+ { tf : 0x01 , local : 0x101 , remote : 0x301 } ,
656+ { tf : 0x05 , local : 0x105 , remote : 0x305 } ,
657+ { tf : 0xff , local : 0x1ff , remote : 0x3ff } ,
658+ ] ;
659+
660+ it ( 'composes span flags with local and remote parent across traceFlags' , ( ) => {
661+ const baseCtx = span . spanContext ( ) ;
662+ for ( const c of cases ) {
663+ // Local parent
664+ const spanLocal = {
665+ ...span ,
666+ spanContext : ( ) => ( {
667+ spanId : baseCtx . spanId ,
668+ traceId : baseCtx . traceId ,
669+ traceFlags : c . tf ,
670+ isRemote : false ,
671+ traceState : baseCtx . traceState ,
672+ } ) ,
673+ parentSpanContext : {
674+ ...span . parentSpanContext ,
675+ isRemote : false ,
676+ } ,
677+ } as unknown as ReadableSpan ;
678+ const reqLocal = createExportTraceServiceRequest ( [ spanLocal ] , { useHex : true } ) ;
679+ const spanFlagsLocal = reqLocal . resourceSpans ?. [ 0 ] . scopeSpans [ 0 ] . spans ?. [ 0 ] . flags ;
680+ assert . strictEqual ( spanFlagsLocal , c . local ) ;
681+
682+ // Remote parent
683+ const spanRemote = {
684+ ...spanLocal ,
685+ parentSpanContext : {
686+ ...span . parentSpanContext ,
687+ isRemote : true ,
688+ } ,
689+ } as unknown as ReadableSpan ;
690+ const reqRemote = createExportTraceServiceRequest ( [ spanRemote ] , { useHex : true } ) ;
691+ const spanFlagsRemote = reqRemote . resourceSpans ?. [ 0 ] . scopeSpans [ 0 ] . spans ?. [ 0 ] . flags ;
692+ assert . strictEqual ( spanFlagsRemote , c . remote ) ;
693+ }
694+ } ) ;
695+
696+ it ( 'composes link flags with local and remote context across traceFlags' , ( ) => {
697+ for ( const c of cases ) {
698+ const linkLocal = {
699+ context : {
700+ spanId : '0000000000000003' ,
701+ traceId : '00000000000000000000000000000002' ,
702+ traceFlags : c . tf ,
703+ isRemote : false ,
704+ traceState : new TraceState ( 'link=foo' ) ,
705+ } ,
706+ attributes : { 'link-attribute' : 'string value' } ,
707+ droppedAttributesCount : 0 ,
708+ } ;
709+ const spanWithLocalLink = {
710+ ...span ,
711+ links : [ linkLocal ] ,
712+ } as unknown as ReadableSpan ;
713+ const reqLocal = createExportTraceServiceRequest ( [ spanWithLocalLink ] , { useHex : true } ) ;
714+ const linkFlagsLocal = reqLocal . resourceSpans ?. [ 0 ] . scopeSpans [ 0 ] . spans ?. [ 0 ] . links ?. [ 0 ] . flags ;
715+ assert . strictEqual ( linkFlagsLocal , c . local ) ;
716+
717+ const linkRemote = {
718+ ...linkLocal ,
719+ context : { ...linkLocal . context , isRemote : true } ,
720+ } ;
721+ const spanWithRemoteLink = {
722+ ...span ,
723+ links : [ linkRemote ] ,
724+ } as unknown as ReadableSpan ;
725+ const reqRemote = createExportTraceServiceRequest ( [ spanWithRemoteLink ] , { useHex : true } ) ;
726+ const linkFlagsRemote = reqRemote . resourceSpans ?. [ 0 ] . scopeSpans [ 0 ] . spans ?. [ 0 ] . links ?. [ 0 ] . flags ;
727+ assert . strictEqual ( linkFlagsRemote , c . remote ) ;
728+ }
729+ } ) ;
730+
731+ it ( 'composes root span flags across traceFlags (no parent)' , ( ) => {
732+ const baseCtx = span . spanContext ( ) ;
733+ for ( const c of cases ) {
734+ const rootSpan = {
735+ ...span ,
736+ spanContext : ( ) => ( {
737+ spanId : baseCtx . spanId ,
738+ traceId : baseCtx . traceId ,
739+ traceFlags : c . tf ,
740+ isRemote : false ,
741+ traceState : baseCtx . traceState ,
742+ } ) ,
743+ parentSpanContext : undefined ,
744+ } as unknown as ReadableSpan ;
745+ const req = createExportTraceServiceRequest ( [ rootSpan ] , { useHex : true } ) ;
746+ const flags = req . resourceSpans ?. [ 0 ] . scopeSpans [ 0 ] . spans ?. [ 0 ] . flags ;
747+ assert . strictEqual ( flags , c . local ) ;
748+ }
749+ } ) ;
750+ } ) ;
651751} ) ;
0 commit comments