11package org .hypertrace .core .spannormalizer .jaeger ;
22
33import com .typesafe .config .Config ;
4- import io .jaegertracing .api_v2 .JaegerSpanInternalModel . KeyValue ;
4+ import io .jaegertracing .api_v2 .JaegerSpanInternalModel ;
55import java .util .Arrays ;
66import java .util .Collections ;
77import java .util .List ;
1111import javax .annotation .Nullable ;
1212import org .apache .commons .lang3 .StringUtils ;
1313import org .apache .commons .lang3 .tuple .Pair ;
14+ import org .hypertrace .core .span .constants .RawSpanConstants ;
15+ import org .hypertrace .core .span .constants .v1 .SpanAttribute ;
1416import org .slf4j .Logger ;
1517import org .slf4j .LoggerFactory ;
1618
1719public class SpanFilter {
18-
1920 private static final Logger LOG = LoggerFactory .getLogger (SpanFilter .class );
21+ private static final String SPAN_KIND_TAG =
22+ RawSpanConstants .getValue (SpanAttribute .SPAN_ATTRIBUTE_SPAN_KIND );
23+ private static final String SPAN_KIND_CLIENT = "client" ;
2024 /**
2125 * Config key using which a list of criterion can be specified to drop the matching spans. Any
2226 * span matching any one of the criterion is dropped. Each criteria is a comma separated list of
@@ -28,34 +32,69 @@ public class SpanFilter {
2832 */
2933 private static final String SPAN_DROP_CRITERION_CONFIG = "processor.spanDropCriterion" ;
3034
35+ public static final String ROOT_SPAN_DROP_CRITERION_CONFIG =
36+ "processor.rootExitSpanDropCriterion" ;
37+ private static final String ROOT_SPAN_ALWAYS_DROP = "alwaysDrop" ;
38+ private static final String ROOT_SPAN_DROP_EXCLUSIONS = "exclusionsMatchCriterion" ;
39+
3140 private static final String COMMA = "," ;
3241 private static final String COLON = ":" ;
3342
34- private final List <List <Pair <String , String >>> spanDropCriterion ;
43+ private List <List <Pair <String , String >>> spanDropCriterion = Collections .emptyList ();
44+ private boolean alwaysDropRootSpan = false ;
45+ private List <List <Pair <String , String >>> rootSpanDropExclusionCriterion = Collections .emptyList ();
3546
3647 public SpanFilter (Config config ) {
48+ if (config .hasPath (SPAN_DROP_CRITERION_CONFIG )) {
49+ List <String > criterion = config .getStringList (SPAN_DROP_CRITERION_CONFIG );
50+ LOG .info ("Span drop criterion: {}" , criterion );
51+ // Parse the config to see if there is any criteria to drop spans.
52+ this .spanDropCriterion = parseStringList (criterion );
53+ }
3754
38- List <String > criterion =
39- config .hasPath (SPAN_DROP_CRITERION_CONFIG )
40- ? config .getStringList (SPAN_DROP_CRITERION_CONFIG )
41- : Collections .emptyList ();
55+ if (config .hasPath (ROOT_SPAN_DROP_CRITERION_CONFIG )) {
56+ Config rootSpanDropCriterionConfig = config .getConfig (ROOT_SPAN_DROP_CRITERION_CONFIG );
57+ LOG .info ("Root Span drop criterion: {}" , rootSpanDropCriterionConfig );
58+ this .alwaysDropRootSpan =
59+ rootSpanDropCriterionConfig .hasPath (ROOT_SPAN_ALWAYS_DROP )
60+ && rootSpanDropCriterionConfig .getBoolean (ROOT_SPAN_ALWAYS_DROP );
61+ List <String > exclusionList =
62+ rootSpanDropCriterionConfig .hasPath (ROOT_SPAN_DROP_EXCLUSIONS )
63+ ? rootSpanDropCriterionConfig .getStringList (ROOT_SPAN_DROP_EXCLUSIONS )
64+ : Collections .emptyList ();
65+ // Parse the config to see if there is any criteria to drop spans.
66+ this .rootSpanDropExclusionCriterion = parseStringList (exclusionList );
67+ }
68+ }
4269
43- // Parse the config to see if there is any criteria to drop spans.
44- this . spanDropCriterion =
45- criterion . stream ()
46- // Split each criteria based on comma
47- .map (s -> s . split ( COMMA ))
48- . map (
49- a ->
50- Arrays . stream ( a )
51- . map ( this :: convertToPair )
52- . filter ( Objects :: nonNull )
53- .collect (Collectors .toList ()))
54- . collect ( Collectors . toList ());
70+ private List < List < Pair < String , String >>> parseStringList ( List < String > stringList ) {
71+ return stringList . stream ()
72+ // Split each criteria based on comma
73+ . map ( s -> s . split ( COMMA ))
74+ .map (
75+ a ->
76+ Arrays . stream ( a )
77+ . map ( this :: convertToPair )
78+ . filter ( Objects :: nonNull )
79+ . collect ( Collectors . toList ()) )
80+ .collect (Collectors .toList ());
81+ }
5582
56- if (!this .spanDropCriterion .isEmpty ()) {
57- LOG .info ("Span drop criterion: {}" , this .spanDropCriterion );
83+ /**
84+ * Method to check if the given span attributes match any of the drop criterion. Returns true if
85+ * the span should be dropped, false otherwise.
86+ */
87+ public boolean shouldDropSpan (
88+ JaegerSpanInternalModel .Span span , Map <String , JaegerSpanInternalModel .KeyValue > tags ) {
89+ if (anyCriteriaMatch (tags , spanDropCriterion )) {
90+ return true ;
5891 }
92+
93+ if (isRootExitSpan (span , tags )) {
94+ boolean anyCriteriaMatch = anyCriteriaMatch (tags , rootSpanDropExclusionCriterion );
95+ return (alwaysDropRootSpan && !anyCriteriaMatch ) || (!alwaysDropRootSpan && anyCriteriaMatch );
96+ }
97+ return false ;
5998 }
6099
61100 @ Nullable
@@ -69,12 +108,10 @@ private Pair<String, String> convertToPair(String s) {
69108 return null ;
70109 }
71110
72- /**
73- * Method to check if the given span attributes match any of the drop criterion. Returns true if
74- * the span should be dropped, false otherwise.
75- */
76- public boolean shouldDropSpan (Map <String , KeyValue > tags ) {
77- return this .spanDropCriterion .stream ()
111+ private boolean anyCriteriaMatch (
112+ Map <String , JaegerSpanInternalModel .KeyValue > tags ,
113+ List <List <Pair <String , String >>> criteriaList ) {
114+ return criteriaList .stream ()
78115 .anyMatch (
79116 l ->
80117 l .stream ()
@@ -84,4 +121,17 @@ public boolean shouldDropSpan(Map<String, KeyValue> tags) {
84121 && StringUtils .equals (
85122 tags .get (p .getLeft ()).getVStr (), p .getRight ())));
86123 }
124+
125+ private boolean isRootExitSpan (
126+ JaegerSpanInternalModel .Span span , Map <String , JaegerSpanInternalModel .KeyValue > tags ) {
127+ if (!span .getReferencesList ().isEmpty ()) {
128+ return false ;
129+ }
130+ JaegerSpanInternalModel .KeyValue spanKindKeyValue = tags .get (SPAN_KIND_TAG );
131+ if (null == spanKindKeyValue ) {
132+ return false ;
133+ }
134+
135+ return SPAN_KIND_CLIENT .equals (spanKindKeyValue .getVStr ());
136+ }
87137}
0 commit comments