From 89c99cb264802f8eca082939b135a1744d9c506e Mon Sep 17 00:00:00 2001 From: Ronak Date: Thu, 18 Nov 2021 20:58:09 +0530 Subject: [PATCH 1/5] feat: enhance the support for dropping filter --- .../spannormalizer/jaeger/SpanDropFilter.java | 47 +++++++ .../spannormalizer/jaeger/SpanFilter.java | 64 +++++++++ .../spannormalizer/SpanNormalizerTest.java | 72 ++++++++++ .../jaeger/JaegerSpanPreProcessorTest.java | 132 +++++++++++++++++- .../configs/span-normalizer/application.conf | 24 ++++ 5 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanDropFilter.java diff --git a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanDropFilter.java b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanDropFilter.java new file mode 100644 index 000000000..789ef67e8 --- /dev/null +++ b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanDropFilter.java @@ -0,0 +1,47 @@ +package org.hypertrace.core.spannormalizer.jaeger; + +public class SpanDropFilter { + + public static final String TAG_KEY = "tagKey"; + public static final String OPERATOR = "operator"; + public static final String TAG_VALUE = "tagValue"; + + public enum Operator { + EQ("EQ"), + NEQ("NEQ"), + EXISTS("EXISTS"), + CONTAINS("CONTAINS"); + + private final String value; + + Operator(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + private String tagKey; + private Operator operator; + private String tagValue; + + public SpanDropFilter(String tagKey, String operator, String tagValue) { + this.tagKey = tagKey; + this.operator = Operator.valueOf(operator); + this.tagValue = tagValue; + } + + public String getTagKey() { + return tagKey; + } + + public Operator getOperator() { + return operator; + } + + public String getTagValue() { + return tagValue; + } +} diff --git a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java index b5511b44f..44d668ae4 100644 --- a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java +++ b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java @@ -1,10 +1,15 @@ package org.hypertrace.core.spannormalizer.jaeger; +import static org.hypertrace.core.spannormalizer.jaeger.SpanDropFilter.OPERATOR; +import static org.hypertrace.core.spannormalizer.jaeger.SpanDropFilter.TAG_KEY; +import static org.hypertrace.core.spannormalizer.jaeger.SpanDropFilter.TAG_VALUE; + import com.google.common.util.concurrent.RateLimiter; import com.typesafe.config.Config; import io.jaegertracing.api_v2.JaegerSpanInternalModel; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -35,6 +40,8 @@ public class SpanFilter { */ private static final String SPAN_DROP_CRITERION_CONFIG = "processor.spanDropCriterion"; + private static final String SPAN_DROP_FILTERS = "processor.spanDropFilters"; + public static final String ROOT_SPAN_DROP_CRITERION_CONFIG = "processor.rootExitSpanDropCriterion"; private static final String ROOT_SPAN_ALWAYS_DROP = "alwaysDrop"; @@ -44,6 +51,8 @@ public class SpanFilter { private static final String COLON = ":"; private List>> spanDropCriterion = Collections.emptyList(); + private List> spanDropFilters = Collections.emptyList(); + ; private boolean alwaysDropRootSpan = false; private List>> rootSpanDropExclusionCriterion = Collections.emptyList(); @@ -55,6 +64,26 @@ public SpanFilter(Config config) { this.spanDropCriterion = parseStringList(criterion); } + if (config.hasPath(SPAN_DROP_FILTERS)) { + this.spanDropFilters = + config.getList(SPAN_DROP_FILTERS).stream() + .map( + orFilters -> { + List> andFilters = + (List>) orFilters.unwrapped(); + return andFilters.stream() + .map( + filter -> + new SpanDropFilter( + filter.get(TAG_KEY), + filter.get(OPERATOR), + filter.get(TAG_VALUE))) + .collect(Collectors.toList()); + }) + .collect(Collectors.toList()); + LOG.info("Json String for Span drop criterion: {}", this.spanDropFilters); + } + if (config.hasPath(ROOT_SPAN_DROP_CRITERION_CONFIG)) { Config rootSpanDropCriterionConfig = config.getConfig(ROOT_SPAN_DROP_CRITERION_CONFIG); LOG.info("Root Span drop criterion: {}", rootSpanDropCriterionConfig); @@ -96,6 +125,13 @@ public boolean shouldDropSpan( return true; } + if (anySpanDropFiltersMatch(spanDropFilters, tags)) { + if (DROPPED_SPANS_RATE_LIMITER.tryAcquire()) { + LOG.info("Dropping span: [{}] with drop filters: [{}]", span, spanDropFilters); + } + return true; + } + if (isRootExitSpan(span, tags)) { boolean anyCriteriaMatch = anyCriteriaMatch(tags, rootSpanDropExclusionCriterion); boolean shouldDropSpan = @@ -149,4 +185,32 @@ private boolean isRootExitSpan( return SPAN_KIND_CLIENT.equals(spanKindKeyValue.getVStr()); } + + private boolean anySpanDropFiltersMatch( + List> spanDropFilters, + Map tags) { + return spanDropFilters.stream() + .anyMatch( + andFilters -> + andFilters.stream().allMatch(filter -> matchSpanDropFilter(filter, tags))); + } + + private boolean matchSpanDropFilter( + SpanDropFilter filter, Map tags) { + switch (filter.getOperator()) { + case EQ: + return tags.containsKey(filter.getTagKey()) + && StringUtils.equals(tags.get(filter.getTagKey()).getVStr(), filter.getTagValue()); + case NEQ: + return tags.containsKey(filter.getTagKey()) + && !StringUtils.equals(tags.get(filter.getTagKey()).getVStr(), filter.getTagValue()); + case CONTAINS: + return tags.containsKey(filter.getTagKey()) + && StringUtils.contains(tags.get(filter.getTagKey()).getVStr(), filter.getTagValue()); + case EXISTS: + return tags.containsKey(filter.getTagKey()); + default: + return false; + } + } } diff --git a/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/SpanNormalizerTest.java b/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/SpanNormalizerTest.java index 1c0dc513a..86aab7a4f 100644 --- a/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/SpanNormalizerTest.java +++ b/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/SpanNormalizerTest.java @@ -1,6 +1,8 @@ package org.hypertrace.core.spannormalizer; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.protobuf.ByteString; import com.google.protobuf.Timestamp; @@ -130,5 +132,75 @@ public void whenJaegerSpansAreProcessedExpectRawSpansToBeOutput() { KeyValue keyValue = rawLogOutputTopic.readKeyValue(); LogEvents logEvents = keyValue.value; Assertions.assertEquals(2, logEvents.getLogEvents().size()); + + // pipe in one more span which doesn't match spanDropFilters + Span span2 = + Span.newBuilder() + .setSpanId(ByteString.copyFrom("2".getBytes())) + .setTraceId(ByteString.copyFrom("trace-2".getBytes())) + .addTags( + JaegerSpanInternalModel.KeyValue.newBuilder() + .setKey("jaeger.servicename") + .setVStr(SERVICE_NAME) + .build()) + .addTags( + JaegerSpanInternalModel.KeyValue.newBuilder() + .setKey("http.method") + .setVStr("GET") + .build()) + .build(); + + inputTopic.pipeInput(span2); + KeyValue kv1 = outputTopic.readKeyValue(); + assertNotNull(kv1); + assertEquals("__default", kv1.key.getTenantId()); + assertEquals( + HexUtils.getHex(ByteString.copyFrom("trace-2".getBytes()).toByteArray()), + HexUtils.getHex(kv1.key.getTraceId().array())); + + // pipe in one more span which match one of spanDropFilters (http.method & http.url) + Span span3 = + Span.newBuilder() + .setSpanId(ByteString.copyFrom("3".getBytes())) + .setTraceId(ByteString.copyFrom("trace-3".getBytes())) + .addTags( + JaegerSpanInternalModel.KeyValue.newBuilder() + .setKey("jaeger.servicename") + .setVStr(SERVICE_NAME) + .build()) + .addTags( + JaegerSpanInternalModel.KeyValue.newBuilder() + .setKey("http.method") + .setVStr("GET") + .build()) + .addTags( + JaegerSpanInternalModel.KeyValue.newBuilder() + .setKey("http.url") + .setVStr("http://xyz.com/health/check") + .build()) + .build(); + + inputTopic.pipeInput(span3); + assertTrue(outputTopic.isEmpty()); + + // pipe in one more span which match one of spanDropFilters (grpc.url) + Span span4 = + Span.newBuilder() + .setSpanId(ByteString.copyFrom("3".getBytes())) + .setTraceId(ByteString.copyFrom("trace-3".getBytes())) + .addTags( + JaegerSpanInternalModel.KeyValue.newBuilder() + .setKey("jaeger.servicename") + .setVStr(SERVICE_NAME) + .build()) + .addTags( + JaegerSpanInternalModel.KeyValue.newBuilder() + .setKey("grpc.url") + .setVStr("doesn't match with input filter set") + .build()) + .build(); + + inputTopic.pipeInput(span4); + assertTrue(outputTopic.isEmpty()); } } diff --git a/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessorTest.java b/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessorTest.java index ce3657b8d..deb8c3a1f 100644 --- a/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessorTest.java +++ b/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessorTest.java @@ -1,5 +1,7 @@ package org.hypertrace.core.spannormalizer.jaeger; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.typesafe.config.ConfigFactory; import io.jaegertracing.api_v2.JaegerSpanInternalModel.KeyValue; import io.jaegertracing.api_v2.JaegerSpanInternalModel.Process; @@ -19,7 +21,7 @@ class JaegerSpanPreProcessorTest { @Test void testPreProcessSpan_missingTenantId() { - Assertions.assertThrows( + assertThrows( RuntimeException.class, () -> { // span dropped since tenant detail not present @@ -364,6 +366,134 @@ public void testDropSpan_RootSpan_NotAlwaysDrop_ExclusionList() { Assertions.assertNotNull(preProcessedSpan); } + @Test + public void testSpanDropFilters() { + String tenantId = "tenant-" + random.nextLong(); + Map configs = new HashMap<>(getCommonConfig()); + configs.putAll( + Map.of( + "processor", + Map.of( + "tenantIdTagKey", + "tenant-key", + "spanDropFilters", + List.of( + List.of( + Map.of("tagKey", "http.method", "operator", "EQ", "tagValue", "GET"), + Map.of("tagKey", "http.url", "operator", "CONTAINS", "tagValue", "health")), + List.of( + Map.of( + "tagKey", "grpc.url", + "operator", "EXISTS", + "tagValue", "Sent.TestGrpcService.GetEcho"), + Map.of("tagKey", "http.method", "operator", "EQ", "tagValue", "POST")), + List.of( + Map.of( + "tagKey", "http.status_code", + "operator", "NEQ", + "tagValue", "200")))))); + JaegerSpanPreProcessor jaegerSpanPreProcessor = + new JaegerSpanPreProcessor(ConfigFactory.parseMap(configs)); + Process process = Process.newBuilder().setServiceName("testService").build(); + + // case 1: match first case (http.method & http.url) + Span span = + Span.newBuilder() + .setProcess(process) + .addTags(KeyValue.newBuilder().setKey("tenant-key").setVStr(tenantId).build()) + .addTags(KeyValue.newBuilder().setKey("http.method").setVStr("GET").build()) + .addTags( + KeyValue.newBuilder() + .setKey("http.url") + .setVStr("http://xyz.com/api/v1/health/check") + .build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + PreProcessedSpan preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNull(preProcessedSpan); + + // case 2: match second case (grpc.url & http.method) + span = + Span.newBuilder() + .setProcess(process) + .addTags(KeyValue.newBuilder().setKey("tenant-key").setVStr(tenantId).build()) + .addTags(KeyValue.newBuilder().setKey("http.method").setVStr("POST").build()) + .addTags( + KeyValue.newBuilder() + .setKey("grpc.url") + .setVStr("Sent.TestGrpcService.GetEcho.Extra") + .build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNull(preProcessedSpan); + + // case 3: match third case (http.status_code) + span = + Span.newBuilder() + .setProcess(process) + .addTags(KeyValue.newBuilder().setKey("tenant-key").setVStr(tenantId).build()) + .addTags(KeyValue.newBuilder().setKey("http.status_code").setVStr("500").build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNull(preProcessedSpan); + + // case 4 : match no filters but key exists, but value doesn't match + span = + Span.newBuilder() + .setProcess(process) + .addTags(KeyValue.newBuilder().setKey("tenant-key").setVStr(tenantId).build()) + .addTags(KeyValue.newBuilder().setKey("http.method").setVStr("GET").build()) + .addTags( + KeyValue.newBuilder() + .setKey("http.url") + .setVStr("http://xyz.com/api/v1/check") + .build()) + .addTags(KeyValue.newBuilder().setKey("http.status_code").setVStr("200").build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNotNull(preProcessedSpan); + + // case 4 : match no filters, no key exists + span = + Span.newBuilder() + .setProcess(process) + .addTags(KeyValue.newBuilder().setKey("tenant-key").setVStr(tenantId).build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNotNull(preProcessedSpan); + } + + @Test + public void testSpanDropFiltersBadConfig() { + assertThrows( + IllegalArgumentException.class, + () -> { + Map configs = new HashMap<>(getCommonConfig()); + configs.putAll( + Map.of( + "processor", + Map.of( + "tenantIdTagKey", + "tenant-key", + "spanDropFilters", + List.of( + List.of( + Map.of( + "tagKey", + "http.method", + "operator", + "EQUAL", + "tagValue", + "GET")))))); + JaegerSpanPreProcessor jaegerSpanPreProcessor = + new JaegerSpanPreProcessor(ConfigFactory.parseMap(configs)); + }); + } + private Map getCommonConfig() { return Map.of( "span.type", diff --git a/span-normalizer/span-normalizer/src/test/resources/configs/span-normalizer/application.conf b/span-normalizer/span-normalizer/src/test/resources/configs/span-normalizer/application.conf index ffb1b2cfc..5e95ca97a 100644 --- a/span-normalizer/span-normalizer/src/test/resources/configs/span-normalizer/application.conf +++ b/span-normalizer/span-normalizer/src/test/resources/configs/span-normalizer/application.conf @@ -27,3 +27,27 @@ processor { defaultTenantId = "__default" } +processor { + spanDropFilters = [ + [ + { + "tagKey": "http.method", + "operator": "EQ", + "tagValue": "GET" + }, + { + "tagKey": "http.url", + "operator": "CONTAINS", + "tagValue": "health" + } + ], + [ + { + "tagKey": "grpc.url", + "operator": "NEQ", + "tagValue": "Sent.TestServiceGetEchos" + } + ] + ] +} + From b1cb908397a662f2f878e9b0b3ed43c1bd298c18 Mon Sep 17 00:00:00 2001 From: Ronak Date: Tue, 23 Nov 2021 17:31:26 +0530 Subject: [PATCH 2/5] feat: added support for checking filter criteria along with process tags too --- .../jaeger/JaegerSpanPreProcessor.java | 2 +- .../spannormalizer/jaeger/SpanFilter.java | 15 +- .../jaeger/JaegerSpanPreProcessorTest.java | 212 ++++++++++++++++++ 3 files changed, 224 insertions(+), 5 deletions(-) diff --git a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessor.java b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessor.java index cc4027280..4a1d1b500 100644 --- a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessor.java +++ b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessor.java @@ -100,7 +100,7 @@ PreProcessedSpan preProcessSpan(Span span) { String tenantId = maybeTenantId.get(); - if (spanFilter.shouldDropSpan(span, spanTags)) { + if (spanFilter.shouldDropSpan(span, spanTags, processTags)) { // increment dropped counter at tenant level tenantToSpansDroppedCount .computeIfAbsent( diff --git a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java index db774f930..1d99b1a69 100644 --- a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java +++ b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java @@ -117,7 +117,9 @@ private List>> parseStringList(List stringList * the span should be dropped, false otherwise. */ public boolean shouldDropSpan( - JaegerSpanInternalModel.Span span, Map tags) { + JaegerSpanInternalModel.Span span, + Map tags, + Map processTags) { if (anyCriteriaMatch(tags, spanDropCriterion)) { if (DROPPED_SPANS_RATE_LIMITER.tryAcquire()) { LOG.info("Dropping span: [{}] with drop criterion: [{}]", span, spanDropCriterion); @@ -125,7 +127,7 @@ public boolean shouldDropSpan( return true; } - if (anySpanDropFiltersMatch(spanDropFilters, tags)) { + if (anySpanDropFiltersMatch(spanDropFilters, tags, processTags)) { if (DROPPED_SPANS_RATE_LIMITER.tryAcquire()) { LOG.info("Dropping span: [{}] with drop filters: [{}]", span, spanDropFilters); } @@ -186,11 +188,16 @@ private boolean isRootExitSpan( private boolean anySpanDropFiltersMatch( List> spanDropFilters, - Map tags) { + Map tags, + Map processTags) { return spanDropFilters.stream() .anyMatch( andFilters -> - andFilters.stream().allMatch(filter -> matchSpanDropFilter(filter, tags))); + andFilters.stream() + .allMatch( + filter -> + matchSpanDropFilter(filter, tags) + || matchSpanDropFilter(filter, processTags))); } private boolean matchSpanDropFilter( diff --git a/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessorTest.java b/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessorTest.java index 1ad12fb74..24ebc1464 100644 --- a/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessorTest.java +++ b/span-normalizer/span-normalizer/src/test/java/org/hypertrace/core/spannormalizer/jaeger/JaegerSpanPreProcessorTest.java @@ -496,6 +496,218 @@ public void testSpanDropFilters() { Assertions.assertNotNull(preProcessedSpan); } + @Test + public void testSpanDropFiltersWithCombinationOfProcessAndSpanTags() { + String tenantId = "tenant-" + random.nextLong(); + Map configs = new HashMap<>(getCommonConfig()); + configs.putAll( + Map.of( + "processor", + Map.of( + "tenantIdTagKey", + "tenant-key", + "spanDropFilters", + List.of( + List.of( + Map.of("tagKey", "tenant-key", "operator", "EQ", "tagValue", tenantId), + Map.of("tagKey", "http.method", "operator", "EQ", "tagValue", "GET"), + Map.of("tagKey", "http.url", "operator", "CONTAINS", "tagValue", "health")), + List.of( + Map.of( + "tagKey", + "service_name", + "operator", + "CONTAINS", + "tagValue", + "drop-service"), + Map.of( + "tagKey", "grpc.url", "operator", "EXISTS", "tagValue", "health")))))); + + JaegerSpanPreProcessor jaegerSpanPreProcessor = + new JaegerSpanPreProcessor(ConfigFactory.parseMap(configs)); + + // case 1: {spanTags: [http.method & http.url], processTags:tenant_id } matches -> drop span + + Process process = + Process.newBuilder() + .setServiceName("testService") + .addTags(KeyValue.newBuilder().setKey("tenant-key").setVStr(tenantId).build()) + .build(); + + Span span = + Span.newBuilder() + .setProcess(process) + .addTags(KeyValue.newBuilder().setKey("http.method").setVStr("GET").build()) + .addTags( + KeyValue.newBuilder() + .setKey("http.url") + .setVStr("http://xyz.com/api/v1/health/check") + .build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + PreProcessedSpan preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNull(preProcessedSpan); + + // case 2: {spanTags: [http.method & http.url], processTags:tenant_id } not matches tenantId + process = + Process.newBuilder() + .setServiceName("testService") + .addTags( + KeyValue.newBuilder().setKey("tenant-key").setVStr(tenantId + "not-match").build()) + .build(); + + span = + Span.newBuilder() + .setProcess(process) + .addTags(KeyValue.newBuilder().setKey("http.method").setVStr("GET").build()) + .addTags( + KeyValue.newBuilder() + .setKey("http.url") + .setVStr("http://xyz.com/api/v1/health/check") + .build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNotNull(preProcessedSpan); + + // case 3: {spanTags: [http.method & http.url & tenant_id], processTags:tenant_id } + // match with spanTag's tenantId -> Drop span + process = + Process.newBuilder() + .setServiceName("testService") + .addTags( + KeyValue.newBuilder() + .setKey("tenant-key") + .setVStr(tenantId + "not-match-process") + .build()) + .build(); + + span = + Span.newBuilder() + .setProcess(process) + .addTags(KeyValue.newBuilder().setKey("tenant-key").setVStr(tenantId).build()) + .addTags(KeyValue.newBuilder().setKey("http.method").setVStr("GET").build()) + .addTags( + KeyValue.newBuilder() + .setKey("http.url") + .setVStr("http://xyz.com/api/v1/health/check") + .build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNull(preProcessedSpan); + + // case 4: {spanTags: [http.method & http.url & tenant_id], processTags:tenant_id } + // not match with spanTag or processTag tenantId + process = + Process.newBuilder() + .setServiceName("testService") + .addTags( + KeyValue.newBuilder() + .setKey("tenant-key") + .setVStr(tenantId + "not-match-process") + .build()) + .build(); + + span = + Span.newBuilder() + .setProcess(process) + .addTags( + KeyValue.newBuilder() + .setKey("tenant-key") + .setVStr(tenantId + "not-match-span") + .build()) + .addTags(KeyValue.newBuilder().setKey("http.method").setVStr("GET").build()) + .addTags( + KeyValue.newBuilder() + .setKey("http.url") + .setVStr("http://xyz.com/api/v1/health/check") + .build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNotNull(preProcessedSpan); + + // case 5: {spanTags: [!grpc.url], processTags:service_name } + // contains test for processTags -> matches + // grpc.url exists in spanTags -> matches + process = + Process.newBuilder() + .setServiceName("testService") + .addTags( + KeyValue.newBuilder() + .setKey("service_name") + .setVStr("drop-service-payment") + .build()) + .build(); + + span = + Span.newBuilder() + .setProcess(process) + .addTags( + KeyValue.newBuilder().setKey("tenant-key").setVStr(tenantId + "not-match-span")) + .addTags(KeyValue.newBuilder().setKey("http.method").setVStr("GET").build()) + .addTags( + KeyValue.newBuilder() + .setKey("grpc.url") + .setVStr("http://xyz.com/api/v1/health/check") + .build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNull(preProcessedSpan); + + // case 6: {spanTags: [!grpc.url], processTags:service_name } + // contains test for processTags -> doesn't matches + // grpc.url exists in spanTags -> match + process = + Process.newBuilder() + .setServiceName("testService") + .addTags(KeyValue.newBuilder().setKey("service_name").setVStr("payment").build()) + .build(); + + span = + Span.newBuilder() + .setProcess(process) + .addTags( + KeyValue.newBuilder().setKey("tenant-key").setVStr(tenantId + "not-match-span")) + .addTags(KeyValue.newBuilder().setKey("http.url").setVStr("GET").build()) + .addTags( + KeyValue.newBuilder() + .setKey("grpc.url") + .setVStr("http://xyz.com/api/v1/health/check") + .build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNotNull(preProcessedSpan); + + // case 6: {spanTags: [!grpc.url], processTags:service_name } + // contains test for processTags -> doesn't matches + // grpc.url doesn't exists in spanTags + process = + Process.newBuilder() + .setServiceName("testService") + .addTags(KeyValue.newBuilder().setKey("service_name").setVStr("payment").build()) + .build(); + + span = + Span.newBuilder() + .setProcess(process) + .addTags( + KeyValue.newBuilder().setKey("tenant-key").setVStr(tenantId + "not-match-span")) + .addTags(KeyValue.newBuilder().setKey("http.url").setVStr("GET").build()) + .addTags( + KeyValue.newBuilder() + .setKey("http.url") + .setVStr("http://xyz.com/api/v1/health/check") + .build()) + .addTags(KeyValue.newBuilder().setKey("extra.tag").setVStr("extra-test-value").build()) + .build(); + preProcessedSpan = jaegerSpanPreProcessor.preProcessSpan(span); + Assertions.assertNotNull(preProcessedSpan); + } + @Test public void testSpanDropFiltersBadConfig() { assertThrows( From ff97f35061fc3c14cf6f1e203263d6a3834a9c0d Mon Sep 17 00:00:00 2001 From: Ronak Date: Tue, 23 Nov 2021 20:10:10 +0530 Subject: [PATCH 3/5] addressed comments --- .../hypertrace/core/spannormalizer/jaeger/SpanFilter.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java index 1d99b1a69..63b84b593 100644 --- a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java +++ b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java @@ -6,6 +6,7 @@ import com.google.common.util.concurrent.RateLimiter; import com.typesafe.config.Config; +import com.typesafe.config.ConfigList; import io.jaegertracing.api_v2.JaegerSpanInternalModel; import java.util.Arrays; import java.util.Collections; @@ -65,8 +66,10 @@ public SpanFilter(Config config) { } if (config.hasPath(SPAN_DROP_FILTERS)) { + ConfigList spanDropFiltersConfig = config.getList(SPAN_DROP_FILTERS); + LOG.info("Span drop filters: {}", spanDropFiltersConfig); this.spanDropFilters = - config.getList(SPAN_DROP_FILTERS).stream() + spanDropFiltersConfig.stream() .map( orFilters -> { List> andFilters = @@ -81,7 +84,6 @@ public SpanFilter(Config config) { .collect(Collectors.toList()); }) .collect(Collectors.toList()); - LOG.info("Json String for Span drop criterion: {}", this.spanDropFilters); } if (config.hasPath(ROOT_SPAN_DROP_CRITERION_CONFIG)) { @@ -129,7 +131,7 @@ public boolean shouldDropSpan( if (anySpanDropFiltersMatch(spanDropFilters, tags, processTags)) { if (DROPPED_SPANS_RATE_LIMITER.tryAcquire()) { - LOG.info("Dropping span: [{}] with drop filters: [{}]", span, spanDropFilters); + LOG.debug("Dropping span: [{}] with drop filters: [{}]", span, spanDropFilters); } return true; } From 7298d39e0651b3d2c091f82c7aa5e6c4f115745a Mon Sep 17 00:00:00 2001 From: Ronak Date: Tue, 23 Nov 2021 20:40:48 +0530 Subject: [PATCH 4/5] addressed tostring and logging related comments --- .../core/spannormalizer/jaeger/SpanDropFilter.java | 14 ++++++++++++++ .../core/spannormalizer/jaeger/SpanFilter.java | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanDropFilter.java b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanDropFilter.java index 789ef67e8..ff4460b21 100644 --- a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanDropFilter.java +++ b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanDropFilter.java @@ -44,4 +44,18 @@ public Operator getOperator() { public String getTagValue() { return tagValue; } + + @Override + public String toString() { + return "SpanDropFilter{" + + "tagKey='" + + tagKey + + '\'' + + ", operator=" + + operator + + ", tagValue='" + + tagValue + + '\'' + + '}'; + } } diff --git a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java index 63b84b593..1a320a49a 100644 --- a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java +++ b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java @@ -131,7 +131,7 @@ public boolean shouldDropSpan( if (anySpanDropFiltersMatch(spanDropFilters, tags, processTags)) { if (DROPPED_SPANS_RATE_LIMITER.tryAcquire()) { - LOG.debug("Dropping span: [{}] with drop filters: [{}]", span, spanDropFilters); + LOG.debug("Dropping span: [{}] with drop filters: [{}]", span, spanDropFilters.toString()); } return true; } From 8b73714d5c81c99bf267e735b19e7e082f811421 Mon Sep 17 00:00:00 2001 From: Ronak Date: Tue, 23 Nov 2021 21:32:01 +0530 Subject: [PATCH 5/5] address comments of wrapping around if debuged enabled for log --- .../org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java index 1a320a49a..3d04ea141 100644 --- a/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java +++ b/span-normalizer/span-normalizer/src/main/java/org/hypertrace/core/spannormalizer/jaeger/SpanFilter.java @@ -130,7 +130,7 @@ public boolean shouldDropSpan( } if (anySpanDropFiltersMatch(spanDropFilters, tags, processTags)) { - if (DROPPED_SPANS_RATE_LIMITER.tryAcquire()) { + if (LOG.isDebugEnabled() && DROPPED_SPANS_RATE_LIMITER.tryAcquire()) { LOG.debug("Dropping span: [{}] with drop filters: [{}]", span, spanDropFilters.toString()); } return true;