diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/ProbabilisticSnapshotSelector.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/ProbabilisticSnapshotSelector.java deleted file mode 100644 index dd03c22cf..000000000 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/ProbabilisticSnapshotSelector.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import java.util.concurrent.ThreadLocalRandom; - -class ProbabilisticSnapshotSelector implements SnapshotSelector { - private final double selectionRate; - - public ProbabilisticSnapshotSelector(double selectionRate) { - this.selectionRate = selectionRate; - } - - @Override - public boolean select(Context context) { - if (!isTraceRoot(context)) { - return false; - } - - ThreadLocalRandom random = ThreadLocalRandom.current(); - return random.nextDouble() <= selectionRate; - } - - private boolean isTraceRoot(Context context) { - return Span.fromContextOrNull(context) == null; - } -} diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingConfigurationCustomizerProvider.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingConfigurationCustomizerProvider.java index 377a4d1a3..cec70800c 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingConfigurationCustomizerProvider.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingConfigurationCustomizerProvider.java @@ -25,7 +25,6 @@ import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PropagatorModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProviderModel; import java.util.List; @@ -52,33 +51,12 @@ OpenTelemetryConfigurationModel customizeModel(OpenTelemetryConfigurationModel m if (snapshotProfiling.isEnabled()) { initActiveSpansTracking(); initStackTraceSampler(snapshotProfiling); - addSnapshotVolumePropagator(model); addSpanProcessors(model); } return model; } - private void addSnapshotVolumePropagator(OpenTelemetryConfigurationModel model) { - PropagatorModel propagatorModel = model.getPropagator(); - if (propagatorModel == null) { - propagatorModel = new PropagatorModel(); - model.withPropagator(propagatorModel); - } - - String volumePropagatorName = SnapshotVolumePropagatorComponentProvider.NAME; - String propagators = propagatorModel.getCompositeList(); - // Possible propagator duplicates with propagatorModel.getComposite() are resolved by the - // upstream - if (propagators == null || propagators.trim().isEmpty()) { - propagators = volumePropagatorName; - } else { - propagators = String.join(",", propagators, volumePropagatorName); - } - - propagatorModel.withCompositeList(propagators); - } - private void initStackTraceSampler( SnapshotProfilingDeclarativeConfiguration snapshotProfilingConfig) { StackTraceSamplerInitializer.setupStackTraceSampler(snapshotProfilingConfig); diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSdkCustomizer.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSdkCustomizer.java index 39f021441..e1a8b4a8c 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSdkCustomizer.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSdkCustomizer.java @@ -24,7 +24,6 @@ import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; import java.time.Duration; import java.util.Collections; -import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; @@ -81,7 +80,6 @@ private SnapshotProfilingSdkCustomizer( @Override public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) { autoConfigurationCustomizer - .addPropertiesCustomizer(autoConfigureSnapshotVolumePropagator()) .addTracerProviderCustomizer(snapshotProfilingSpanProcessor(registry)) .addPropertiesCustomizer(setupStackTraceSampler()) .addPropertiesCustomizer(startTrackingActiveSpans(registry)) @@ -102,39 +100,14 @@ public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) { snapshotProfilingSpanProcessor(TraceRegistry registry) { return (builder, properties) -> { if (snapshotProfilingEnabled(properties)) { - return builder.addSpanProcessor(new SnapshotProfilingSpanProcessor(registry)); - } - return builder; - }; - } + double selectionProbability = + new SnapshotProfilingEnvVarsConfiguration(properties).getSnapshotSelectionProbability(); - /** - * Attempt to autoconfigure the OpenTelemetry propagators to include the Splunk snapshot volume - * propagator and ensure it runs after the W3C Baggage propagator and ensure that a trace context - * propagator is configured. In addition, take care to retain any propagators explicitly - * configured prior. - * - *

The Java agent uses the "otel.propagators" property and the value is assumed to be a comma - * seperated list of propagator names. See OpenTelemetry's - * Java Agent Configuration for more details. - */ - private Function> autoConfigureSnapshotVolumePropagator() { - return properties -> { - if (snapshotProfilingEnabled(properties)) { - Set propagators = new LinkedHashSet<>(properties.getList("otel.propagators")); - if (propagators.contains("none")) { - return Collections.emptyMap(); - } - - if (includeTraceContextPropagator(propagators)) { - propagators.add("tracecontext"); - } - propagators.add("baggage"); - propagators.add(SnapshotVolumePropagatorProvider.NAME); - return Collections.singletonMap("otel.propagators", String.join(",", propagators)); + return builder.addSpanProcessor( + new SnapshotProfilingSpanProcessor( + registry, new TraceIdBasedSnapshotSelector(selectionProbability))); } - return Collections.emptyMap(); + return builder; }; } diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSpanProcessor.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSpanProcessor.java index 00e0eac29..5f2d49fd8 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSpanProcessor.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSpanProcessor.java @@ -18,6 +18,7 @@ import static com.splunk.opentelemetry.profiler.ProfilingSemanticAttributes.SNAPSHOT_PROFILING; +import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.trace.ReadWriteSpan; @@ -29,19 +30,22 @@ */ public class SnapshotProfilingSpanProcessor implements SpanProcessor { private final TraceRegistry registry; + private final SnapshotSelector selector; private final OrphanedTraceCleaner orphanedTraceCleaner; - SnapshotProfilingSpanProcessor(TraceRegistry registry) { + SnapshotProfilingSpanProcessor(TraceRegistry registry, SnapshotSelector selector) { this.registry = registry; + this.selector = selector; this.orphanedTraceCleaner = new OrphanedTraceCleaner(registry); } @Override public void onStart(Context context, ReadWriteSpan span) { if (isEntry(span)) { - Volume volume = Volume.from(context); - if (volume == Volume.HIGHEST) { - registry.register(span.getSpanContext()); + SpanContext spanContext = span.getSpanContext(); + boolean selected = selector.select(spanContext); + if (selected) { + registry.register(spanContext); orphanedTraceCleaner.register(span); } } diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSpanProcessorComponentProvider.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSpanProcessorComponentProvider.java index 1f034a31a..a0b0d0b8a 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSpanProcessorComponentProvider.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingSpanProcessorComponentProvider.java @@ -47,6 +47,10 @@ public String getName() { @Override public SnapshotProfilingSpanProcessor create( DeclarativeConfigProperties declarativeConfigProperties) { - return new SnapshotProfilingSpanProcessor(traceRegistry); + double selectionProbability = + new SnapshotProfilingDeclarativeConfiguration(declarativeConfigProperties) + .getSnapshotSelectionProbability(); + return new SnapshotProfilingSpanProcessor( + traceRegistry, new TraceIdBasedSnapshotSelector(selectionProbability)); } } diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSelector.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSelector.java index dda646cb6..e3c34aa70 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSelector.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSelector.java @@ -16,12 +16,8 @@ package com.splunk.opentelemetry.profiler.snapshot; -import io.opentelemetry.context.Context; +import io.opentelemetry.api.trace.SpanContext; interface SnapshotSelector { - default SnapshotSelector or(SnapshotSelector other) { - return context -> select(context) || other.select(context); - } - - boolean select(Context context); + boolean select(SpanContext context); } diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagator.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagator.java deleted file mode 100644 index 7db16a56b..000000000 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagator.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapGetter; -import io.opentelemetry.context.propagation.TextMapPropagator; -import io.opentelemetry.context.propagation.TextMapSetter; -import java.util.Collection; -import java.util.Collections; - -class SnapshotVolumePropagator implements TextMapPropagator { - private final SnapshotSelector selector; - - SnapshotVolumePropagator(SnapshotSelector selector) { - this.selector = selector; - } - - @Override - public Collection fields() { - return Collections.emptyList(); - } - - @Override - public void inject(Context context, C carrier, TextMapSetter setter) {} - - /** - * Make a decision whether a trace should be selected for snapshotting if --and only if -- that - * decision has not yet been made by an upstream service. Ideally a snapshotting decision will - * have been made only at trace root, however there are many scenarios (e.g. RUM, or language - * agents without snapshot support) where a trace will begin without a decision. In those - * instances we would like to snapshot as much of the trace as possible. - * - *

Not seen here in the introduction of {@link TraceIdBasedSnapshotSelector} which will - * deterministically select a trace based on the Trace ID value so that all participating and - * capable agents can make the same snapshotting decision, if necessary. - */ - @Override - public Context extract(Context context, C carrier, TextMapGetter getter) { - Volume volume = Volume.from(context); - if (volume != Volume.UNSPECIFIED) { - return context; - } - - volume = selector.select(context) ? Volume.HIGHEST : Volume.OFF; - return context.with(volume); - } -} diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorComponentProvider.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorComponentProvider.java deleted file mode 100644 index c1c991090..000000000 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorComponentProvider.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import com.google.auto.service.AutoService; -import com.google.common.annotations.VisibleForTesting; -import io.opentelemetry.api.incubator.config.DeclarativeConfigException; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.context.propagation.TextMapPropagator; -import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; - -@AutoService(ComponentProvider.class) -public class SnapshotVolumePropagatorComponentProvider implements ComponentProvider { - static final String NAME = "splunk_snapshot_volume"; - - @Override - public Class getType() { - return TextMapPropagator.class; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public TextMapPropagator create(DeclarativeConfigProperties propagatorProperties) { - if (!SnapshotProfilingDeclarativeConfiguration.SUPPLIER.isConfigured()) { - throw new DeclarativeConfigException("Snapshot profiling is not configured"); - } - double selectionProbability = - SnapshotProfilingDeclarativeConfiguration.SUPPLIER.get().getSnapshotSelectionProbability(); - - return new SnapshotVolumePropagator(selector(selectionProbability)); - } - - @VisibleForTesting - SnapshotSelector selector(double selectionProbability) { - return new TraceIdBasedSnapshotSelector(selectionProbability) - .or(new ProbabilisticSnapshotSelector(selectionProbability)); - } -} diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorProvider.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorProvider.java deleted file mode 100644 index 3cdd6f611..000000000 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import com.google.auto.service.AutoService; -import io.opentelemetry.context.propagation.TextMapPropagator; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigurablePropagatorProvider; - -@AutoService(ConfigurablePropagatorProvider.class) -public class SnapshotVolumePropagatorProvider implements ConfigurablePropagatorProvider { - public static final String NAME = "splunk-snapshot"; - - @Override - public TextMapPropagator getPropagator(ConfigProperties config) { - double selectionProbability = - new SnapshotProfilingEnvVarsConfiguration(config).getSnapshotSelectionProbability(); - return new SnapshotVolumePropagator(selector(selectionProbability)); - } - - private SnapshotSelector selector(double selectionProbability) { - return new TraceIdBasedSnapshotSelector(selectionProbability) - .or(new ProbabilisticSnapshotSelector(selectionProbability)); - } - - @Override - public String getName() { - return NAME; - } -} diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/TraceIdBasedSnapshotSelector.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/TraceIdBasedSnapshotSelector.java index 3a4544a32..fced2402e 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/TraceIdBasedSnapshotSelector.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/TraceIdBasedSnapshotSelector.java @@ -16,48 +16,44 @@ package com.splunk.opentelemetry.profiler.snapshot; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.trace.samplers.Sampler; -import io.opentelemetry.sdk.trace.samplers.SamplingDecision; -import io.opentelemetry.sdk.trace.samplers.SamplingResult; -import java.util.Collections; class TraceIdBasedSnapshotSelector implements SnapshotSelector { - private final Sampler sampler; + // the length of trace-id represented as a hex string + private static final int TRACE_ID_LENGTH = 32; + // number of characters taken from the tail of trace-id as the trace randomness + private static final int CHARS = 7; + private static final String HEX_FORMATTER = "%07x"; + // to convert probability to threshold + private static final int MULTIPLIER = (1 << (4 * CHARS)) - 1; + private final String threshold; TraceIdBasedSnapshotSelector(double selectionProbability) { if (selectionProbability < 0 || selectionProbability > 1) { throw new IllegalArgumentException("Selection probability must be between 0 and 1."); } - this.sampler = Sampler.traceIdRatioBased(selectionProbability); + + this.threshold = thresholdFor(selectionProbability); + } + + private static String thresholdFor(double probability) { + int threshold = (int) (probability * MULTIPLIER); + if (threshold == 0) { + // Zero or near-zero probability, special case + return null; + } + return String.format(HEX_FORMATTER, threshold); } @Override - public boolean select(Context context) { - SpanContext spanContext = Span.fromContext(context).getSpanContext(); - if (!spanContext.isValid()) { + public boolean select(SpanContext spanContext) { + if (threshold == null || !spanContext.isValid()) { return false; } - return shouldSample(spanContext.getTraceId()) == SamplingDecision.RECORD_AND_SAMPLE; - } - - /** - * Trace ID ratio sampling only considers trace ID so other parameters can safely be placeholders. - */ - private SamplingDecision shouldSample(String traceId) { - SamplingResult result = - sampler.shouldSample( - Context.root(), - traceId, - "", - SpanKind.INTERNAL, - Attributes.empty(), - Collections.emptyList()); - return result.getDecision(); + String traceId = spanContext.getTraceId(); + String randomness = traceId.substring(TRACE_ID_LENGTH - CHARS); + // Select if randomness is lesser or equal to threshold + return randomness.compareTo(threshold) < 1; } } diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/Volume.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/Volume.java deleted file mode 100644 index 1aadedbfd..000000000 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/snapshot/Volume.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import io.opentelemetry.api.baggage.Baggage; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.ImplicitContextKeyed; -import java.util.Locale; - -public enum Volume implements ImplicitContextKeyed { - OFF, - HIGHEST, - UNSPECIFIED; - - private static final String SPLUNK_TRACE_SNAPSHOT_VOLUME = "splunk.trace.snapshot.volume"; - - static Volume from(Context context) { - Baggage baggage = Baggage.fromContext(context); - return fromString(baggage.getEntryValue(SPLUNK_TRACE_SNAPSHOT_VOLUME)); - } - - private static Volume fromString(String value) { - if (value == null) { - return UNSPECIFIED; - } - - try { - return Volume.valueOf(value.toUpperCase(Locale.ROOT)); - } catch (IllegalArgumentException e) { - return OFF; - } - } - - @Override - public String toString() { - return name().toLowerCase(Locale.ROOT); - } - - @Override - public Context storeInContext(Context context) { - return context.with(toBaggage()); - } - - private Baggage toBaggage() { - return Baggage.current().toBuilder().put(SPLUNK_TRACE_SNAPSHOT_VOLUME, toString()).build(); - } -} diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/AutoConfigureSnapshotVolumePropagatorTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/AutoConfigureSnapshotVolumePropagatorTest.java deleted file mode 100644 index 3f8be775f..000000000 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/AutoConfigureSnapshotVolumePropagatorTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import static org.assertj.core.api.Assertions.assertThat; - -import io.opentelemetry.sdk.autoconfigure.OpenTelemetrySdkExtension; -import io.opentelemetry.sdk.autoconfigure.OpenTelemetrySdkExtension.Builder; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -class AutoConfigureSnapshotVolumePropagatorTest { - private static final String OTEL_PROPAGATORS = "otel-propagators"; - - @Test - void autoConfigureSnapshotVolumePropagator() { - try (var sdk = newSdk().build()) { - var properties = sdk.getConfig(); - assertThat(properties.getList(OTEL_PROPAGATORS)) - .contains(SnapshotVolumePropagatorProvider.NAME); - } - } - - @Test - void snapshotVolumePropagatorMustBeAfterTraceContextAndBaggage() { - try (var sdk = newSdk().build()) { - var properties = sdk.getConfig(); - assertThat(properties.getList(OTEL_PROPAGATORS)) - .containsExactly("tracecontext", "baggage", SnapshotVolumePropagatorProvider.NAME); - } - } - - @Test - void appendSnapshotPropagatorToEndOfAlreadyConfiguredPropagators() { - try (var sdk = - newSdk() - .withProperty(OTEL_PROPAGATORS, "tracecontext,baggage,some-other-propagator") - .build()) { - var properties = sdk.getConfig(); - assertThat(properties.getList(OTEL_PROPAGATORS)) - .containsExactly( - "tracecontext", - "baggage", - "some-other-propagator", - SnapshotVolumePropagatorProvider.NAME); - } - } - - @ParameterizedTest - @ValueSource(strings = {"baggage", "tracecontext"}) - void doNotDoubleCountDefaultOpenTelemetryPropagators(String propagatorName) { - try (var sdk = newSdk().withProperty(OTEL_PROPAGATORS, propagatorName).build()) { - var properties = sdk.getConfig(); - assertThat(properties.getList(OTEL_PROPAGATORS)).containsOnlyOnce(propagatorName); - } - } - - @Test - void doNotDoubleCountSnapshotVolumePropagator() { - try (var sdk = - newSdk().withProperty(OTEL_PROPAGATORS, SnapshotVolumePropagatorProvider.NAME).build()) { - var properties = sdk.getConfig(); - assertThat(properties.getList(OTEL_PROPAGATORS)) - .containsOnlyOnce(SnapshotVolumePropagatorProvider.NAME); - } - } - - @Test - void doNotAddSnapshotVolumePropagatorWhenTraceSnapshottingIsDisabled() { - try (var sdk = - newSdk() - .withProperty( - SnapshotProfilingEnvVarsConfiguration.CONFIG_KEY_ENABLE_SNAPSHOT_PROFILER, "false") - .build()) { - var properties = sdk.getConfig(); - assertThat(properties.getList(OTEL_PROPAGATORS)) - .doesNotContain(SnapshotVolumePropagatorProvider.NAME); - } - } - - @Test - void doNotAddSnapshotVolumePropagatorsConfiguredAsNone() { - try (var sdk = newSdk().withProperty(OTEL_PROPAGATORS, "none").build()) { - var properties = sdk.getConfig(); - assertThat(properties.getList(OTEL_PROPAGATORS)) - .doesNotContain(SnapshotVolumePropagatorProvider.NAME); - } - } - - @Test - void doNotAddTraceContextPropagatorWhenOtherPropagatorsAreExplicitlyConfigured() { - try (var sdk = - newSdk().withProperty(OTEL_PROPAGATORS, "some-other-propagator,baggage").build()) { - var properties = sdk.getConfig(); - assertThat(properties.getList(OTEL_PROPAGATORS)) - .containsExactly( - "some-other-propagator", "baggage", SnapshotVolumePropagatorProvider.NAME); - } - } - - @Test - void addBaggagePropagatorWhenOtherPropagatorsAreExplicitlyConfiguredButBaggageIsMissing() { - try (var sdk = newSdk().withProperty(OTEL_PROPAGATORS, "some-other-propagator").build()) { - var properties = sdk.getConfig(); - assertThat(properties.getList(OTEL_PROPAGATORS)) - .containsExactly( - "some-other-propagator", "baggage", SnapshotVolumePropagatorProvider.NAME); - } - } - - private Builder newSdk() { - return OpenTelemetrySdkExtension.configure() - .withProperty( - SnapshotProfilingEnvVarsConfiguration.CONFIG_KEY_ENABLE_SNAPSHOT_PROFILER, "true") - .with(new SnapshotProfilingSdkCustomizer()); - } -} diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/ConcurrentServiceEntrySamplingTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/ConcurrentServiceEntrySamplingTest.java index 5b2462c9d..327e9bc68 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/ConcurrentServiceEntrySamplingTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/ConcurrentServiceEntrySamplingTest.java @@ -61,6 +61,7 @@ private StackTraceSampler newSampler(StagingArea staging) { public final OpenTelemetrySdkExtension downstreamSdk = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .with(downstreamCustomizer) .with( new StackTraceExporterActivator( @@ -83,8 +84,8 @@ private StackTraceSampler newSampler(StagingArea staging) { public final OpenTelemetrySdkExtension upstreamSdk = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .with(upstreamCustomizer) - .with(new SnapshotVolumePropagator((c) -> true)) .build(); @RegisterExtension diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/DistributedProfilingSignalTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/DistributedProfilingSignalTest.java index 5fb453877..1ee1c13ab 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/DistributedProfilingSignalTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/DistributedProfilingSignalTest.java @@ -38,8 +38,8 @@ class DistributedProfilingSignalTest { public final OpenTelemetrySdkExtension downstreamSdk = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .with(downstreamCustomizer) - .with(new SnapshotVolumePropagator((c) -> true)) .build(); @RegisterExtension @@ -64,8 +64,8 @@ class DistributedProfilingSignalTest { public final OpenTelemetrySdkExtension upstreamSdk = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .with(upstreamCustomizer) - .with(new SnapshotVolumePropagator((c) -> true)) .build(); @RegisterExtension @@ -86,10 +86,10 @@ class DistributedProfilingSignalTest { * 2. Middle is instrumented with a vanilla OpenTelemetry agent
* 3. Downstream is instrumented with the snapshot profiling agent extension
* We want for the upstream service instrumentation to initially register the trace for profiling - * and for that signal to propagate through the middle service to the downstream service. + * and for the downstream service to register the same trace for profiling as well. */ @Test - void traceSnapshotVolumePropagatesAcrossProcessBoundaries() { + void traceSnapshotSelectionPropagatesAcrossProcessBoundaries() { upstream.send(new Message()); await().atMost(Duration.ofDays(2)).until(() -> upstream.waitForResponse() != null); diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/GracefulShutdownTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/GracefulShutdownTest.java index 627b07bc7..c54ad34dc 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/GracefulShutdownTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/GracefulShutdownTest.java @@ -38,6 +38,7 @@ class GracefulShutdownTest { public final OpenTelemetrySdkExtension sdk = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .with(Snapshotting.customizer().withRealStackTraceSampler().withRealStagingArea().build()) .with( new StackTraceExporterActivator( @@ -66,7 +67,7 @@ void stopSnapshotProfilingExtensionWhenOpenTelemetrySdkIsShutdown(Tracer tracer) private Runnable startNewTrace(Tracer tracer) { var logger = LoggerFactory.getLogger(GracefulShutdownTest.class); return () -> { - try (var ignored1 = Context.root().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored1 = Context.root().makeCurrent()) { var span = tracer.spanBuilder("root").setSpanKind(SpanKind.SERVER).startSpan(); try (var ignored2 = span.makeCurrent()) { Thread.sleep(25); diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/LongRunningBackgroundTaskTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/LongRunningBackgroundTaskTest.java index 360af0308..791c125c7 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/LongRunningBackgroundTaskTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/LongRunningBackgroundTaskTest.java @@ -38,8 +38,8 @@ class LongRunningBackgroundTaskTest { public final OpenTelemetrySdkExtension sdk = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .with(customizer) - .with(new SnapshotVolumePropagator((c) -> true)) .build(); private CountDownLatch slowTaskLatch = new CountDownLatch(1); diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/MultiThreadedTraceProfilingTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/MultiThreadedTraceProfilingTest.java index f3bdd1dba..a5afc32e3 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/MultiThreadedTraceProfilingTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/MultiThreadedTraceProfilingTest.java @@ -38,8 +38,8 @@ public class MultiThreadedTraceProfilingTest { public final OpenTelemetrySdkExtension sdk = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .with(customizer) - .with(new SnapshotVolumePropagator((c) -> true)) .build(); @RegisterExtension diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/ProbabilisticSnapshotSelectorTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/ProbabilisticSnapshotSelectorTest.java deleted file mode 100644 index 6856b91fe..000000000 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/ProbabilisticSnapshotSelectorTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import java.util.ArrayList; -import java.util.List; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; - -/** - * The intent of the pipeline is to select roughly 5% of traces for snapshotting, and this 5% should - * be relatively stable regardless of how long we observe the snapshotting selection process. This - * is a naturally non-deterministic behavior, however, we are not able to test it through - * traditional deterministic unit tests. - * - *

Rather we need to test the behaviour by gathering a series of results and examining their - * variance from the intent, and there are two data points in particular we are interested in 1. - * Total percentage of traces selected for snapshotting 2. Stableness overtime of the snapshot - * selection algorithm - * - *

We cannot expect exactly 5% of traces selected, nor can we expect a perfectly stable system. - * We must instead accept some level of deviation from the stated intent of 5%. - * - *

Since the selection process is non-deterministic the idea behind this "test" is to confirm the - * results are all within some acceptable range and to do this we need execute the program a lot of - * times to obtain a distribution of outcomes. Here we have arbitrarily defined "a lot of times" to - * mean 100. - * - *

Each run of the test will process 1000 traces and our expectation is for roughly 5%, or 100, - * of those traces to be selected for snapshotting. We have arbitrarily defined our acceptable range - * as 10% of our expectation, or 90 <= x <= 110. - * - *

However outcomes beyond the acceptable range are still expected, but we shouldn't expect too - * many of those so our test assertions state that after the 100 executions are complete less than - * 5% of outcomes are beyond the acceptable range. Or, put another way, at least 95% of outcomes are - * within the acceptable range. - */ -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -class ProbabilisticSnapshotSelectorTest { - private static final int ITERATIONS = 100; - private static final int TRACES_PER_ITERATIONS = 1000; - private static final double SELECTION_RATE = 0.05; - private static final List OUTCOMES = new ArrayList<>(); - - private final ProbabilisticSnapshotSelector selector = - new ProbabilisticSnapshotSelector(SELECTION_RATE); - - @RepeatedTest(ITERATIONS) - @Order(1) - void processTraces() { - int selected = 0; - for (int i = 0; i < TRACES_PER_ITERATIONS; i++) { - if (selector.select(Context.root())) { - selected++; - } - } - OUTCOMES.add(selected); - } - - @Test - @Order(2) - void evaluatePercentAllowed() { - assertEquals(SELECTION_RATE * 100, percentAllowed(), 1.0); - } - - private double percentAllowed() { - int allowed = OUTCOMES.stream().mapToInt(Integer::intValue).sum(); - int considered = TRACES_PER_ITERATIONS * OUTCOMES.size(); - return ((double) allowed / (double) (considered)) * 100; - } - - @Test - @Order(3) - @Disabled("flaky test") - void evaluateOutliers() { - assertThat(outliers()).isLessThan((int) (TRACES_PER_ITERATIONS * SELECTION_RATE)); - } - - private long outliers() { - double expectedSelectionsPerIteration = TRACES_PER_ITERATIONS * SELECTION_RATE; - int upper = (int) (expectedSelectionsPerIteration * 1.1); - int lower = (int) (expectedSelectionsPerIteration * .9); - return OUTCOMES.stream().filter(i -> i < lower || i > upper).count(); - } - - @Test - void selectRootTrace() { - var selector = new ProbabilisticSnapshotSelector(100.0); - assertThat(selector.select(Context.root())).isTrue(); - } - - @Test - void rejectRootTrace() { - var selector = new ProbabilisticSnapshotSelector(0.0); - assertThat(selector.select(Context.root())).isFalse(); - } - - @Test - void alwaysRejectWhenNotTraceRoot() { - var spanContext = Snapshotting.spanContext().remote().build(); - var parentSpan = Span.wrap(spanContext); - var context = Context.root().with(parentSpan); - - var selector = new ProbabilisticSnapshotSelector(100.0); - assertThat(selector.select(context)).isFalse(); - } -} diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingConfigurationCustomizerProviderTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingConfigurationCustomizerProviderTest.java index 8254d8fa8..bfcceeb59 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingConfigurationCustomizerProviderTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingConfigurationCustomizerProviderTest.java @@ -63,25 +63,6 @@ void shouldDoNothingIfProfilerIsNotEnabled(@TempDir Path tempDir) throws IOExcep assertThat(model.getTracerProvider()).isNull(); } - @Test - void shouldAddRequiredPropagator() { - // given - String yaml = - """ - file_format: "1.0" - distribution: - splunk: - profiling: - callgraphs: - """; - - // when - OpenTelemetryConfigurationModel model = getCustomizedModel(yaml); - - // then - assertThat(model.getPropagator().getCompositeList()).isEqualTo("splunk_snapshot_volume"); - } - @Test void shouldKeepPropagatorsDefinedInCompositeList() { // given @@ -101,8 +82,7 @@ void shouldKeepPropagatorsDefinedInCompositeList() { // then Set propagators = Set.of(model.getPropagator().getCompositeList().split(",")); - assertThat(propagators) - .isEqualTo(Set.of("propagator1", "propagator2", "splunk_snapshot_volume")); + assertThat(propagators).isEqualTo(Set.of("propagator1", "propagator2")); } @Test diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingFeatureFlagTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingFeatureFlagTest.java index 2f961e950..1946fb4d5 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingFeatureFlagTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingFeatureFlagTest.java @@ -38,7 +38,7 @@ class SnapshotProfilingDisabledByDefaultTest { @Test void snapshotProfilingIsDisabledByDefault(Tracer tracer) { - try (var ignored = Context.current().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.current().makeCurrent()) { var root = tracer.spanBuilder("root").startSpan(); assertThat(registry.isRegistered(root.getSpanContext())).isFalse(); } @@ -52,11 +52,12 @@ class SnapshotProfilingEnabledTest { OpenTelemetrySdkExtension.configure() .with(customizer) .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .build(); @Test void snapshotProfilingIsExplicitlyEnabled(Tracer tracer) { - try (var ignored = Context.current().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.current().makeCurrent()) { var root = tracer.spanBuilder("root").startSpan(); assertThat(registry.isRegistered(root.getSpanContext())).isTrue(); } @@ -74,7 +75,7 @@ class SnapshotProfilingDisabledTest { @Test void snapshotProfilingIsExplicitlyEnabled(Tracer tracer) { - try (var ignored = Context.current().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.current().makeCurrent()) { var root = tracer.spanBuilder("root").startSpan(); assertThat(registry.isRegistered(root.getSpanContext())).isFalse(); } diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingLogExportingTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingLogExportingTest.java index bfe440476..ee1b18bab 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingLogExportingTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingLogExportingTest.java @@ -58,6 +58,7 @@ class SnapshotProfilingLogExportingTest { public final OpenTelemetrySdkExtension sdk = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .with(customizer) .with( new StackTraceExporterActivator( @@ -73,7 +74,7 @@ void tearDown() { @Test void exportStackTracesForProfiledTraces(Tracer tracer) throws Exception { SpanContext spanContext; - try (var ignoredScope1 = Context.root().with(Volume.HIGHEST).makeCurrent()) { + try (var ignoredScope1 = Context.root().makeCurrent()) { var span = tracer.spanBuilder("root").startSpan(); try (var ignoredScope2 = span.makeCurrent()) { spanContext = span.getSpanContext(); diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSelectorTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSelectorTest.java deleted file mode 100644 index 6c004fdfa..000000000 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSelectorTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import static org.assertj.core.api.Assertions.assertThat; - -import io.opentelemetry.context.Context; -import java.util.stream.Stream; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -class SnapshotSelectorTest { - private static final SnapshotSelector TRUE = c -> true; - private static final SnapshotSelector FALSE = c -> false; - - @ParameterizedTest - @MethodSource("oneOrTheOther") - void orEvaluatesCorrectly(SnapshotSelector selector, boolean expected) { - var context = Context.root(); - assertThat(selector.select(context)).isEqualTo(expected); - } - - private static Stream oneOrTheOther() { - return Stream.of( - Arguments.of(TRUE.or(TRUE), true), - Arguments.of(TRUE.or(FALSE), true), - Arguments.of(FALSE.or(TRUE), true), - Arguments.of(FALSE.or(FALSE), false)); - } - - @Test - void orReturnsImmediatelyUponPositiveSelection() { - var context = Context.root(); - - var first = new ObservableSelector(TRUE); - var second = new ObservableSelector(TRUE); - var selector = first.or(second); - - assertThat(selector.select(context)).isTrue(); - assertThat(first.evaluated).isTrue(); - assertThat(second.evaluated).isFalse(); - } - - static class ObservableSelector implements SnapshotSelector { - private final SnapshotSelector selector; - private boolean evaluated = false; - - ObservableSelector(SnapshotSelector selector) { - this.selector = selector; - } - - @Override - public boolean select(Context context) { - evaluated = true; - return selector.select(context); - } - } -} diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSelectorTestTraceIds.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSelectorTestTraceIds.java index 3ef054c69..8652348e4 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSelectorTestTraceIds.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSelectorTestTraceIds.java @@ -25,29 +25,25 @@ /** * Maintains a collection of trace ids mapped to percentiles matching the probability calculation in - * {@link io.opentelemetry.sdk.trace.samplers.TraceIdRatioBasedSampler}. + * {@link com.splunk.opentelemetry.profiler.snapshot.TraceIdBasedSnapshotSelector}. * - *

A trace ID percentile is defined as the range of values existing between {@link - * Long#MAX_VALUE} * (percentile - 1 / 100) and {@link Long#MAX_VALUE} * (percentile / 100). A trace - * ID is placed within a percentile by using the {@link Long} representation of the last 16 - * characters of the trace id. When that long value is negative, the absolute value is used to find - * the percentile the trace id belongs to. + *

A trace ID percentile is defined as the range of values existing between SELECTION_RANGE * + * (percentile - 1 / 100) and SELECTION_RANGE * (percentile / 100). A trace ID is placed within a + * percentile by using the {@link Long} representation of the last 14 characters of the trace id. * *

  * Ex. For percentile 5 the range is considered to be:
- * lower = {@link Long#MAX_VALUE} * 0.04 = 368934881474191040
- * upper = {@link Long#MAX_VALUE} * 0.05 = 461168601842738816
+ * lower = SELECTION_RANGE * 0.04 = 10737418
+ * upper = SELECTION_RANGE * 0.05 = 13421772
  * 
* - *

A trace id is considered to be in the percentile range when the absolute value of second long - * in the trace id characters (as calculated using {@link - * io.opentelemetry.api.internal.OtelEncodingUtils#longFromBase16String(traceId, 16)}) is within the - * range. - * - * @see io.opentelemetry.sdk.trace.samplers.TraceIdRatioBasedSampler - * @see io.opentelemetry.api.internal.OtelEncodingUtils#longFromBase16String(CharSequence, int) + *

A trace id is considered to be in the percentile range when the 28 lower bits of the second + * long in the trace id characters is within the range. */ class SnapshotSelectorTestTraceIds { + // TraceIdBasedSnapshotSelector looks only at the lower 28 bits of the 128-bit trace-id value + private static final int SELECTION_RANGE = 1 << 28; + /** * Get trace ids known to be within the requested percentile. At least two trace ids will be * returned for each percentile representing the second long in the trace id being both positive @@ -65,124 +61,123 @@ static List forPercentile(int percentile) { private static final Map> TRACE_IDS = Map.ofEntries( - mapEntry(1, "00000000000000000143b39877726d4c", "0000000000000000febc4c67888d92b4"), - mapEntry(2, "00000000000000000148aaf1b30b99cd", "0000000000000000feb7550e4cf46633"), - mapEntry(3, "000000000000000002c619f84b6e3d6d", "0000000000000000fd39e607b491c293"), - mapEntry(4, "000000000000000003e90e2397e85e31", "0000000000000000fc16f1dc6817a1cf"), - mapEntry(5, "00000000000000000599e9374303b131", "0000000000000000fa6616c8bcfc4ecf"), - mapEntry(6, "000000000000000006b0fccea239c2b9", "0000000000000000f94f03315dc63d47"), - mapEntry(7, "000000000000000008ddd8dd0054e50f", "0000000000000000f7222722ffab1af1"), - mapEntry(8, "00000000000000000914a87beefb8944", "0000000000000000f6eb5784110476bc"), - mapEntry(9, "00000000000000000a81f147ae79b580", "0000000000000000f57e0eb851864a80"), - mapEntry(10, "00000000000000000c7a85e0e3f6e67e", "0000000000000000f3857a1f1c091982"), - mapEntry(11, "00000000000000000dd7c279626667d8", "0000000000000000f2283d869d999828"), - mapEntry(12, "00000000000000000f57cc320b3e215f", "0000000000000000f0a833cdf4c1dea1"), - mapEntry(13, "00000000000000000fe3a959597f1edf", "0000000000000000f01c56a6a680e121"), - mapEntry(14, "0000000000000000118124dcd62c13cd", "0000000000000000ee7edb2329d3ec33"), - mapEntry(15, "0000000000000000130ef512f84555b3", "0000000000000000ecf10aed07baaa4d"), - mapEntry(16, "0000000000000000141b67a6ec1e7670", "0000000000000000ebe4985913e18990"), - mapEntry(17, "00000000000000001585569f807b5f27", "0000000000000000ea7aa9607f84a0d9"), - mapEntry(18, "000000000000000015d637d48c22d1a2", "0000000000000000ea29c82b73dd2e5e"), - mapEntry(19, "0000000000000000179120b3146bc1dc", "0000000000000000e86edf4ceb943e24"), - mapEntry(20, "00000000000000001882dbfd7abfa5fb", "0000000000000000e77d240285405a05"), - mapEntry(21, "00000000000000001adaa7e91a829c90", "0000000000000000e5255816e57d6370"), - mapEntry(22, "00000000000000001b3b4b75dcb2bfa3", "0000000000000000e4c4b48a234d405d"), - mapEntry(23, "00000000000000001c4e3ee8733679ed", "0000000000000000e3b1c1178cc98613"), - mapEntry(24, "00000000000000001e603c290e5e580a", "0000000000000000e19fc3d6f1a1a7f6"), - mapEntry(25, "00000000000000001faa411f98ddc7cb", "0000000000000000e055bee067223835"), - mapEntry(26, "000000000000000020a5afbcd97e4120", "0000000000000000df5a50432681bee0"), - mapEntry(27, "00000000000000002209e46754395688", "0000000000000000ddf61b98abc6a978"), - mapEntry(28, "0000000000000000233bd49d8de75c71", "0000000000000000dcc42b627218a38f"), - mapEntry(29, "000000000000000023da35b710aee647", "0000000000000000dc25ca48ef5119b9"), - mapEntry(30, "000000000000000025d6512432116c49", "0000000000000000da29aedbcdee93b7"), - mapEntry(31, "00000000000000002676d70894ccaaf9", "0000000000000000d98928f76b335507"), - mapEntry(32, "000000000000000027b9015b4eee4f09", "0000000000000000d846fea4b111b0f7"), - mapEntry(33, "00000000000000002908c4007e983072", "0000000000000000d6f73bff8167cf8e"), - mapEntry(34, "00000000000000002a4e4a10d0eef684", "0000000000000000d5b1b5ef2f11097c"), - mapEntry(35, "00000000000000002caaa2529f376d41", "0000000000000000d3555dad60c892bf"), - mapEntry(36, "00000000000000002d777a1c645899f5", "0000000000000000d28885e39ba7660b"), - mapEntry(37, "00000000000000002ecf3ed7042fbbc9", "0000000000000000d130c128fbd04437"), - mapEntry(38, "00000000000000002ff45e5ddc9d52d6", "0000000000000000d00ba1a22362ad2a"), - mapEntry(39, "000000000000000030e16d4ebedf82f5", "0000000000000000cf1e92b141207d0b"), - mapEntry(40, "000000000000000032a03147ce4cc60a", "0000000000000000cd5fceb831b339f6"), - mapEntry(41, "0000000000000000345e2f0cbdce2196", "0000000000000000cba1d0f34231de6a"), - mapEntry(42, "000000000000000034f65c111fb8e190", "0000000000000000cb09a3eee0471e70"), - mapEntry(43, "00000000000000003679137f3515a89b", "0000000000000000c986ec80caea5765"), - mapEntry(44, "00000000000000003723c78599aa8203", "0000000000000000c8dc387a66557dfd"), - mapEntry(45, "0000000000000000396dd313445b8dea", "0000000000000000c6922cecbba47216"), - mapEntry(46, "00000000000000003aa7691ef0edc188", "0000000000000000c55896e10f123e78"), - mapEntry(47, "00000000000000003bb404785110eb8c", "0000000000000000c44bfb87aeef1474"), - mapEntry(48, "00000000000000003ca55c229d93ce23", "0000000000000000c35aa3dd626c31dd"), - mapEntry(49, "00000000000000003d82411baa8640cd", "0000000000000000c27dbee45579bf33"), - mapEntry(50, "00000000000000003edb9eb17d582b29", "0000000000000000c124614e82a7d4d7"), - mapEntry(51, "0000000000000000405bfc65c6b9fe1e", "0000000000000000bfa4039a394601e2"), - mapEntry(52, "000000000000000041d75c3fa386fee6", "0000000000000000be28a3c05c79011a"), - mapEntry(53, "0000000000000000437c32176ead3933", "0000000000000000bc83cde89152c6cd"), - mapEntry(54, "0000000000000000441eae96cca9b1ab", "0000000000000000bbe1516933564e55"), - mapEntry(55, "000000000000000045ad0089da3cad48", "0000000000000000ba52ff7625c352b8"), - mapEntry(56, "0000000000000000469b0599b4b42b74", "0000000000000000b964fa664b4bd48c"), - mapEntry(57, "0000000000000000483c973d7219ee64", "0000000000000000b7c368c28de6119c"), - mapEntry(58, "00000000000000004a2414453cee6677", "0000000000000000b5dbebbac3119989"), - mapEntry(59, "00000000000000004adb3965a6cbec2d", "0000000000000000b524c69a593413d3"), - mapEntry(60, "00000000000000004c6f922c7949ede4", "0000000000000000b3906dd386b6121c"), - mapEntry(61, "00000000000000004df5f13e05aa5613", "0000000000000000b20a0ec1fa55a9ed"), - mapEntry(62, "00000000000000004f35fe02b3e7e461", "0000000000000000b0ca01fd4c181b9f"), - mapEntry(63, "000000000000000050162d60064273fc", "0000000000000000afe9d29ff9bd8c04"), - mapEntry(64, "000000000000000050b68a04f001e2d7", "0000000000000000af4975fb0ffe1d29"), - mapEntry(65, "0000000000000000533189021ef11943", "0000000000000000acce76fde10ee6bd"), - mapEntry(66, "0000000000000000534cecedf1b7d6a6", "0000000000000000acb313120e48295a"), - mapEntry(67, "000000000000000055b2bd9c1c657001", "0000000000000000aa4d4263e39a8fff"), - mapEntry(68, "0000000000000000567949e730f262b2", "0000000000000000a986b618cf0d9d4e"), - mapEntry(69, "000000000000000057199fe8bc4ef161", "0000000000000000a8e6601743b10e9f"), - mapEntry(70, "000000000000000058cc4d0b1d6b01b5", "0000000000000000a733b2f4e294fe4b"), - mapEntry(71, "000000000000000059c19e1a3e2f6ca8", "0000000000000000a63e61e5c1d09358"), - mapEntry(72, "00000000000000005af1551116b3dbff", "0000000000000000a50eaaeee94c2401"), - mapEntry(73, "00000000000000005c7017b8f295b9b1", "0000000000000000a38fe8470d6a464f"), - mapEntry(74, "00000000000000005e4d3841617b60dd", "0000000000000000a1b2c7be9e849f23"), - mapEntry(75, "00000000000000005ee8f85e75a427d7", "0000000000000000a11707a18a5bd829"), - mapEntry(76, "00000000000000006093d2d520cc6e90", "00000000000000009f6c2d2adf339170"), - mapEntry(77, "00000000000000006203192ebaae234f", "00000000000000009dfce6d14551dcb1"), - mapEntry(78, "0000000000000000630c2fda50a965e4", "00000000000000009cf3d025af569a1c"), - mapEntry(79, "000000000000000064f5e269e2e24f20", "00000000000000009b0a1d961d1db0e0"), - mapEntry(80, "000000000000000065c9fa9afb7fd35e", "00000000000000009a36056504802ca2"), - mapEntry(81, "000000000000000066cb4ee73ce16f2a", "00000000000000009934b118c31e90d6"), - mapEntry(82, "0000000000000000683fbf3468ca8a54", "000000000000000097c040cb973575ac"), - mapEntry(83, "00000000000000006a3a8d3da082a9c7", "000000000000000095c572c25f7d5639"), - mapEntry(84, "00000000000000006aab99065ac9ddcc", "0000000000000000955466f9a5362234"), - mapEntry(85, "00000000000000006bde934c09acdcee", "000000000000000094216cb3f6532312"), - mapEntry(86, "00000000000000006d6d8a23eead7196", "0000000000000000929275dc11528e6a"), - mapEntry(87, "00000000000000006ee8e3f10829c598", "000000000000000091171c0ef7d63a68"), - mapEntry(88, "00000000000000006ff553d6a3a7c64f", "0000000000000000900aac295c5839b1"), - mapEntry(89, "000000000000000070ec301873be78ec", "00000000000000008f13cfe78c418714"), - mapEntry(90, "00000000000000007300000232767805", "00000000000000008cfffffdcd8987fb"), - mapEntry(91, "00000000000000007433d290acdedde0", "00000000000000008bcc2d6f53212220"), - mapEntry(92, "0000000000000000758737145b360ecb", "00000000000000008a78c8eba4c9f135"), - mapEntry(93, "0000000000000000770083adadec9c20", "000000000000000088ff7c52521363e0"), - mapEntry(94, "000000000000000077bb30dfbf5a4ac2", "00000000000000008844cf2040a5b53e"), - mapEntry(95, "0000000000000000797f17c4c31bdc02", "00000000000000008680e83b3ce423fe"), - mapEntry(96, "00000000000000007acff0cd846071a3", "000000000000000085300f327b9f8e5d"), - mapEntry(97, "00000000000000007c0554b910135b0d", "000000000000000083faab46efeca4f3"), - mapEntry(98, "00000000000000007c61f93693043865", "0000000000000000839e06c96cfbc79b"), - mapEntry(99, "00000000000000007d841f140bf3625b", "0000000000000000827be0ebf40c9da5")); + mapEntry(1, "00000000000000000000000000209d27", "0000000000000000000000000027a91d"), + mapEntry(2, "000000000000000000000000003a269a", "000000000000000000000000002c3ecc"), + mapEntry(3, "00000000000000000000000000587789", "000000000000000000000000005b87fe"), + mapEntry(4, "00000000000000000000000000982d38", "00000000000000000000000000918baa"), + mapEntry(5, "00000000000000000000000000c04436", "00000000000000000000000000be2039"), + mapEntry(6, "00000000000000000000000000e6fbd2", "00000000000000000000000000d39f04"), + mapEntry(7, "0000000000000000000000000100222c", "000000000000000000000000011d04b6"), + mapEntry(8, "000000000000000000000000013a8c30", "00000000000000000000000001361b6d"), + mapEntry(9, "000000000000000000000000015f9f64", "0000000000000000000000000151646a"), + mapEntry(10, "00000000000000000000000001752030", "000000000000000000000000018b5787"), + mapEntry(11, "00000000000000000000000001b750c6", "00000000000000000000000001c059d3"), + mapEntry(12, "00000000000000000000000001d11c72", "00000000000000000000000001e376de"), + mapEntry(13, "00000000000000000000000001f08d5a", "0000000000000000000000000204c9fb"), + mapEntry(14, "00000000000000000000000002347a35", "0000000000000000000000000214a27e"), + mapEntry(15, "000000000000000000000000024d2306", "0000000000000000000000000259ec24"), + mapEntry(16, "00000000000000000000000002716a58", "000000000000000000000000027e25c7"), + mapEntry(17, "00000000000000000000000002aac8f5", "0000000000000000000000000291b571"), + mapEntry(18, "00000000000000000000000002c24e43", "00000000000000000000000002bc4e2d"), + mapEntry(19, "00000000000000000000000002fcbf2a", "00000000000000000000000002f4e764"), + mapEntry(20, "0000000000000000000000000324ce3a", "000000000000000000000000033293e4"), + mapEntry(21, "0000000000000000000000000335ae6b", "0000000000000000000000000358cb7f"), + mapEntry(22, "000000000000000000000000037cd58b", "000000000000000000000000036bdbfc"), + mapEntry(23, "000000000000000000000000038d056c", "000000000000000000000000039b559c"), + mapEntry(24, "00000000000000000000000003bee8f2", "00000000000000000000000003c7f0e3"), + mapEntry(25, "00000000000000000000000003e77be6", "00000000000000000000000003f249b1"), + mapEntry(26, "00000000000000000000000004220e60", "000000000000000000000000042389b1"), + mapEntry(27, "000000000000000000000000043ddf33", "0000000000000000000000000441f2da"), + mapEntry(28, "00000000000000000000000004700385", "000000000000000000000000046b4412"), + mapEntry(29, "0000000000000000000000000487853d", "000000000000000000000000048008d7"), + mapEntry(30, "00000000000000000000000004ac4ece", "00000000000000000000000004aaad0b"), + mapEntry(31, "00000000000000000000000004df8325", "00000000000000000000000004e98cbe"), + mapEntry(32, "00000000000000000000000005173694", "000000000000000000000000050def4d"), + mapEntry(33, "0000000000000000000000000540c99a", "000000000000000000000000054418d2"), + mapEntry(34, "0000000000000000000000000558bf3b", "000000000000000000000000054e30d0"), + mapEntry(35, "00000000000000000000000005809404", "00000000000000000000000005956530"), + mapEntry(36, "00000000000000000000000005c0e2f6", "00000000000000000000000005a5f331"), + mapEntry(37, "00000000000000000000000005d4f283", "00000000000000000000000005dcd0ab"), + mapEntry(38, "00000000000000000000000006030db4", "00000000000000000000000005f1f580"), + mapEntry(39, "0000000000000000000000000628a56f", "000000000000000000000000061ce55b"), + mapEntry(40, "0000000000000000000000000659af9d", "0000000000000000000000000642e003"), + mapEntry(41, "00000000000000000000000006739770", "0000000000000000000000000674eca0"), + mapEntry(42, "000000000000000000000000069a041b", "00000000000000000000000006b6a03a"), + mapEntry(43, "00000000000000000000000006d5a52c", "00000000000000000000000006c5a423"), + mapEntry(44, "00000000000000000000000006e3d905", "00000000000000000000000007078393"), + mapEntry(45, "000000000000000000000000071f4bce", "00000000000000000000000007228cf3"), + mapEntry(46, "000000000000000000000000074e0b07", "00000000000000000000000007581aba"), + mapEntry(47, "000000000000000000000000076db61f", "000000000000000000000000076bb44e"), + mapEntry(48, "00000000000000000000000007897a80", "000000000000000000000000079e61a0"), + mapEntry(49, "00000000000000000000000007bdc92c", "00000000000000000000000007cf73eb"), + mapEntry(50, "00000000000000000000000007d721eb", "00000000000000000000000007e27553"), + mapEntry(51, "0000000000000000000000000807f57c", "000000000000000000000000080e5e54"), + mapEntry(52, "00000000000000000000000008448b48", "000000000000000000000000084c3b38"), + mapEntry(53, "00000000000000000000000008560c03", "00000000000000000000000008698617"), + mapEntry(54, "000000000000000000000000089c219e", "0000000000000000000000000884faef"), + mapEntry(55, "00000000000000000000000008a91de0", "00000000000000000000000008b0ea40"), + mapEntry(56, "00000000000000000000000008f57f98", "00000000000000000000000008d976c0"), + mapEntry(57, "00000000000000000000000008fcb88b", "0000000000000000000000000902ca7b"), + mapEntry(58, "00000000000000000000000009444897", "00000000000000000000000009387b84"), + mapEntry(59, "00000000000000000000000009547645", "000000000000000000000000096d9006"), + mapEntry(60, "00000000000000000000000009934905", "000000000000000000000000098e0e28"), + mapEntry(61, "00000000000000000000000009b814fd", "00000000000000000000000009c04915"), + mapEntry(62, "00000000000000000000000009d33446", "00000000000000000000000009c46df9"), + mapEntry(63, "0000000000000000000000000a102bc6", "00000000000000000000000009f1eb48"), + mapEntry(64, "0000000000000000000000000a22c9af", "0000000000000000000000000a3424b5"), + mapEntry(65, "0000000000000000000000000a591261", "0000000000000000000000000a4fe3d7"), + mapEntry(66, "0000000000000000000000000a78d37d", "0000000000000000000000000a6f1a96"), + mapEntry(67, "0000000000000000000000000a9c1b2e", "0000000000000000000000000ab30f4e"), + mapEntry(68, "0000000000000000000000000acb1dd7", "0000000000000000000000000adacc63"), + mapEntry(69, "0000000000000000000000000aee5d2d", "0000000000000000000000000b075d61"), + mapEntry(70, "0000000000000000000000000b245fe6", "0000000000000000000000000b21bb2c"), + mapEntry(71, "0000000000000000000000000b4fa6e5", "0000000000000000000000000b53022a"), + mapEntry(72, "0000000000000000000000000b61ceed", "0000000000000000000000000b7c97c6"), + mapEntry(73, "0000000000000000000000000b8c94c7", "0000000000000000000000000b9399d6"), + mapEntry(74, "0000000000000000000000000bced4f0", "0000000000000000000000000bc0c8fd"), + mapEntry(75, "0000000000000000000000000bdc3cf3", "0000000000000000000000000bf5659c"), + mapEntry(76, "0000000000000000000000000c1fb9fb", "0000000000000000000000000c0e2a7c"), + mapEntry(77, "0000000000000000000000000c4c2b6f", "0000000000000000000000000c2b2c62"), + mapEntry(78, "0000000000000000000000000c59724c", "0000000000000000000000000c79fbd3"), + mapEntry(79, "0000000000000000000000000c820326", "0000000000000000000000000c9aa100"), + mapEntry(80, "0000000000000000000000000ca4daef", "0000000000000000000000000cabca09"), + mapEntry(81, "0000000000000000000000000cce8c41", "0000000000000000000000000cefba44"), + mapEntry(82, "0000000000000000000000000d1e1bd3", "0000000000000000000000000d155488"), + mapEntry(83, "0000000000000000000000000d1f9610", "0000000000000000000000000d378273"), + mapEntry(84, "0000000000000000000000000d5c1735", "0000000000000000000000000d6a2dbb"), + mapEntry(85, "0000000000000000000000000d7c3863", "0000000000000000000000000d866d9d"), + mapEntry(86, "0000000000000000000000000db23d8c", "0000000000000000000000000da49dc5"), + mapEntry(87, "0000000000000000000000000deb6b81", "0000000000000000000000000de4e54a"), + mapEntry(88, "0000000000000000000000000e0021c7", "0000000000000000000000000e13d1ef"), + mapEntry(89, "0000000000000000000000000e385cd2", "0000000000000000000000000e1ff154"), + mapEntry(90, "0000000000000000000000000e4eea14", "0000000000000000000000000e510a37"), + mapEntry(91, "0000000000000000000000000e8bdd8c", "0000000000000000000000000e8c190b"), + mapEntry(92, "0000000000000000000000000e9c58e0", "0000000000000000000000000e9c0501"), + mapEntry(93, "0000000000000000000000000edcea53", "0000000000000000000000000ed2fb19"), + mapEntry(94, "0000000000000000000000000ef3d070", "0000000000000000000000000ee90679"), + mapEntry(95, "0000000000000000000000000f29177a", "0000000000000000000000000f2f72b0"), + mapEntry(96, "0000000000000000000000000f39cc43", "0000000000000000000000000f4a5ad1"), + mapEntry(97, "0000000000000000000000000f5ce953", "0000000000000000000000000f6272ae"), + mapEntry(98, "0000000000000000000000000fa7290d", "0000000000000000000000000fad85af"), + mapEntry(99, "0000000000000000000000000fb567d2", "0000000000000000000000000fd17054")); private static Map.Entry> mapEntry(int percentile, String... traceIds) { return Map.entry(percentile, List.of(traceIds)); } /** - * Generates a map of percentiles to trace ids that will pass the sampling check in {@link - * io.opentelemetry.sdk.trace.samplers.TraceIdRatioBasedSampler} when the corresponding - * probability is used (e.g., 5th percentile and 0.05). + * Generates a map of percentiles to trace ids that will pass the selection check when the + * corresponding probability is used (e.g., 5th percentile and 0.05). */ public static void main(String[] args) { var map = new LinkedHashMap>(); for (int percentile = 1; percentile <= 99; percentile++) { - long lower = (long) (Long.MAX_VALUE * ((double) (percentile - 1) / 100)); - long upper = (long) (Long.MAX_VALUE * ((double) (percentile) / 100)); + long lower = (long) (SELECTION_RANGE * ((double) (percentile - 1) / 100)); + long upper = (long) (SELECTION_RANGE * ((double) (percentile) / 100)); - var random = new Random().nextLong(lower + 1, upper); - // TraceIdRatioBasedSampler only considers the second number so OK to leave as 0 - map.put(percentile, List.of(TraceId.fromLongs(0, random), TraceId.fromLongs(0, -random))); + var random1 = new Random().nextLong(lower + 1, upper); + var random2 = new Random().nextLong(lower + 1, upper); + map.put(percentile, List.of(TraceId.fromLongs(0, random1), TraceId.fromLongs(0, random2))); } System.out.println(asJavaCode(map)); } diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSpanAttributeTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSpanAttributeTest.java index 34fba8b25..865be857f 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSpanAttributeTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotSpanAttributeTest.java @@ -38,11 +38,12 @@ class SnapshotSpanAttributeTest { OpenTelemetrySdkExtension.configure() .with(customizer) .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .build(); @Test void addSnapshotSpanAttributeToEntrySpans(Tracer tracer) { - try (var ignored = Context.root().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.root().makeCurrent()) { var span = (ReadWriteSpan) tracer.spanBuilder("root").startSpan(); var attribute = span.getAttribute(AttributeKey.booleanKey("splunk.snapshot.profiling")); assertThat(attribute).isTrue(); @@ -51,7 +52,7 @@ void addSnapshotSpanAttributeToEntrySpans(Tracer tracer) { @Test void doNotAddSnapshotSpanAttributeToNonEntrySpans(Tracer tracer) { - try (var ignored1 = Context.root().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored1 = Context.root().makeCurrent()) { var root = tracer.spanBuilder("root").startSpan(); try (var ignored2 = root.makeCurrent()) { var client = (ReadWriteSpan) tracer.spanBuilder("client").startSpan(); @@ -63,7 +64,7 @@ void doNotAddSnapshotSpanAttributeToNonEntrySpans(Tracer tracer) { @Test void addSnapshotSpanAttributeToAllEntrySpans(Tracer tracer) { - try (var ignored1 = Context.root().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored1 = Context.root().makeCurrent()) { try (var ignored2 = tracer.spanBuilder("root").startSpan().makeCurrent()) { var client = tracer.spanBuilder("client").startSpan(); try (var ignored3 = client.makeCurrent()) { @@ -85,7 +86,7 @@ void addSnapshotSpanAttributeToAllEntrySpans(Tracer tracer) { void doNotAddSnapshotSpanAttributeWhenTraceIsNotRegisteredForSnapshotting(Tracer tracer) { registry.toggle(State.OFF); - try (var ignored = Context.root().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.root().makeCurrent()) { var span = (ReadWriteSpan) tracer.spanBuilder("root").startSpan(); var attribute = span.getAttribute(AttributeKey.booleanKey("splunk.snapshot.profiling")); assertThat(attribute).isNull(); diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorComponentProviderTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorComponentProviderTest.java deleted file mode 100644 index d49deb51e..000000000 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorComponentProviderTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import static com.splunk.opentelemetry.testing.declarativeconfig.DeclarativeConfigTestUtil.getProfilingConfig; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -import com.splunk.opentelemetry.testing.declarativeconfig.DeclarativeConfigTestUtil; -import io.opentelemetry.api.incubator.config.DeclarativeConfigException; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.context.propagation.TextMapPropagator; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -class SnapshotVolumePropagatorComponentProviderTest { - @AfterEach - void tearDown() { - SnapshotProfilingDeclarativeConfiguration.SUPPLIER.reset(); - } - - @Test - void shouldThrowExceptionWhenProfilingNotConfigured() { - // given - SnapshotVolumePropagatorComponentProvider propagatorProvider = - new SnapshotVolumePropagatorComponentProvider(); - - // when - assertThatThrownBy(() -> propagatorProvider.create(null)) - .isInstanceOf(DeclarativeConfigException.class); - } - - @Test - void shouldCreatePropagatorWithDefaultSelectionProbabilityWhenNotProvided() { - // given - var yaml = - """ - file_format: "1.0" - distribution: - splunk: - profiling: - callgraphs: - """; - var configurationModel = DeclarativeConfigTestUtil.parse(yaml); - DeclarativeConfigProperties profilingConfig = getProfilingConfig(configurationModel); - SnapshotProfilingDeclarativeConfiguration.SUPPLIER.configure( - new SnapshotProfilingDeclarativeConfiguration(profilingConfig)); - - SnapshotVolumePropagatorComponentProvider propagatorProvider = - new SnapshotVolumePropagatorComponentProvider(); - propagatorProvider = spy(propagatorProvider); - - // when - TextMapPropagator propagator = propagatorProvider.create(null); - - // then - assertThat(propagator).isNotNull(); - assertThat(propagator).isInstanceOf(SnapshotVolumePropagator.class); - verify(propagatorProvider) - .selector(SnapshotProfilingConfiguration.DEFAULT_SELECTION_PROBABILITY); - } - - @Test - void shouldCreatePropagatorWithProvidedValidSelectionProbability() { - // given - var yaml = - """ - file_format: "1.0" - distribution: - splunk: - profiling: - callgraphs: - selection_probability: 0.123 - """; - var configurationModel = DeclarativeConfigTestUtil.parse(yaml); - DeclarativeConfigProperties profilingConfig = getProfilingConfig(configurationModel); - SnapshotProfilingDeclarativeConfiguration.SUPPLIER.configure( - new SnapshotProfilingDeclarativeConfiguration(profilingConfig)); - - SnapshotVolumePropagatorComponentProvider propagatorProvider = - new SnapshotVolumePropagatorComponentProvider(); - propagatorProvider = spy(propagatorProvider); - - // when - TextMapPropagator propagator = propagatorProvider.create(null); - - // then - assertThat(propagator).isNotNull(); - assertThat(propagator).isInstanceOf(SnapshotVolumePropagator.class); - verify(propagatorProvider).selector(0.123); - } -} diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorProviderTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorProviderTest.java deleted file mode 100644 index 75df3e504..000000000 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorProviderTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.common.ComponentLoader; -import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.stream.IntStream; -import java.util.stream.Stream; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -class SnapshotVolumePropagatorProviderTest { - private static final ComponentLoader COMPONENT_LOADER = - ComponentLoader.forClassLoader(SnapshotVolumePropagatorProviderTest.class.getClassLoader()); - private final SnapshotVolumePropagatorProvider provider = new SnapshotVolumePropagatorProvider(); - - @Test - void provideSnapshotVolumePropagator() { - var propagator = - provider.getPropagator( - DefaultConfigProperties.create(Collections.emptyMap(), COMPONENT_LOADER)); - assertInstanceOf(SnapshotVolumePropagator.class, propagator); - } - - @Test - void name() { - assertEquals("splunk-snapshot", provider.getName()); - } - - /** Has a roughly 0.0025% chance to fail. */ - @Test - void probabilisticSelectorIsConfigured() { - var properties = - DefaultConfigProperties.create( - Map.of("splunk.snapshot.selection.probability", "0.10"), COMPONENT_LOADER); - - var carrier = new ObservableCarrier(); - var propagator = provider.getPropagator(properties); - - var volumes = new ArrayList(); - for (int i = 0; i < 100; i++) { - var contextFromPropagator = propagator.extract(Context.root(), carrier, carrier); - var volume = Volume.from(contextFromPropagator); - volumes.add(volume); - } - - assertThat(volumes).contains(Volume.HIGHEST); - } - - @ParameterizedTest - @MethodSource("traceIdsToSelect") - void traceIdSelectorIsConfigured(String traceId) { - var properties = - DefaultConfigProperties.create( - Map.of("splunk.snapshot.selection.probability", "0.10"), COMPONENT_LOADER); - - var remoteSpanContext = Snapshotting.spanContext().withTraceId(traceId).remote().build(); - var remoteParentSpan = Span.wrap(remoteSpanContext); - var context = Context.root().with(remoteParentSpan); - - var carrier = new ObservableCarrier(); - var propagator = provider.getPropagator(properties); - var contextFromPropagator = propagator.extract(context, carrier, carrier); - var volume = Volume.from(contextFromPropagator); - - assertEquals(Volume.HIGHEST, volume); - } - - private static Stream traceIdsToSelect() { - return IntStream.range(1, 11) - .mapToObj(SnapshotSelectorTestTraceIds::forPercentile) - .flatMap(Collection::stream); - } -} diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorTest.java deleted file mode 100644 index 5f6ba559e..000000000 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotVolumePropagatorTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.splunk.opentelemetry.profiler.snapshot.SnapshotVolumePropagatorTest.ToggleableSnapshotSelector.State; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import java.util.Collections; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.junit.jupiter.params.provider.EnumSource.Mode; - -class SnapshotVolumePropagatorTest { - @RegisterExtension public final ObservableCarrier carrier = new ObservableCarrier(); - - private final ToggleableSnapshotSelector selector = new ToggleableSnapshotSelector(); - private final SnapshotVolumePropagator propagator = new SnapshotVolumePropagator(selector); - - @Test - void propagatorDoesNotReportAnyFields() { - assertEquals(Collections.emptyList(), propagator.fields()); - } - - @Test - void selectTraceForSnapshottingByAttachingHighestVolumeToBaggage() { - selector.toggle(State.ON); - - var contextFromPropagator = propagator.extract(Context.root(), carrier, carrier); - - var volume = Volume.from(contextFromPropagator); - assertEquals(Volume.HIGHEST, volume); - } - - @Test - void rejectTraceForSnapshottingByAttachingOffVolumeToBaggage() { - selector.toggle(State.OFF); - - var contextFromPropagator = propagator.extract(Context.root(), carrier, carrier); - - var volume = Volume.from(contextFromPropagator); - assertEquals(Volume.OFF, volume); - } - - @ParameterizedTest - @EnumSource(value = Volume.class, mode = Mode.EXCLUDE, names = "UNSPECIFIED") - void retainTraceSelectionDecisionFromUpstreamServices(Volume volume) { - var spanContext = Snapshotting.spanContext().remote().build(); - var parentSpan = Span.wrap(spanContext); - var context = Context.root().with(parentSpan).with(volume); - - var contextFromPropagator = propagator.extract(context, carrier, carrier); - - var volumeFromContext = Volume.from(contextFromPropagator); - assertEquals(volume, volumeFromContext); - } - - @Test - void selectTraceForSnapshottingDecisionLeftUndecidedAndTraceIsSelected() { - selector.toggle(State.ON); - - var spanContext = Snapshotting.spanContext().remote().build(); - var parentSpan = Span.wrap(spanContext); - var context = Context.root().with(parentSpan); - - var contextFromPropagator = propagator.extract(context, carrier, carrier); - - var volumeFromContext = Volume.from(contextFromPropagator); - assertEquals(Volume.HIGHEST, volumeFromContext); - } - - @Test - void rejectTraceForSnapshottingWhenDecisionLeftUndecidedButTraceIsRejected() { - selector.toggle(State.OFF); - - var spanContext = Snapshotting.spanContext().remote().build(); - var parentSpan = Span.wrap(spanContext); - var context = Context.root().with(parentSpan); - - var contextFromPropagator = propagator.extract(context, carrier, carrier); - - var volumeFromContext = Volume.from(contextFromPropagator); - assertEquals(Volume.OFF, volumeFromContext); - } - - static class ToggleableSnapshotSelector implements SnapshotSelector { - enum State { - ON, - OFF - } - - private State state = State.ON; - - @Override - public boolean select(Context context) { - return state == State.ON; - } - - void toggle(State state) { - this.state = state; - } - } -} diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SpanSamplingTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SpanSamplingTest.java index 2b85fb4e7..ff5a28281 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SpanSamplingTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SpanSamplingTest.java @@ -37,13 +37,14 @@ class SpanSamplingDisabled { public final OpenTelemetrySdkExtension s = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .withSampler(Sampler.alwaysOff()) .with(customizer) .build(); @Test void doNotRegisterTraceForProfilingWhenSpanSamplingIsOff(Tracer tracer) { - try (var ignored = Context.current().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.current().makeCurrent()) { var root = tracer.spanBuilder("root").startSpan(); assertThat(registry.isRegistered(root.getSpanContext())).isFalse(); } @@ -56,13 +57,14 @@ class SpanSamplingEnabled { public final OpenTelemetrySdkExtension s = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .withSampler(Sampler.alwaysOn()) .with(customizer) .build(); @Test void registerTraceForProfilingWhenSpanSamplingIsOn(Tracer tracer) { - try (var ignored = Context.current().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.current().makeCurrent()) { var root = tracer.spanBuilder("root").startSpan(); assertThat(registry.isRegistered(root.getSpanContext())).isTrue(); } diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceIdBasedSnapshotSelectorTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceIdBasedSnapshotSelectorTest.java index a92a6fabe..a1d95d7eb 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceIdBasedSnapshotSelectorTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceIdBasedSnapshotSelectorTest.java @@ -19,8 +19,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; import java.util.List; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -38,21 +36,20 @@ void requireSelectionRateBetween0_0And1_0(double selectionRate) { } @Test - void doNotSelectTraceWhenRoot() { - var context = Context.root(); - var selector = new TraceIdBasedSnapshotSelector(0.05); - assertThat(selector.select(context)).isFalse(); + void doSelectTraceWhenRoot() { + var spanContext = + Snapshotting.spanContext().withTraceId("00000000000000004adb3965a6cbec2d").build(); + var selector = new TraceIdBasedSnapshotSelector(1.0); + assertThat(selector.select(spanContext)).isTrue(); } @ParameterizedTest @MethodSource("traceIdsToSelect") void selectTraceWhenTraceIdIsComputedToBeLessThanOrEqualToSelectionRate(String traceId) { var spanContext = Snapshotting.spanContext().withTraceId(traceId).build(); - var span = Span.wrap(spanContext); - var context = Context.root().with(span); var selector = new TraceIdBasedSnapshotSelector(0.05); - assertThat(selector.select(context)).isTrue(); + assertThat(selector.select(spanContext)).isTrue(); } private static Stream traceIdsToSelect() { @@ -65,11 +62,9 @@ private static Stream traceIdsToSelect() { @MethodSource("traceIdsToNotSelect") void doNotSelectTraceWhenTraceIdIsComputedToBeMoreThanSelectionRate(String traceId) { var spanContext = Snapshotting.spanContext().withTraceId(traceId).build(); - var span = Span.wrap(spanContext); - var context = Context.root().with(span); var selector = new TraceIdBasedSnapshotSelector(0.05); - assertThat(selector.select(context)).isFalse(); + assertThat(selector.select(spanContext)).isFalse(); } private static Stream traceIdsToNotSelect() { diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceProfilingTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceProfilingTest.java index babfd9a0b..4022c6fe2 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceProfilingTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceProfilingTest.java @@ -37,12 +37,13 @@ class TraceProfilingTest { public final OpenTelemetrySdkExtension sdk = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .with(customizer) .build(); @Test void startTraceProfilingWhenRootSpanContextBegins(Tracer tracer) { - try (var ignored = Context.root().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.root().makeCurrent()) { var span = tracer.spanBuilder("root").startSpan(); try (var ignored2 = span.makeCurrent()) { assertThat(sampler.isBeingSampled(span.getSpanContext())).isTrue(); @@ -63,7 +64,7 @@ void startTraceProfilingWhenDownstreamSpanContextBegins(Tracer tracer) { var remoteParentSpanContext = Snapshotting.spanContext().remote().build(); var parentSpan = Span.wrap(remoteParentSpanContext); - try (var ignored = Context.root().with(Volume.HIGHEST).with(parentSpan).makeCurrent()) { + try (var ignored = Context.root().with(parentSpan).makeCurrent()) { var span = tracer.spanBuilder("root").startSpan(); try (var ignored2 = span.makeCurrent()) { assertThat(sampler.isBeingSampled(span.getSpanContext())).isTrue(); @@ -84,7 +85,7 @@ void doNotStartTraceProfilingInDownstreamServicesWhenTraceHasNotBeenSelected(Tra @Test void stopTraceProfilingWhenEntrySpanEnds(Tracer tracer) { - try (var ignored = Context.root().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.root().makeCurrent()) { var entry = tracer.spanBuilder("entry").startSpan(); entry.end(); assertThat(sampler.isBeingSampled(entry.getSpanContext())).isFalse(); @@ -93,7 +94,7 @@ void stopTraceProfilingWhenEntrySpanEnds(Tracer tracer) { @Test void canStopTraceProfilingFromDifferentThread(Tracer tracer) throws Exception { - try (var ignored = Context.root().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.root().makeCurrent()) { var entry = tracer.spanBuilder("entry").startSpan(); var endingThread = new Thread(entry::end); @@ -108,7 +109,7 @@ void canStopTraceProfilingFromDifferentThread(Tracer tracer) throws Exception { void doNotStartTraceProfilingWhenTraceIsNotRegistered(Tracer tracer) { registry.toggle(State.OFF); - try (var ignored = Context.root().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.root().makeCurrent()) { var root = tracer.spanBuilder("root").setSpanKind(SpanKind.SERVER).startSpan(); var client = tracer @@ -123,7 +124,7 @@ void doNotStartTraceProfilingWhenTraceIsNotRegistered(Tracer tracer) { @Test void onlyStopTraceProfilingWhenEntrySpanContextCloses(Tracer tracer) { - try (var ignored = Context.root().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.root().makeCurrent()) { var root = tracer.spanBuilder("root").setSpanKind(SpanKind.SERVER).startSpan(); try (var ignoredRootContext = root.makeCurrent()) { var child = diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceRegistrationTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceRegistrationTest.java index 56a15b9a8..f2ca277f7 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceRegistrationTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/TraceRegistrationTest.java @@ -34,12 +34,13 @@ class TraceRegistrationTest { public final OpenTelemetrySdkExtension s = OpenTelemetrySdkExtension.configure() .withProperty("splunk.snapshot.profiler.enabled", "true") + .withProperty("splunk.snapshot.selection.probability", "1.0") .with(customizer) .build(); @Test void registerTraceForProfilingWhenRootSpanStarts(Tracer tracer) { - try (var ignored = Context.current().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.current().makeCurrent()) { var root = tracer.spanBuilder("root").startSpan(); assertThat(registry.isRegistered(root.getSpanContext())).isTrue(); } @@ -50,7 +51,7 @@ void registerTraceForProfilingWhenDownstreamEntryStarts(Tracer tracer) { var remoteSpanContext = Snapshotting.spanContext().remote().build(); var remoteParent = Span.wrap(remoteSpanContext); - try (var ignored = Context.current().with(Volume.HIGHEST).with(remoteParent).makeCurrent()) { + try (var ignored = Context.current().with(remoteParent).makeCurrent()) { var root = tracer.spanBuilder("root").startSpan(); assertThat(registry.isRegistered(root.getSpanContext())).isTrue(); } @@ -58,7 +59,7 @@ void registerTraceForProfilingWhenDownstreamEntryStarts(Tracer tracer) { @Test void unregisterTraceForProfilingWhenEntrySpanEnds(Tracer tracer) { - try (var ignored = Context.current().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.current().makeCurrent()) { var root = tracer.spanBuilder("root").startSpan(); root.end(); assertThat(registry.isRegistered(root.getSpanContext())).isFalse(); @@ -66,22 +67,14 @@ void unregisterTraceForProfilingWhenEntrySpanEnds(Tracer tracer) { } @Test - void doNotRegisterTraceForProfilingWhenSnapshotVolumeIsOff(Tracer tracer) { - try (var ignored = Context.current().with(Volume.OFF).makeCurrent()) { - var root = tracer.spanBuilder("root").startSpan(); - assertThat(registry.isRegistered(root.getSpanContext())).isFalse(); - } - } - - @Test - void doNotRegisterTraceForProfilingWhenSnapshotVolumeIsNotfound(Tracer tracer) { + void registerTraceForProfilingWhenSnapshotVolumeIsNotfound(Tracer tracer) { var root = tracer.spanBuilder("root").startSpan(); - assertThat(registry.isRegistered(root.getSpanContext())).isFalse(); + assertThat(registry.isRegistered(root.getSpanContext())).isTrue(); } @Test void onlyUnregisterTraceForProfilingWhenEntrySpanEnds(Tracer tracer) { - try (var ignored = Context.current().with(Volume.HIGHEST).makeCurrent()) { + try (var ignored = Context.current().makeCurrent()) { var root = tracer.spanBuilder("root").startSpan(); var child = tracer.spanBuilder("child").setParent(Context.current().with(root)).startSpan(); child.end(); diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/VolumeTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/VolumeTest.java deleted file mode 100644 index 12b6726be..000000000 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/VolumeTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 com.splunk.opentelemetry.profiler.snapshot; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import io.opentelemetry.api.baggage.Baggage; -import io.opentelemetry.context.Context; -import java.util.Locale; -import java.util.stream.Stream; -import net.bytebuddy.utility.RandomString; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.EnumSource; -import org.junit.jupiter.params.provider.EnumSource.Mode; -import org.junit.jupiter.params.provider.MethodSource; - -class VolumeTest { - @ParameterizedTest - @EnumSource( - value = Volume.class, - mode = Mode.EXCLUDE, - names = {"UNSPECIFIED"}) - void toStringRepresentation(Volume volume) { - assertEquals(volume.name().toLowerCase(Locale.ROOT), volume.toString()); - } - - @ParameterizedTest - @MethodSource("volumesAsStrings") - void extractVolumeFromOpenTelemetryContext(Volume volume, String asString) { - var baggage = Baggage.builder().put("splunk.trace.snapshot.volume", asString).build(); - var context = Context.current().with(baggage); - assertEquals(volume, Volume.from(context)); - } - - @ParameterizedTest - @MethodSource("volumesAsStrings") - void fromContextIsNotSensitiveToLocale(Volume volume, String asString) { - var baggage = Baggage.builder().put("splunk.trace.snapshot.volume", asString).build(); - var context = Context.current().with(baggage); - - var defaultLocale = Locale.getDefault(); - try { - for (var locale : Locale.getAvailableLocales()) { - Locale.setDefault(locale); - assertEquals(volume, Volume.from(context)); - } - } finally { - Locale.setDefault(defaultLocale); - } - } - - private static Stream volumesAsStrings() { - return Stream.of( - Arguments.of(Volume.OFF, "off"), - Arguments.of(Volume.HIGHEST, "highest"), - Arguments.of(Volume.HIGHEST, "hıghest")); - } - - @Test - void fromContextReturnsUnspecifiedWhenMatchNotFound() { - var baggage = Baggage.builder().build(); - var context = Context.current().with(baggage); - assertEquals(Volume.UNSPECIFIED, Volume.from(context)); - } - - @Test - void fromContextReturnsOffUnsupportedValueFound() { - var baggage = Baggage.builder().put("splunk.trace.snapshot.volume", "not-a-volume").build(); - var context = Context.current().with(baggage); - assertEquals(Volume.OFF, Volume.from(context)); - } - - @ParameterizedTest - @EnumSource( - value = Volume.class, - mode = Mode.EXCLUDE, - names = {"UNSPECIFIED"}) - void storeBaggageRepresentationInOpenTelemetryContext(Volume volume) { - var context = Context.current().with(volume); - var baggage = Baggage.fromContext(context); - var entry = baggage.getEntry("splunk.trace.snapshot.volume"); - - assertNotNull(entry); - assertEquals(volume.toString(), entry.getValue()); - } - - @ParameterizedTest - @EnumSource( - value = Volume.class, - mode = Mode.EXCLUDE, - names = {"UNSPECIFIED"}) - void respectPreviousBaggageEntriesOpenTelemetryContext(Volume volume) { - var baggageKey = "existing-baggage-entry"; - var baggageValue = RandomString.make(); - var context = Context.current().with(Baggage.builder().put(baggageKey, baggageValue).build()); - - try (var ignored = context.makeCurrent()) { - var contextWithVolume = context.with(volume); - var baggage = Baggage.fromContext(contextWithVolume); - var entry = baggage.getEntry(baggageKey); - - assertNotNull(entry); - assertEquals(baggageValue, entry.getValue()); - } - } -}