Skip to content

Commit

Permalink
Merge pull request #34510 from geoand/#34376
Browse files Browse the repository at this point in the history
Enhance OpenTelemetry's DropTargetsSampler
  • Loading branch information
geoand authored Jul 4, 2023
2 parents 798f1ce + b8b2c37 commit 60da8ba
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,44 @@ public SamplingResult shouldSample(Context parentContext, String traceId, String

if (spanKind.equals(SpanKind.SERVER)) {
String target = attributes.get(SemanticAttributes.HTTP_TARGET);
// TODO - radcortez - Match /* endpoints
if (target != null && dropTargets.contains(target)) {
if (shouldDrop(target)) {
return SamplingResult.drop();
}
}

return sampler.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks);
}

/**
* Determines whether a path should be dropped
* TODO: this can certainly be optimized if we find that it's a hot-path
*/
private boolean shouldDrop(String target) {
if ((target == null) || target.isEmpty()) {
return false;
}
if (safeContains(target)) { // check exact match
return true;
}
if (target.charAt(target.length() - 1) == '/') { // check if the path without the ending slash matched
if (safeContains(target.substring(0, target.length() - 1))) {
return true;
}
}
int lastSlashIndex = target.lastIndexOf('/');
if (lastSlashIndex != -1) {
if (safeContains(target.substring(0, lastSlashIndex) + "*")
|| safeContains(target.substring(0, lastSlashIndex) + "/*")) { // check if a wildcard matches
return true;
}
}
return false;
}

private boolean safeContains(String target) {
return dropTargets.contains(target);
}

@Override
public String getDescription() {
return sampler.getDescription();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package io.quarkus.opentelemetry.runtime.tracing;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import org.junit.jupiter.api.Test;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.data.LinkData;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import io.opentelemetry.sdk.trace.samplers.SamplingResult;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;

class DropTargetsSamplerTest {

@Test
void testDropTargets() {
CountingSampler countingSampler = new CountingSampler();
var sut = new DropTargetsSampler(countingSampler, List.of("/q/swagger-ui", "/q/swagger-ui*"));

assertEquals(SamplingResult.recordAndSample(), getShouldSample(sut, "/other"));
assertEquals(1, countingSampler.count.get());

assertEquals(SamplingResult.drop(), getShouldSample(sut, "/q/swagger-ui"));
assertEquals(1, countingSampler.count.get());

assertEquals(SamplingResult.drop(), getShouldSample(sut, "/q/swagger-ui/"));
assertEquals(1, countingSampler.count.get());

assertEquals(SamplingResult.drop(), getShouldSample(sut, "/q/swagger-ui/whatever"));
assertEquals(1, countingSampler.count.get());

assertEquals(SamplingResult.recordAndSample(), getShouldSample(sut, "/q/test"));
assertEquals(2, countingSampler.count.get());
}

private static SamplingResult getShouldSample(DropTargetsSampler sut, String target) {
return sut.shouldSample(null, null, null, SpanKind.SERVER,
Attributes.of(SemanticAttributes.HTTP_TARGET, target), null);
}

private static final class CountingSampler implements Sampler {

final AtomicLong count = new AtomicLong(0);

@Override
public SamplingResult shouldSample(Context parentContext, String traceId, String name, SpanKind spanKind,
Attributes attributes, List<LinkData> parentLinks) {
count.incrementAndGet();
return SamplingResult.recordAndSample();
}

@Override
public String getDescription() {
return "test";
}
}
}

0 comments on commit 60da8ba

Please sign in to comment.