@@ -103,6 +103,56 @@ describe('shouldIgnoreSpan', () => {
103103 expect ( shouldIgnoreSpan ( { description : 'GET /health' , op : 'http.server' } , [ { op : 'http.server' } ] ) ) . toBe ( true ) ;
104104 } ) ;
105105
106+ describe ( 'attribute matching' , ( ) => {
107+ it . each ( [
108+ // strings: pattern matching (substring + regex)
109+ [ 'GET' , 'GE' , true ] ,
110+ [ 'GET' , 'POST' , false ] ,
111+ [ 'GET' , / ^ G E T $ / , true ] ,
112+ [ 'GET' , / ^ P O S T $ / , false ] ,
113+ // numbers: strict equality
114+ [ 200 , 200 , true ] ,
115+ [ 404 , 200 , false ] ,
116+ // booleans: strict equality
117+ [ true , true , true ] ,
118+ [ true , false , false ] ,
119+ // no type coercion across primitive types
120+ [ true , 'true' , false ] ,
121+ // arrays: element-wise strict equality (one positive per element type, plus mismatch shapes)
122+ [ [ 'a' , 'b' ] , [ 'a' , 'b' ] , true ] ,
123+ [ [ 'a' , 'b' ] , [ 'a' , 'c' ] , false ] ,
124+ [ [ 'a' , 'b' ] , [ 'a' ] , false ] ,
125+ [ [ 1 , 2 ] , [ 1 , 2 ] , true ] ,
126+ [ [ true , false ] , [ true , false ] , true ] ,
127+ ] ) ( 'matches attribute value %j against pattern %j → %s' , ( actual , pattern , expected ) => {
128+ const span = { description : 'span' , op : 'op' , attributes : { x : actual } } ;
129+ expect ( shouldIgnoreSpan ( span , [ { attributes : { x : pattern } } ] ) ) . toBe ( expected ) ;
130+ } ) ;
131+
132+ it ( 'does not match when the attribute key is absent on the span' , ( ) => {
133+ const span = { description : 'span' , op : 'op' , attributes : { } } ;
134+ expect ( shouldIgnoreSpan ( span , [ { attributes : { 'missing.key' : 'x' } } ] ) ) . toBe ( false ) ;
135+ } ) ;
136+
137+ it ( 'requires every attribute entry to match' , ( ) => {
138+ const span = { description : 'span' , op : 'op' , attributes : { a : 1 , b : 2 } } ;
139+ expect ( shouldIgnoreSpan ( span , [ { attributes : { a : 1 , b : 2 } } ] ) ) . toBe ( true ) ;
140+ expect ( shouldIgnoreSpan ( span , [ { attributes : { a : 1 , b : 3 } } ] ) ) . toBe ( false ) ;
141+ } ) ;
142+
143+ it ( 'requires both name and attributes to match' , ( ) => {
144+ const span = { description : 'GET /healthz' , op : 'http.server' , attributes : { 'http.method' : 'GET' } } ;
145+ expect ( shouldIgnoreSpan ( span , [ { name : / h e a l t h z ? / , attributes : { 'http.method' : 'GET' } } ] ) ) . toBe ( true ) ;
146+ expect ( shouldIgnoreSpan ( span , [ { name : / h e a l t h z ? / , attributes : { 'http.method' : 'POST' } } ] ) ) . toBe ( false ) ;
147+ expect ( shouldIgnoreSpan ( span , [ { name : / o t h e r / , attributes : { 'http.method' : 'GET' } } ] ) ) . toBe ( false ) ;
148+ } ) ;
149+
150+ it ( 'still matches an attribute-only filter on a span without a description' , ( ) => {
151+ const span = { description : undefined as unknown as string , op : undefined , attributes : { foo : 'bar' } } ;
152+ expect ( shouldIgnoreSpan ( span , [ { attributes : { foo : 'bar' } } ] ) ) . toBe ( true ) ;
153+ } ) ;
154+ } ) ;
155+
106156 it ( 'emits a debug log when a span is ignored' , ( ) => {
107157 const debugLogSpy = vi . spyOn ( debug , 'log' ) ;
108158 const span = { description : 'testDescription' , op : 'testOp' } ;
0 commit comments