diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/SpanFilterBuilder.java b/splunk-otel-android/src/main/java/com/splunk/rum/SpanFilterBuilder.java index 6e37cb5ee..a233f46bc 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/SpanFilterBuilder.java +++ b/splunk-otel-android/src/main/java/com/splunk/rum/SpanFilterBuilder.java @@ -18,24 +18,14 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.sdk.trace.export.SpanExporter; -import java.util.HashMap; -import java.util.Map; import java.util.function.Function; import java.util.function.Predicate; -/** - * Allows modification of span data before it is sent to the exporter. Spans can be modified or - * entirely rejected from export. - */ +/** Delegating wrapper around otel SpanFilterBuilder. */ public final class SpanFilterBuilder { - private Predicate rejectSpanNamesPredicate = spanName -> false; - private final Map, Predicate> rejectSpanAttributesPredicates = - new HashMap<>(); - private final Map, Function> spanAttributeReplacements = new HashMap<>(); - - SpanFilterBuilder() {} - + private final io.opentelemetry.rum.internal.SpanFilterBuilder delegate = + new io.opentelemetry.rum.internal.SpanFilterBuilder(); /** * Remove matching spans from the exporter pipeline. * @@ -46,7 +36,7 @@ public final class SpanFilterBuilder { * @return {@code this}. */ public SpanFilterBuilder rejectSpansByName(Predicate spanNamePredicate) { - rejectSpanNamesPredicate = rejectSpanNamesPredicate.or(spanNamePredicate); + delegate.rejectSpansByName(spanNamePredicate); return this; } @@ -63,13 +53,7 @@ public SpanFilterBuilder rejectSpansByName(Predicate spanNamePredicate) */ public SpanFilterBuilder rejectSpansByAttributeValue( AttributeKey attributeKey, Predicate attributeValuePredicate) { - - rejectSpanAttributesPredicates.compute( - attributeKey, - (k, oldValue) -> - oldValue == null - ? attributeValuePredicate - : ((Predicate) oldValue).or(attributeValuePredicate)); + delegate.rejectSpansByAttributeValue(attributeKey, attributeValuePredicate); return this; } @@ -83,7 +67,8 @@ public SpanFilterBuilder rejectSpansByAttributeValue( * @return {@code this}. */ public SpanFilterBuilder removeSpanAttribute(AttributeKey attributeKey) { - return removeSpanAttribute(attributeKey, value -> true); + delegate.removeSpanAttribute(attributeKey); + return this; } /** @@ -99,9 +84,8 @@ public SpanFilterBuilder removeSpanAttribute(AttributeKey attributeKey) { */ public SpanFilterBuilder removeSpanAttribute( AttributeKey attributeKey, Predicate attributeValuePredicate) { - - return replaceSpanAttribute( - attributeKey, old -> attributeValuePredicate.test(old) ? null : old); + delegate.removeSpanAttribute(attributeKey, attributeValuePredicate); + return this; } /** @@ -119,30 +103,15 @@ public SpanFilterBuilder removeSpanAttribute( */ public SpanFilterBuilder replaceSpanAttribute( AttributeKey attributeKey, Function attributeValueModifier) { - - spanAttributeReplacements.compute( - attributeKey, - (k, oldValue) -> - oldValue == null - ? attributeValueModifier - : ((Function) oldValue).andThen(attributeValueModifier)); + delegate.replaceSpanAttribute(attributeKey, attributeValueModifier); return this; } - Function build() { - // make a copy so that the references from the builder are not included in the returned - // function - Predicate rejectSpanNamesPredicate = this.rejectSpanNamesPredicate; - Map, Predicate> rejectSpanAttributesPredicates = - new HashMap<>(this.rejectSpanAttributesPredicates); - Map, Function> spanAttributeReplacements = - new HashMap<>(this.spanAttributeReplacements); + io.opentelemetry.rum.internal.SpanFilterBuilder getDelegate() { + return delegate; + } - return exporter -> - new SpanDataModifier( - exporter, - rejectSpanNamesPredicate, - rejectSpanAttributesPredicates, - spanAttributeReplacements); + public Function build() { + return delegate.build(); } } diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/StandardAttributes.java b/splunk-otel-android/src/main/java/com/splunk/rum/StandardAttributes.java index 64b4d2882..46a69e237 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/StandardAttributes.java +++ b/splunk-otel-android/src/main/java/com/splunk/rum/StandardAttributes.java @@ -18,6 +18,7 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.rum.internal.SpanFilterBuilder; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; /** diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/ModifiedSpanData.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/ModifiedSpanData.java similarity index 96% rename from splunk-otel-android/src/main/java/com/splunk/rum/ModifiedSpanData.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/ModifiedSpanData.java index 1271cf5c8..14cda52b2 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/ModifiedSpanData.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/ModifiedSpanData.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.trace.data.DelegatingSpanData; diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/SpanDataModifier.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/SpanDataModifier.java similarity index 99% rename from splunk-otel-android/src/main/java/com/splunk/rum/SpanDataModifier.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/SpanDataModifier.java index f9a2d5a5b..dda96f557 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/SpanDataModifier.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/SpanDataModifier.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; diff --git a/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/SpanFilterBuilder.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/SpanFilterBuilder.java new file mode 100644 index 000000000..3f4638d97 --- /dev/null +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/SpanFilterBuilder.java @@ -0,0 +1,146 @@ +/* + * Copyright Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.rum.internal; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Predicate; + +/** + * Allows modification of span data before it is sent to the exporter. Spans can be modified or + * entirely rejected from export. + */ +public final class SpanFilterBuilder { + + private Predicate rejectSpanNamesPredicate = spanName -> false; + private final Map, Predicate> rejectSpanAttributesPredicates = + new HashMap<>(); + private final Map, Function> spanAttributeReplacements = new HashMap<>(); + + /** + * Remove matching spans from the exporter pipeline. + * + *

Spans with names that match the {@code spanNamePredicate} will not be exported. + * + * @param spanNamePredicate A function that returns true if a span with passed name should be + * rejected. + * @return {@code this}. + */ + public SpanFilterBuilder rejectSpansByName(Predicate spanNamePredicate) { + rejectSpanNamesPredicate = rejectSpanNamesPredicate.or(spanNamePredicate); + return this; + } + + /** + * Remove matching spans from the exporter pipeline. + * + *

Any span that contains an attribute with key {@code attributeKey} and value matching the + * {@code attributeValuePredicate} will not be exported. + * + * @param attributeKey An attribute key to match. + * @param attributeValuePredicate A function that returns true if a span containing an attribute + * with matching value should be rejected. + * @return {@code this}. + */ + public SpanFilterBuilder rejectSpansByAttributeValue( + AttributeKey attributeKey, Predicate attributeValuePredicate) { + + rejectSpanAttributesPredicates.compute( + attributeKey, + (k, oldValue) -> + oldValue == null + ? attributeValuePredicate + : ((Predicate) oldValue).or(attributeValuePredicate)); + return this; + } + + /** + * Modify span data before it enters the exporter pipeline. + * + *

Any attribute with key {@code attributeKey} and will be removed from the span before it is + * exported. + * + * @param attributeKey An attribute key to match. + * @return {@code this}. + */ + public SpanFilterBuilder removeSpanAttribute(AttributeKey attributeKey) { + return removeSpanAttribute(attributeKey, value -> true); + } + + /** + * Modify span data before it enters the exporter pipeline. + * + *

Any attribute with key {@code attributeKey} and value matching the {@code + * attributeValuePredicate} will be removed from the span before it is exported. + * + * @param attributeKey An attribute key to match. + * @param attributeValuePredicate A function that returns true if an attribute with matching + * value should be removed from the span. + * @return {@code this}. + */ + public SpanFilterBuilder removeSpanAttribute( + AttributeKey attributeKey, Predicate attributeValuePredicate) { + + return replaceSpanAttribute( + attributeKey, old -> attributeValuePredicate.test(old) ? null : old); + } + + /** + * Modify span data before it enters the exporter pipeline. + * + *

The value of any attribute with key {@code attributeKey} will be passed to the {@code + * attributeValueModifier} function. The value returned by the function will replace the + * original value. When the modifier function returns {@code null} the attribute will be removed + * from the span. + * + * @param attributeKey An attribute key to match. + * @param attributeValueModifier A function that receives the old attribute value and returns + * the new one. + * @return {@code this}. + */ + public SpanFilterBuilder replaceSpanAttribute( + AttributeKey attributeKey, Function attributeValueModifier) { + + spanAttributeReplacements.compute( + attributeKey, + (k, oldValue) -> + oldValue == null + ? attributeValueModifier + : ((Function) oldValue).andThen(attributeValueModifier)); + return this; + } + + public Function build() { + // make a copy so that the references from the builder are not included in the returned + // function + Predicate rejectSpanNamesPredicate = this.rejectSpanNamesPredicate; + Map, Predicate> rejectSpanAttributesPredicates = + new HashMap<>(this.rejectSpanAttributesPredicates); + Map, Function> spanAttributeReplacements = + new HashMap<>(this.spanAttributeReplacements); + + return exporter -> + new SpanDataModifier( + exporter, + rejectSpanNamesPredicate, + rejectSpanAttributesPredicates, + spanAttributeReplacements); + } +} diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/ModifiedSpanDataTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/ModifiedSpanDataTest.java similarity index 99% rename from splunk-otel-android/src/test/java/com/splunk/rum/ModifiedSpanDataTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/ModifiedSpanDataTest.java index e547f82b5..ef27fddf9 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/ModifiedSpanDataTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/ModifiedSpanDataTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal; import static io.opentelemetry.api.common.AttributeKey.stringKey; import static java.util.Collections.emptyList; diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/SpanDataModifierTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/SpanDataModifierTest.java similarity index 99% rename from splunk-otel-android/src/test/java/com/splunk/rum/SpanDataModifierTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/SpanDataModifierTest.java index 4847986e3..3fec041b1 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/SpanDataModifierTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/SpanDataModifierTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal; import static io.opentelemetry.api.common.AttributeKey.longKey; import static io.opentelemetry.api.common.AttributeKey.stringKey;