diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/BaseDecorator.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/BaseDecorator.java index 122e76c5fbd..e07b06c3439 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/BaseDecorator.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/BaseDecorator.java @@ -1,6 +1,5 @@ package datadog.trace.bootstrap.instrumentation.decorator; -import static datadog.trace.api.cache.RadixTreeCache.PORTS; import static datadog.trace.api.cache.RadixTreeCache.UNSET_PORT; import static datadog.trace.bootstrap.instrumentation.java.net.HostNameResolver.hostName; @@ -153,9 +152,8 @@ public AgentSpan setPeerPort(AgentSpan span, String port) { public AgentSpan setPeerPort(AgentSpan span, int port) { if (port > UNSET_PORT) { - span.setTag(Tags.PEER_PORT, PORTS.get(port)); + span.setTag(Tags.PEER_PORT, port); } - return span; } diff --git a/dd-java-agent/instrumentation/mongo/mongo-common/src/main/java/datadog/trace/instrumentation/mongo/MongoCommandListener.java b/dd-java-agent/instrumentation/mongo/mongo-common/src/main/java/datadog/trace/instrumentation/mongo/MongoCommandListener.java index 1c893a51571..00e7ee0786c 100644 --- a/dd-java-agent/instrumentation/mongo/mongo-common/src/main/java/datadog/trace/instrumentation/mongo/MongoCommandListener.java +++ b/dd-java-agent/instrumentation/mongo/mongo-common/src/main/java/datadog/trace/instrumentation/mongo/MongoCommandListener.java @@ -1,7 +1,6 @@ package datadog.trace.instrumentation.mongo; import static datadog.trace.api.Functions.UTF8_ENCODE; -import static datadog.trace.api.cache.RadixTreeCache.PORTS; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.closeActive; @@ -150,7 +149,7 @@ public void commandStarted(final CommandStartedEvent event) { // may do a DNS lookup ServerAddress serverAddress = event.getConnectionDescription().getServerAddress(); span.setTag(Tags.PEER_HOSTNAME, serverAddress.getHost()) - .setTag(Tags.PEER_PORT, PORTS.get(serverAddress.getPort())) + .setTag(Tags.PEER_PORT, serverAddress.getPort()) .setTag( Tags.DB_OPERATION, COMMAND_NAMES.computeIfAbsent(event.getCommandName(), UTF8_ENCODE)); diff --git a/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java b/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java index 4a0eb4378b5..b716de73b59 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java @@ -34,6 +34,7 @@ import datadog.trace.core.taginterceptor.TagInterceptor; import datadog.trace.core.tagprocessor.TagsPostProcessorFactory; import datadog.trace.util.TagsHelper; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.Closeable; import java.io.IOException; import java.util.Collections; @@ -1123,7 +1124,7 @@ public void processTagsAndBaggage( samplingPriority != PrioritySampling.UNSET ? samplingPriority : getSamplingPriority(), measured, topLevel, - httpStatusCode == 0 ? null : HTTP_STATUSES.get(httpStatusCode), + httpStatusCode == 0 ? null : shortStatusCodeToString(httpStatusCode), // Get origin from rootSpan.context getOrigin(), longRunningVersion, @@ -1131,6 +1132,22 @@ public void processTagsAndBaggage( } } + @SuppressFBWarnings("DCN") // only interested in catching NullPointerException (see note below) + private static UTF8BytesString shortStatusCodeToString(short httpStatusCode) { + try { + return HTTP_STATUSES.get(httpStatusCode); + } catch (NullPointerException e) { + // Intermittent NPE observed in JDK code on Semeru 11.0.29: java.lang.NullPointerException: + // at j.l.i.ArrayVarHandle$...Operations$OpObject.computeOffset(ArrayVarHandle.java:142) + // at j.l.i.ArrayVarHandle$...Operations$OpObject.compareAndSet(ArrayVarHandle.java:201) + // at j.u.c.atomic.AtomicReferenceArray.compareAndSet(AtomicReferenceArray.java:152) + // at datadog.trace.api.cache.RadixTreeCache.computeIfAbsent(RadixTreeCache.java:59) + // Location indicates JDK's VarHandle used to access the backing array has returned null + // To mitigate this rare JDK bug we skip the cache and fall back to manual string creation + return UTF8BytesString.create(Short.toString(httpStatusCode)); + } + } + void injectW3CBaggageTags(Map baggageItemsWithPropagationTags) { List baggageTagKeys = Config.get().getTraceBaggageTagKeys(); if (baggageTagKeys.isEmpty()) { diff --git a/internal-api/src/main/java/datadog/trace/api/cache/RadixTreeCache.java b/internal-api/src/main/java/datadog/trace/api/cache/RadixTreeCache.java index d2c1288aa55..1cb2bc65f77 100644 --- a/internal-api/src/main/java/datadog/trace/api/cache/RadixTreeCache.java +++ b/internal-api/src/main/java/datadog/trace/api/cache/RadixTreeCache.java @@ -18,9 +18,6 @@ public final class RadixTreeCache { 16, 32, TO_STRING, 200, 201, 301, 307, 400, 401, 403, 404, 500, 502, 503); public static final int UNSET_PORT = 0; - // should cover range [0, 2^16) - public static final RadixTreeCache PORTS = - new RadixTreeCache<>(256, 256, Integer::valueOf, 80, 443, 8080); private final int level1; private final int level2; diff --git a/internal-api/src/test/groovy/datadog/trace/api/cache/RadixTreeCacheTest.groovy b/internal-api/src/test/groovy/datadog/trace/api/cache/RadixTreeCacheTest.groovy index 1b98e00a1ae..4a4f634d955 100644 --- a/internal-api/src/test/groovy/datadog/trace/api/cache/RadixTreeCacheTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/api/cache/RadixTreeCacheTest.groovy @@ -118,13 +118,6 @@ class RadixTreeCacheTest extends DDSpecification { }) } - def "cache ports"() { - expect: - Integer.valueOf(port) == RadixTreeCache.PORTS.get(port) - where: - port << [0, 80, 443, 4444, 8080, 65535] - } - def "cache HTTP statuses"() { expect: Integer.toString(status) == RadixTreeCache.HTTP_STATUSES.get(status) as String