From 7cb51501478a0e64e3c9f397aaaf5fc35b9a2428 Mon Sep 17 00:00:00 2001 From: "chris.agocs" Date: Fri, 13 Sep 2024 12:50:50 -0700 Subject: [PATCH 01/18] Apply spotless --- .../datadog/trace/lambda/LambdaHandler.java | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java b/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java index 1d298169207..b9d341f9f5a 100644 --- a/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java +++ b/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java @@ -45,6 +45,7 @@ public class LambdaHandler { private static final String DATADOG_INVOCATION_ERROR_TYPE = "x-datadog-invocation-error-type"; private static final String DATADOG_INVOCATION_ERROR_STACK = "x-datadog-invocation-error-stack"; private static final String DATADOG_TAGS_KEY = "x-datadog-tags"; + private static final String DATADOG_UPPER_64_TRACE_ID_TAG_KEY = "_dd.p.tid"; private static final String START_INVOCATION = "/lambda/start-invocation"; private static final String END_INVOCATION = "/lambda/end-invocation"; @@ -86,9 +87,20 @@ public static AgentSpan.Context notifyStartInvocation( .build()) .execute()) { if (response.isSuccessful()) { - final String traceID = response.headers().get(DATADOG_TRACE_ID); + final String traceIDLower64Long = response.headers().get(DATADOG_TRACE_ID); final String priority = response.headers().get(DATADOG_SAMPLING_PRIORITY); - if (null != traceID && null != priority) { + final String tags = response.headers().get(DATADOG_TAGS_KEY); + final String traceIDUpper64BitHex = findUpper64BitTraceId(tags); + DDTraceId traceId; + if (null != traceIDUpper64BitHex && null != traceIDLower64Long) { + long lower64Long = Long.parseUnsignedLong(traceIDLower64Long); + String lower64Hex = Long.toHexString(lower64Long); + String full128BitHex = traceIDUpper64BitHex + lower64Hex; + traceId = DDTraceId.fromHex(full128BitHex); + } else { + traceId = DDTraceId.from(traceIDLower64Long); + } + if (null != traceIDLower64Long && null != priority) { int samplingPriority = PrioritySampling.UNSET; try { samplingPriority = Integer.parseInt(priority); @@ -97,18 +109,12 @@ public static AgentSpan.Context notifyStartInvocation( } log.debug( "notifyStartInvocation success, found traceID = {} and samplingPriority = {}", - traceID, + traceIDLower64Long, samplingPriority); PropagationTags propagationTags = - propagationTagsFactory.fromHeaderValue( - PropagationTags.HeaderType.DATADOG, response.headers().get(DATADOG_TAGS_KEY)); + propagationTagsFactory.fromHeaderValue(PropagationTags.HeaderType.DATADOG, tags); return new ExtractedContext( - DDTraceId.from(traceID), - DDSpanId.ZERO, - samplingPriority, - null, - propagationTags, - DATADOG); + traceId, DDSpanId.ZERO, samplingPriority, null, propagationTags, DATADOG); } else { log.debug( "could not find traceID or sampling priority in notifyStartInvocation, not injecting the context"); @@ -120,6 +126,21 @@ public static AgentSpan.Context notifyStartInvocation( return null; } + private static String findUpper64BitTraceId(String tags) + throws NumberFormatException, IndexOutOfBoundsException { + if (tags == null) { + return null; + } + String[] tagPairs = tags.split(","); + for (String tagPair : tagPairs) { + String[] tag = tagPair.trim().split("="); + if (tag.length == 2 && tag[0].equals(DATADOG_UPPER_64_TRACE_ID_TAG_KEY)) { + return tag[1]; + } + } + return null; + } + public static boolean notifyEndInvocation(AgentSpan span, Object result, boolean isError) { if (null == span || null == span.getSamplingPriority()) { From f4c75c7103c8003d18310ee2bfb53489a8cf3f03 Mon Sep 17 00:00:00 2001 From: "chris.agocs" Date: Tue, 17 Sep 2024 13:12:32 -0700 Subject: [PATCH 02/18] Use the core tracer's context propagation API --- .../java/datadog/trace/core/CoreTracer.java | 2 +- .../datadog/trace/lambda/LambdaHandler.java | 30 +++++++++++++++++++ .../trace/lambda/LambdaHandlerTest.groovy | 7 +++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index 8da026f224f..6cacd7037ff 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -956,7 +956,7 @@ public AgentSpan blackholeSpan() { @Override public AgentSpan.Context notifyExtensionStart(Object event) { - return LambdaHandler.notifyStartInvocation(event, propagationTagsFactory); + return LambdaHandler.notifyStartInvocation(this, event); } @Override diff --git a/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java b/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java index b9d341f9f5a..6b0831a7f0a 100644 --- a/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java +++ b/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java @@ -10,6 +10,7 @@ import datadog.trace.api.DDTraceId; import datadog.trace.api.sampling.PrioritySampling; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.core.CoreTracer; import datadog.trace.core.propagation.ExtractedContext; import datadog.trace.core.propagation.PropagationTags; import java.io.ByteArrayInputStream; @@ -74,6 +75,35 @@ public class LambdaHandler { private static String EXTENSION_BASE_URL = "http://127.0.0.1:8124"; + public static AgentSpan.Context notifyStartInvocation(CoreTracer tracer, Object event) { + RequestBody body = RequestBody.create(jsonMediaType, writeValueAsString(event)); + try (Response response = + HTTP_CLIENT + .newCall( + new Request.Builder() + .url(EXTENSION_BASE_URL + START_INVOCATION) + .addHeader(DATADOG_META_LANG, "java") + .post(body) + .build()) + .execute()) { + if (response.isSuccessful()) { + + return tracer + .propagate() + .extract( + response.headers(), + (carrier, classifier) -> { + for (String headerName : carrier.names()) { + classifier.accept(headerName, carrier.get(headerName)); + } + }); + } + } catch (Throwable ignored) { + log.error("could not reach the extension"); + } + return null; + } + public static AgentSpan.Context notifyStartInvocation( Object event, PropagationTags.Factory propagationTagsFactory) { RequestBody body = RequestBody.create(jsonMediaType, writeValueAsString(event)); diff --git a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy index bf2dc097f19..2a9cdc186bb 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy @@ -4,6 +4,7 @@ import datadog.trace.api.Config import datadog.trace.api.DDSpanId import datadog.trace.api.DDTags import datadog.trace.api.DDTraceId +import datadog.trace.core.CoreTracer import datadog.trace.core.propagation.PropagationTags import datadog.trace.core.test.DDCoreSpecification import datadog.trace.core.DDSpan @@ -32,6 +33,7 @@ class LambdaHandlerTest extends DDCoreSpecification { given: Config config = Mock(Config) config.getxDatadogTagsMaxLength() >> 512 + CoreTracer ct = CoreTracer.builder().config(config).build() def server = httpServer { handlers { @@ -47,7 +49,7 @@ class LambdaHandlerTest extends DDCoreSpecification { LambdaHandler.setExtensionBaseUrl(server.address.toString()) when: - def objTest = LambdaHandler.notifyStartInvocation(obj, PropagationTags.factory(config)) + def objTest = LambdaHandler.notifyStartInvocation(ct, obj) then: objTest.getTraceId().toString() == traceId @@ -65,6 +67,7 @@ class LambdaHandlerTest extends DDCoreSpecification { given: Config config = Mock(Config) config.getxDatadogTagsMaxLength() >> 512 + CoreTracer ct = CoreTracer.builder().config(config).build() def server = httpServer { handlers { @@ -78,7 +81,7 @@ class LambdaHandlerTest extends DDCoreSpecification { LambdaHandler.setExtensionBaseUrl(server.address.toString()) when: - def objTest = LambdaHandler.notifyStartInvocation(obj, PropagationTags.factory(config)) + def objTest = LambdaHandler.notifyStartInvocation(ct, obj) then: objTest == expected From 4f14ced5a692553c8df75761b1a48b5ef4b88e1b Mon Sep 17 00:00:00 2001 From: "chris.agocs" Date: Tue, 17 Sep 2024 15:04:01 -0700 Subject: [PATCH 03/18] Remove unused import --- .../test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy index 2a9cdc186bb..d1fd7513d33 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy @@ -5,7 +5,6 @@ import datadog.trace.api.DDSpanId import datadog.trace.api.DDTags import datadog.trace.api.DDTraceId import datadog.trace.core.CoreTracer -import datadog.trace.core.propagation.PropagationTags import datadog.trace.core.test.DDCoreSpecification import datadog.trace.core.DDSpan import com.amazonaws.services.lambda.runtime.events.SQSEvent From 634e8e9eb8d1d84a8c3abfada9e5e82158651bc0 Mon Sep 17 00:00:00 2001 From: "chris.agocs" Date: Tue, 17 Sep 2024 15:15:36 -0700 Subject: [PATCH 04/18] Add test for 128 bit trace IDs --- .../trace/lambda/LambdaHandlerTest.groovy | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy index d1fd7513d33..616c83e811d 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy @@ -62,6 +62,41 @@ class LambdaHandlerTest extends DDCoreSpecification { "1234" | 2 | new TestObject() } + def "test start invocation with 128 bit trace ID"() { + given: + Config config = Mock(Config) + config.getxDatadogTagsMaxLength() >> 512 + CoreTracer ct = CoreTracer.builder().config(config).build() + + def server = httpServer { + handlers { + post("/lambda/start-invocation") { + response + .status(200) + .addHeader("x-datadog-trace-id", "5744042798732701615") + .addHeader("x-datadog-sampling-priority", "2") + .addHeader("x-datadog-tags", "_dd.p.tid=1914fe7789eb32be") + .send() + } + } + } + LambdaHandler.setExtensionBaseUrl(server.address.toString()) + + when: + def objTest = LambdaHandler.notifyStartInvocation(ct, obj) + + then: + objTest.getTraceId().toString() == traceId + objTest.getSamplingPriority() == samplingPriority + + cleanup: + server.close() + + where: + traceId | samplingPriority | obj + "33339707034668043638992915224308903855" | 2 | new TestObject() + } + def "test start invocation failure"() { given: Config config = Mock(Config) From fea8502147dc7f23ab69248c29eb77685a82b1e7 Mon Sep 17 00:00:00 2001 From: "chris.agocs" Date: Wed, 18 Sep 2024 14:19:27 -0700 Subject: [PATCH 05/18] Remove old notifyStartInvocation method --- .../datadog/trace/lambda/LambdaHandler.java | 75 ------------------- 1 file changed, 75 deletions(-) diff --git a/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java b/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java index 6b0831a7f0a..e11dbb8c29e 100644 --- a/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java +++ b/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java @@ -1,18 +1,13 @@ package datadog.trace.lambda; -import static datadog.trace.api.TracePropagationStyle.DATADOG; import static java.util.concurrent.TimeUnit.SECONDS; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.Moshi; import datadog.trace.api.DDSpanId; import datadog.trace.api.DDTags; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.sampling.PrioritySampling; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.core.CoreTracer; -import datadog.trace.core.propagation.ExtractedContext; -import datadog.trace.core.propagation.PropagationTags; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -45,8 +40,6 @@ public class LambdaHandler { private static final String DATADOG_INVOCATION_ERROR_MSG = "x-datadog-invocation-error-msg"; private static final String DATADOG_INVOCATION_ERROR_TYPE = "x-datadog-invocation-error-type"; private static final String DATADOG_INVOCATION_ERROR_STACK = "x-datadog-invocation-error-stack"; - private static final String DATADOG_TAGS_KEY = "x-datadog-tags"; - private static final String DATADOG_UPPER_64_TRACE_ID_TAG_KEY = "_dd.p.tid"; private static final String START_INVOCATION = "/lambda/start-invocation"; private static final String END_INVOCATION = "/lambda/end-invocation"; @@ -104,75 +97,7 @@ public static AgentSpan.Context notifyStartInvocation(CoreTracer tracer, Object return null; } - public static AgentSpan.Context notifyStartInvocation( - Object event, PropagationTags.Factory propagationTagsFactory) { - RequestBody body = RequestBody.create(jsonMediaType, writeValueAsString(event)); - try (Response response = - HTTP_CLIENT - .newCall( - new Request.Builder() - .url(EXTENSION_BASE_URL + START_INVOCATION) - .addHeader(DATADOG_META_LANG, "java") - .post(body) - .build()) - .execute()) { - if (response.isSuccessful()) { - final String traceIDLower64Long = response.headers().get(DATADOG_TRACE_ID); - final String priority = response.headers().get(DATADOG_SAMPLING_PRIORITY); - final String tags = response.headers().get(DATADOG_TAGS_KEY); - final String traceIDUpper64BitHex = findUpper64BitTraceId(tags); - DDTraceId traceId; - if (null != traceIDUpper64BitHex && null != traceIDLower64Long) { - long lower64Long = Long.parseUnsignedLong(traceIDLower64Long); - String lower64Hex = Long.toHexString(lower64Long); - String full128BitHex = traceIDUpper64BitHex + lower64Hex; - traceId = DDTraceId.fromHex(full128BitHex); - } else { - traceId = DDTraceId.from(traceIDLower64Long); - } - if (null != traceIDLower64Long && null != priority) { - int samplingPriority = PrioritySampling.UNSET; - try { - samplingPriority = Integer.parseInt(priority); - } catch (final NumberFormatException ignored) { - log.warn("could not read the sampling priority, defaulting to UNSET"); - } - log.debug( - "notifyStartInvocation success, found traceID = {} and samplingPriority = {}", - traceIDLower64Long, - samplingPriority); - PropagationTags propagationTags = - propagationTagsFactory.fromHeaderValue(PropagationTags.HeaderType.DATADOG, tags); - return new ExtractedContext( - traceId, DDSpanId.ZERO, samplingPriority, null, propagationTags, DATADOG); - } else { - log.debug( - "could not find traceID or sampling priority in notifyStartInvocation, not injecting the context"); - } - } - } catch (Throwable ignored) { - log.error("could not reach the extension"); - } - return null; - } - - private static String findUpper64BitTraceId(String tags) - throws NumberFormatException, IndexOutOfBoundsException { - if (tags == null) { - return null; - } - String[] tagPairs = tags.split(","); - for (String tagPair : tagPairs) { - String[] tag = tagPair.trim().split("="); - if (tag.length == 2 && tag[0].equals(DATADOG_UPPER_64_TRACE_ID_TAG_KEY)) { - return tag[1]; - } - } - return null; - } - public static boolean notifyEndInvocation(AgentSpan span, Object result, boolean isError) { - if (null == span || null == span.getSamplingPriority()) { log.error( "could not notify the extension as the lambda span is null or no sampling priority has been found"); From d17d6646b9416c954e19294470d807c58f6ce111 Mon Sep 17 00:00:00 2001 From: "chris.agocs" Date: Wed, 18 Sep 2024 21:55:47 -0700 Subject: [PATCH 06/18] Try a different way of building CoreTracer? --- .../groovy/datadog/trace/lambda/LambdaHandlerTest.groovy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy index 616c83e811d..ed309f18352 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy @@ -32,7 +32,7 @@ class LambdaHandlerTest extends DDCoreSpecification { given: Config config = Mock(Config) config.getxDatadogTagsMaxLength() >> 512 - CoreTracer ct = CoreTracer.builder().config(config).build() + CoreTracer ct = CoreTracer.builder().build() def server = httpServer { handlers { @@ -66,7 +66,7 @@ class LambdaHandlerTest extends DDCoreSpecification { given: Config config = Mock(Config) config.getxDatadogTagsMaxLength() >> 512 - CoreTracer ct = CoreTracer.builder().config(config).build() + CoreTracer ct = CoreTracer.builder().build() def server = httpServer { handlers { @@ -101,7 +101,7 @@ class LambdaHandlerTest extends DDCoreSpecification { given: Config config = Mock(Config) config.getxDatadogTagsMaxLength() >> 512 - CoreTracer ct = CoreTracer.builder().config(config).build() + CoreTracer ct = CoreTracer.builder().build() def server = httpServer { handlers { From a78f9a03946089132b42d595b7a74ab65855f733 Mon Sep 17 00:00:00 2001 From: Laplie Anderson Date: Fri, 20 Sep 2024 12:43:22 -0400 Subject: [PATCH 07/18] toHexString() instead of toString(). Plus tracer builder fixes --- .../datadog/trace/lambda/LambdaHandlerTest.groovy | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy index ed309f18352..aac4fbf4842 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy @@ -32,7 +32,7 @@ class LambdaHandlerTest extends DDCoreSpecification { given: Config config = Mock(Config) config.getxDatadogTagsMaxLength() >> 512 - CoreTracer ct = CoreTracer.builder().build() + CoreTracer ct = tracerBuilder().build() def server = httpServer { handlers { @@ -56,6 +56,7 @@ class LambdaHandlerTest extends DDCoreSpecification { cleanup: server.close() + ct.close() where: traceId | samplingPriority | obj @@ -66,7 +67,7 @@ class LambdaHandlerTest extends DDCoreSpecification { given: Config config = Mock(Config) config.getxDatadogTagsMaxLength() >> 512 - CoreTracer ct = CoreTracer.builder().build() + CoreTracer ct = tracerBuilder().build() def server = httpServer { handlers { @@ -86,22 +87,23 @@ class LambdaHandlerTest extends DDCoreSpecification { def objTest = LambdaHandler.notifyStartInvocation(ct, obj) then: - objTest.getTraceId().toString() == traceId + objTest.getTraceId().toHexString() == traceId objTest.getSamplingPriority() == samplingPriority cleanup: server.close() + ct.close() where: - traceId | samplingPriority | obj - "33339707034668043638992915224308903855" | 2 | new TestObject() + traceId | samplingPriority | obj + "1914fe7789eb32be4fb6f07e011a6faf" | 2 | new TestObject() } def "test start invocation failure"() { given: Config config = Mock(Config) config.getxDatadogTagsMaxLength() >> 512 - CoreTracer ct = CoreTracer.builder().build() + CoreTracer ct = tracerBuilder().build() def server = httpServer { handlers { @@ -122,6 +124,7 @@ class LambdaHandlerTest extends DDCoreSpecification { cleanup: server.close() + ct.close() where: expected | obj From e72240d6b41a344c8619edf75b1cf8043b15706f Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 23 Sep 2024 09:58:43 -0400 Subject: [PATCH 08/18] Bump profiler to 1.15.0 To be used for patch v1.39.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8026189c17e..6636f0f5470 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -29,7 +29,7 @@ moshi = '1.11.0' testcontainers = '1.19.3' jmc = "8.1.0" autoservice = "1.0-rc7" -ddprof = "1.13.0" +ddprof = "1.15.0" asm = "9.7" cafe_crypto = "0.1.0" lz4 = "1.7.1" From 87e7f1d1c29bdf27b7fac8c4e7709a46c6215b38 Mon Sep 17 00:00:00 2001 From: "chris.agocs" Date: Mon, 23 Sep 2024 09:23:41 -0700 Subject: [PATCH 09/18] Get rid of Mock Config, since I think it's not necessary here --- .../groovy/datadog/trace/lambda/LambdaHandlerTest.groovy | 7 ------- 1 file changed, 7 deletions(-) diff --git a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy index aac4fbf4842..716dec06ddf 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy @@ -1,6 +1,5 @@ package datadog.trace.lambda -import datadog.trace.api.Config import datadog.trace.api.DDSpanId import datadog.trace.api.DDTags import datadog.trace.api.DDTraceId @@ -30,8 +29,6 @@ class LambdaHandlerTest extends DDCoreSpecification { def "test start invocation success"() { given: - Config config = Mock(Config) - config.getxDatadogTagsMaxLength() >> 512 CoreTracer ct = tracerBuilder().build() def server = httpServer { @@ -65,8 +62,6 @@ class LambdaHandlerTest extends DDCoreSpecification { def "test start invocation with 128 bit trace ID"() { given: - Config config = Mock(Config) - config.getxDatadogTagsMaxLength() >> 512 CoreTracer ct = tracerBuilder().build() def server = httpServer { @@ -101,8 +96,6 @@ class LambdaHandlerTest extends DDCoreSpecification { def "test start invocation failure"() { given: - Config config = Mock(Config) - config.getxDatadogTagsMaxLength() >> 512 CoreTracer ct = tracerBuilder().build() def server = httpServer { From bf7540185427352414ad5a7ad87b75c132d48da1 Mon Sep 17 00:00:00 2001 From: Idan Shatz Date: Wed, 25 Sep 2024 07:21:52 -0600 Subject: [PATCH 10/18] change tags to match Code Origin RFC updated spec --- .../debugger/probe/CodeOriginProbe.java | 24 +++---------------- .../debugger/origin/CodeOriginTest.java | 14 +---------- .../agent/test/asserts/TagsAssert.groovy | 4 ---- .../main/java/datadog/trace/api/DDTags.java | 12 ++-------- 4 files changed, 6 insertions(+), 48 deletions(-) diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/CodeOriginProbe.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/CodeOriginProbe.java index 6c6eeba5233..1f0c774a11b 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/CodeOriginProbe.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/CodeOriginProbe.java @@ -1,7 +1,6 @@ package com.datadog.debugger.probe; import static com.datadog.debugger.codeorigin.DebuggerConfiguration.isDebuggerEnabled; -import static datadog.trace.api.DDTags.DD_CODE_ORIGIN_SNAPSHOT_ID; import static datadog.trace.api.DDTags.DD_STACK_CODE_ORIGIN_FRAME; import static datadog.trace.api.DDTags.DD_STACK_CODE_ORIGIN_TYPE; import static java.lang.String.format; @@ -13,7 +12,6 @@ import com.datadog.debugger.instrumentation.InstrumentationResult; import com.datadog.debugger.sink.Snapshot; import com.datadog.debugger.util.ClassNameFiltering; -import datadog.trace.api.DDTags; import datadog.trace.bootstrap.debugger.CapturedContext; import datadog.trace.bootstrap.debugger.MethodLocation; import datadog.trace.bootstrap.debugger.ProbeId; @@ -91,28 +89,9 @@ public void commit( private void applySpanOriginTags(AgentSpan span, String snapshotId) { List entries = getUserStackFrames(); - recordCodeOrigin(span, entries, snapshotId); recordStackFrames(span, entries, snapshotId); } - private void recordCodeOrigin( - AgentSpan span, List entries, String snapshotId) { - if (entrySpanProbe && !entries.isEmpty()) { - StackTraceElement entry = entries.get(0); - List list = asList(span, span.getLocalRootSpan()); - for (AgentSpan s : list) { - s.setTag(DDTags.DD_CODE_ORIGIN_FILE, toFileName(entry.getClassName())); - s.setTag(DDTags.DD_CODE_ORIGIN_METHOD, entry.getMethodName()); - s.setTag(DDTags.DD_CODE_ORIGIN_LINE, entry.getLineNumber()); - s.setTag(DDTags.DD_CODE_ORIGIN_TYPE, entry.getClassName()); - s.setTag(DDTags.DD_CODE_ORIGIN_METHOD_SIGNATURE, signature); - if (snapshotId != null) { - s.setTag(DD_CODE_ORIGIN_SNAPSHOT_ID, snapshotId); - } - } - } - } - private void recordStackFrames( AgentSpan span, List entries, String snapshotId) { List agentSpans = @@ -127,6 +106,9 @@ private void recordStackFrames( s.setTag(format(DD_STACK_CODE_ORIGIN_FRAME, i, "method"), info.getMethodName()); s.setTag(format(DD_STACK_CODE_ORIGIN_FRAME, i, "line"), info.getLineNumber()); s.setTag(format(DD_STACK_CODE_ORIGIN_FRAME, i, "type"), info.getClassName()); + if (i == 0 && signature != null) { + s.setTag(format(DD_STACK_CODE_ORIGIN_FRAME, i, "signature"), signature); + } if (i == 0 && snapshotId != null) { s.setTag(format(DD_STACK_CODE_ORIGIN_FRAME, i, "snapshot_id"), snapshotId); } diff --git a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java index 76d2ab934fa..4ed122314c1 100644 --- a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java +++ b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java @@ -32,7 +32,6 @@ import com.datadog.debugger.util.TestTraceInterceptor; import datadog.trace.agent.tooling.TracerInstaller; import datadog.trace.api.Config; -import datadog.trace.api.DDTags; import datadog.trace.api.InstrumenterConfig; import datadog.trace.api.interceptor.MutableSpan; import datadog.trace.bootstrap.debugger.DebuggerContext; @@ -191,10 +190,6 @@ private void waitForInstrumentation() { private static void checkEntrySpanTags(MutableSpan span, boolean includeSnapshot) { String keys = format("Existing keys for %s: %s", span.getOperationName(), ldKeys(span)); - assertKeyPresent(span, DDTags.DD_CODE_ORIGIN_FILE); - assertKeyPresent(span, DDTags.DD_CODE_ORIGIN_LINE); - assertKeyPresent(span, DDTags.DD_CODE_ORIGIN_METHOD); - assertKeyPresent(span, DDTags.DD_CODE_ORIGIN_METHOD_SIGNATURE); assertEquals(span.getTag(DD_STACK_CODE_ORIGIN_TYPE), "entry", keys); assertKeyPresent(span, DD_STACK_CODE_ORIGIN_TYPE); @@ -204,7 +199,6 @@ private static void checkEntrySpanTags(MutableSpan span, boolean includeSnapshot assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "type")); if (includeSnapshot) { - assertKeyPresent(span, DDTags.DD_CODE_ORIGIN_SNAPSHOT_ID); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "snapshot_id")); } } @@ -229,14 +223,8 @@ private static void checkExitSpanTags(MutableSpan span, boolean includeSnapshot) String keys = format("Existing keys for %s: %s", span.getOperationName(), new TreeSet<>(ldKeys(span))); - assertKeyNotPresent(span, DDTags.DD_CODE_ORIGIN_FILE); - assertKeyNotPresent(span, DDTags.DD_CODE_ORIGIN_LINE); - assertKeyNotPresent(span, DDTags.DD_CODE_ORIGIN_METHOD); - assertKeyNotPresent(span, DDTags.DD_CODE_ORIGIN_METHOD_SIGNATURE); - assertKeyNotPresent(span, DDTags.DD_CODE_ORIGIN_SNAPSHOT_ID); - assertKeyPresent(span, DD_STACK_CODE_ORIGIN_TYPE); - assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "file")); + assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 3, "file")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "line")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "method")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "type")); diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/asserts/TagsAssert.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/asserts/TagsAssert.groovy index b66fcd730bc..0693ddfda56 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/asserts/TagsAssert.groovy +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/asserts/TagsAssert.groovy @@ -62,10 +62,6 @@ class TagsAssert { assertedTags.add(DDTags.PROFILING_ENABLED) assertedTags.add(DDTags.PROFILING_CONTEXT_ENGINE) assertedTags.add(DDTags.BASE_SERVICE) - assertedTags.add(DDTags.DD_CODE_ORIGIN_FILE) - assertedTags.add(DDTags.DD_CODE_ORIGIN_METHOD) - assertedTags.add(DDTags.DD_CODE_ORIGIN_LINE) - assertedTags.add(DDTags.DD_CODE_ORIGIN_METHOD_SIGNATURE) assertedTags.add(DDTags.DSM_ENABLED) assertedTags.add(DDTags.DJM_ENABLED) assertedTags.add(DDTags.PARENT_ID) diff --git a/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java b/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java index 58506822388..f456eeb02fe 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java @@ -3,20 +3,12 @@ public class DDTags { private static final String DD_LD_PREFIX = "_dd.ld."; - public static final String DD_STACK_CODE_ORIGIN_PREFIX = "_dd.stack.code_origin."; + public static final String DD_STACK_CODE_ORIGIN_PREFIX = DD_LD_PREFIX + "code_origin."; public static final String DD_STACK_CODE_ORIGIN_TYPE = DD_STACK_CODE_ORIGIN_PREFIX + "type"; // _dd.stack.code_origin.frame.%d.file|line|method|type|snapshot_id public static final String DD_STACK_CODE_ORIGIN_FRAME = - DD_STACK_CODE_ORIGIN_PREFIX + "frame.%d.%s"; - - public static final String DD_CODE_ORIGIN_FILE = DD_LD_PREFIX + "code_origin.file"; - public static final String DD_CODE_ORIGIN_METHOD = DD_LD_PREFIX + "code_origin.method"; - public static final String DD_CODE_ORIGIN_METHOD_SIGNATURE = - DD_LD_PREFIX + "code_origin.signature"; - public static final String DD_CODE_ORIGIN_LINE = DD_LD_PREFIX + "code_origin.line"; - public static final String DD_CODE_ORIGIN_SNAPSHOT_ID = DD_LD_PREFIX + "code_origin.snapshot_id"; - public static final String DD_CODE_ORIGIN_TYPE = DD_LD_PREFIX + "code_origin.type"; + DD_STACK_CODE_ORIGIN_PREFIX + "frames.%d.%s"; public static final String SPAN_TYPE = "span.type"; public static final String SERVICE_NAME = "service.name"; From 0f8251aee9bd7bfc979fddd2e8b93a89b4c9fb8a Mon Sep 17 00:00:00 2001 From: Idan Shatz Date: Wed, 25 Sep 2024 10:51:52 -0600 Subject: [PATCH 11/18] address PR comments --- .../test/java/com/datadog/debugger/origin/CodeOriginTest.java | 3 ++- dd-trace-api/src/main/java/datadog/trace/api/DDTags.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java index 4ed122314c1..a76a202644b 100644 --- a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java +++ b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java @@ -196,6 +196,7 @@ private static void checkEntrySpanTags(MutableSpan span, boolean includeSnapshot assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "file")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "line")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "method")); + assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "signature")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "type")); if (includeSnapshot) { @@ -224,7 +225,7 @@ private static void checkExitSpanTags(MutableSpan span, boolean includeSnapshot) format("Existing keys for %s: %s", span.getOperationName(), new TreeSet<>(ldKeys(span))); assertKeyPresent(span, DD_STACK_CODE_ORIGIN_TYPE); - assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 3, "file")); + assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "file")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "line")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "method")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "type")); diff --git a/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java b/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java index f456eeb02fe..bafad0a3f6f 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java @@ -6,7 +6,7 @@ public class DDTags { public static final String DD_STACK_CODE_ORIGIN_PREFIX = DD_LD_PREFIX + "code_origin."; public static final String DD_STACK_CODE_ORIGIN_TYPE = DD_STACK_CODE_ORIGIN_PREFIX + "type"; - // _dd.stack.code_origin.frame.%d.file|line|method|type|snapshot_id + // _dd.ld.code_origin.frames.%d.file|line|method|type|snapshot_id public static final String DD_STACK_CODE_ORIGIN_FRAME = DD_STACK_CODE_ORIGIN_PREFIX + "frames.%d.%s"; From 05e8fd63aabdf08771f5bd650e6aea07b4cc5140 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Bempel Date: Thu, 26 Sep 2024 22:08:55 +0200 Subject: [PATCH 12/18] Fix duplicated locals with arguments (#7683) When hoisting local variables remove the locals that could be have the same name than arguments. This could happen resulting of the instrumentation by the tracer that reshuffle the local variable table and then reassign dedicated slots to those arguments --- .../CapturedContextInstrumentor.java | 18 ++++++++++++++++-- .../debugger/instrumentation/Instrumentor.java | 4 ++-- .../instrumentation/MetricInstrumentor.java | 4 ++-- .../TracerDebuggerIntegrationTest.java | 3 +++ 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/CapturedContextInstrumentor.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/CapturedContextInstrumentor.java index af0bb92b2a8..dda1265b201 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/CapturedContextInstrumentor.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/CapturedContextInstrumentor.java @@ -476,6 +476,7 @@ private Collection initAndHoistLocalVars(InsnList insnList) { } checkHoistableLocalVar(localVar, localVarsByName, localVarsBySlot, hoistableVarByName); } + removeDuplicatesFromArgs(hoistableVarByName, localVarsBySlotArray); // hoist vars List results = new ArrayList<>(); for (Map.Entry> entry : hoistableVarByName.entrySet()) { @@ -512,6 +513,19 @@ private Collection initAndHoistLocalVars(InsnList insnList) { return results; } + private void removeDuplicatesFromArgs( + Map> hoistableVarByName, + LocalVariableNode[] localVarsBySlotArray) { + for (int idx = 0; idx < argOffset; idx++) { + LocalVariableNode localVar = localVarsBySlotArray[idx]; + if (localVar == null) { + continue; + } + // we are removing local variables that are arguments + hoistableVarByName.remove(localVar.name); + } + } + private LabelNode findLatestLabel(InsnList instructions, Set endLabels) { for (AbstractInsnNode insn = instructions.getLast(); insn != null; insn = insn.getPrevious()) { if (insn instanceof LabelNode && endLabels.contains(insn)) { @@ -762,8 +776,8 @@ private void collectArguments(InsnList insnList, Snapshot.Kind kind) { int slot = isStatic ? 0 : 1; for (Type argType : argTypes) { String currentArgName = null; - if (slot < localVarsBySlot.length) { - LocalVariableNode localVarNode = localVarsBySlot[slot]; + if (slot < localVarsBySlotArray.length) { + LocalVariableNode localVarNode = localVarsBySlotArray[slot]; currentArgName = localVarNode != null ? localVarNode.name : null; } if (currentArgName == null) { diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/Instrumentor.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/Instrumentor.java index 0f81bf033d6..d16e2fda812 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/Instrumentor.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/Instrumentor.java @@ -45,7 +45,7 @@ public abstract class Instrumentor { protected final LabelNode methodEnterLabel; protected int localVarBaseOffset; protected int argOffset; - protected final LocalVariableNode[] localVarsBySlot; + protected final LocalVariableNode[] localVarsBySlotArray; protected LabelNode returnHandlerLabel; protected final List finallyBlocks = new ArrayList<>(); @@ -68,7 +68,7 @@ public Instrumentor( for (Type t : argTypes) { argOffset += t.getSize(); } - localVarsBySlot = extractLocalVariables(argTypes); + localVarsBySlotArray = extractLocalVariables(argTypes); } public abstract InstrumentationResult.Status instrument(); diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/MetricInstrumentor.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/MetricInstrumentor.java index 1905d451f49..11c46673318 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/MetricInstrumentor.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/MetricInstrumentor.java @@ -697,8 +697,8 @@ private ASMHelper.Type tryRetrieveArgument(String head, InsnList insnList) { int slot = instrumentor.isStatic ? 0 : 1; for (Type argType : argTypes) { String currentArgName = null; - if (instrumentor.localVarsBySlot.length > 0) { - LocalVariableNode localVarNode = instrumentor.localVarsBySlot[slot]; + if (instrumentor.localVarsBySlotArray.length > 0) { + LocalVariableNode localVarNode = instrumentor.localVarsBySlotArray[slot]; currentArgName = localVarNode != null ? localVarNode.name : null; } if (currentArgName == null) { diff --git a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/TracerDebuggerIntegrationTest.java b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/TracerDebuggerIntegrationTest.java index 4b1884dd4b9..4361a8e5573 100644 --- a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/TracerDebuggerIntegrationTest.java +++ b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/TracerDebuggerIntegrationTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import com.datadog.debugger.agent.JsonSnapshotSerializer; @@ -99,6 +100,8 @@ void testTracerSameMethod() throws Exception { Snapshot snapshot = request.getDebugger().getSnapshot(); assertEquals(PROBE_ID.getId(), snapshot.getProbe().getId()); assertEquals(42, snapshot.getCaptures().getEntry().getArguments().get("argInt").getValue()); + // no locals captured + assertNull(snapshot.getCaptures().getEntry().getLocals()); assertTrue(Pattern.matches("[0-9a-f]+", request.getTraceId())); assertTrue(Pattern.matches("\\d+", request.getSpanId())); } From 5645fbc8d8467bfd5ee061075717ac2efeb34131 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 27 Sep 2024 10:19:18 +0200 Subject: [PATCH 13/18] Upgrade testcontainers (#7688) * feat: Update to latest testcontainers version * feat: Make sure testcontainers versions are consistent --- dd-java-agent/instrumentation/aws-java-sns-1.0/build.gradle | 2 +- dd-java-agent/instrumentation/aws-java-sns-2.0/build.gradle | 2 +- .../instrumentation/datastax-cassandra-3.8/build.gradle | 2 +- dd-java-agent/instrumentation/datastax-cassandra-3/build.gradle | 2 +- dd-java-agent/instrumentation/datastax-cassandra-4/build.gradle | 2 +- dd-java-agent/instrumentation/jdbc/build.gradle | 2 +- gradle/libs.versions.toml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dd-java-agent/instrumentation/aws-java-sns-1.0/build.gradle b/dd-java-agent/instrumentation/aws-java-sns-1.0/build.gradle index 480ea864e22..0e64612a3a6 100644 --- a/dd-java-agent/instrumentation/aws-java-sns-1.0/build.gradle +++ b/dd-java-agent/instrumentation/aws-java-sns-1.0/build.gradle @@ -22,7 +22,7 @@ dependencies { // SQS is used to act as the "Subscriber" of the SNS topic. // There's a problem with sqs sdk v1 with localstack+testcontainers testing. so use sdk v2 for sqs testImplementation 'software.amazon.awssdk:sqs:2.25.40' - testImplementation 'org.testcontainers:localstack:1.19.7' + testImplementation group: 'org.testcontainers', name: 'localstack', version: libs.versions.testcontainers.get() latestDepTestImplementation group: 'com.amazonaws', name: 'aws-java-sdk-sns', version: '+' } diff --git a/dd-java-agent/instrumentation/aws-java-sns-2.0/build.gradle b/dd-java-agent/instrumentation/aws-java-sns-2.0/build.gradle index 41099604996..90db2451631 100644 --- a/dd-java-agent/instrumentation/aws-java-sns-2.0/build.gradle +++ b/dd-java-agent/instrumentation/aws-java-sns-2.0/build.gradle @@ -21,7 +21,7 @@ dependencies { testImplementation 'software.amazon.awssdk:sns:2.25.40' // SQS is used to act as the "Subscriber" of the SNS topic. testImplementation 'software.amazon.awssdk:sqs:2.25.40' - testImplementation 'org.testcontainers:localstack:1.19.7' + testImplementation group: 'org.testcontainers', name: 'localstack', version: libs.versions.testcontainers.get() latestDepTestImplementation group: 'software.amazon.awssdk', name: 'sns', version: '+' } diff --git a/dd-java-agent/instrumentation/datastax-cassandra-3.8/build.gradle b/dd-java-agent/instrumentation/datastax-cassandra-3.8/build.gradle index 33649d5ea20..0e2e9efba6c 100644 --- a/dd-java-agent/instrumentation/datastax-cassandra-3.8/build.gradle +++ b/dd-java-agent/instrumentation/datastax-cassandra-3.8/build.gradle @@ -28,7 +28,7 @@ dependencies { testImplementation group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.8.0' testImplementation group: 'com.github.jbellis', name: 'jamm', version: '0.3.3' - testImplementation ('org.testcontainers:cassandra:1.17.6') { + testImplementation (group: 'org.testcontainers', name: 'cassandra', version: libs.versions.testcontainers.get()) { exclude group: 'com.datastax.cassandra', module: 'cassandra-driver-core' } diff --git a/dd-java-agent/instrumentation/datastax-cassandra-3/build.gradle b/dd-java-agent/instrumentation/datastax-cassandra-3/build.gradle index 54392ca26cc..b91ca20d229 100644 --- a/dd-java-agent/instrumentation/datastax-cassandra-3/build.gradle +++ b/dd-java-agent/instrumentation/datastax-cassandra-3/build.gradle @@ -52,7 +52,7 @@ dependencies { testImplementation group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.2.0' testImplementation group: 'com.github.jbellis', name: 'jamm', version: '0.3.3' - testImplementation ('org.testcontainers:cassandra:1.17.6') { + testImplementation (group: 'org.testcontainers', name: 'cassandra', version: libs.versions.testcontainers.get()) { exclude group: 'com.datastax.cassandra', module: 'cassandra-driver-core' } diff --git a/dd-java-agent/instrumentation/datastax-cassandra-4/build.gradle b/dd-java-agent/instrumentation/datastax-cassandra-4/build.gradle index 47cf694eacb..68ef75a7956 100644 --- a/dd-java-agent/instrumentation/datastax-cassandra-4/build.gradle +++ b/dd-java-agent/instrumentation/datastax-cassandra-4/build.gradle @@ -22,7 +22,7 @@ dependencies { // ProgrammaticConfig, required to set the timeout, wasn't added until 4.0.1 testImplementation group: 'com.datastax.oss', name: 'java-driver-core', version: '4.0.1' - testImplementation group: 'org.testcontainers', name: 'cassandra', version: '1.17.6' + testImplementation group: 'org.testcontainers', name: 'cassandra', version: libs.versions.testcontainers.get() // Force 0.3.3 because 0.3.0 has a version parsing bug that fails on jdk 15 testImplementation group: 'com.github.jbellis', name: "jamm", version: '0.3.3' diff --git a/dd-java-agent/instrumentation/jdbc/build.gradle b/dd-java-agent/instrumentation/jdbc/build.gradle index 06c92d54486..ae412741974 100644 --- a/dd-java-agent/instrumentation/jdbc/build.gradle +++ b/dd-java-agent/instrumentation/jdbc/build.gradle @@ -38,7 +38,7 @@ dependencies { testImplementation group: 'org.testcontainers', name:'mysql', version: libs.versions.testcontainers.get() testImplementation group: 'org.testcontainers', name:'postgresql', version: libs.versions.testcontainers.get() - testImplementation group: 'org.testcontainers', name:'mssqlserver', version: '1.19.8' + testImplementation group: 'org.testcontainers', name:'mssqlserver', version: libs.versions.testcontainers.get() testRuntimeOnly project(':dd-java-agent:instrumentation:iast-instrumenter') diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6636f0f5470..810474ad645 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -26,7 +26,7 @@ commons = "3.2" mockito = '4.4.0' jctools = '3.3.0' moshi = '1.11.0' -testcontainers = '1.19.3' +testcontainers = '1.20.1' jmc = "8.1.0" autoservice = "1.0-rc7" ddprof = "1.15.0" From aa1e54c87a9a9322d98c5387179ad29bf20ff216 Mon Sep 17 00:00:00 2001 From: Jordan Wong <61242306+jordan-wong@users.noreply.github.com> Date: Fri, 27 Sep 2024 09:56:08 -0400 Subject: [PATCH 14/18] Improve BUILDING documentation, and fix typo in setup script (#7618) * Add and modify some of the BUILDING documentation, and fix typo in setup script * Remove 'Troubleshooting' section --- BUILDING.md | 2 +- setup.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 1859c8dcce0..10b49764979 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -10,7 +10,7 @@ This documentation is dedicated to developers to setup their environment, and bu ## Development environment quick check -As a preliminary step, you can quickly check that your development environment is properly set up to build the project running `./setup.sh` from the project root: +To check that your development environment is properly set up to build the project, you will eventually run `./setup.sh` from the project root and should have its output look something like this: ```bash $ ./setup.sh diff --git a/setup.sh b/setup.sh index 077421fd6fd..de097ead030 100755 --- a/setup.sh +++ b/setup.sh @@ -59,7 +59,7 @@ function look-for-hook() { elif [ -e "$HOOKS_PATH/$HOOK_NAME" ] && [ "$(get-file-hash $HOOKS_PATH/$HOOK_NAME)" == "$HOOK_CHECKSUM" ]; then echo "✅ $HOOK_NAME hook is installed in git hooks path." else - echo "🟨 $HOOK_NAME hook was not found (optional but recommanded)." + echo "🟨 $HOOK_NAME hook was not found (optional but recommended)." fi } From 201bcbe8ed2faadfabe4d1a673f65d4db39ad47b Mon Sep 17 00:00:00 2001 From: Nikita Tkachenko <121111529+nikita-tkachenko-datadog@users.noreply.github.com> Date: Fri, 27 Sep 2024 21:48:11 +0200 Subject: [PATCH 15/18] Use remote service to get CI provider info when configured to do so (#7689) --- .../communication/BackendApiFactory.java | 9 +- .../java/datadog/communication/IntakeApi.java | 5 +- .../ddagent/SharedCommunicationObjects.java | 16 +- .../civisibility/CiVisibilityServices.java | 84 ++- .../trace/civisibility/ci/AppVeyorInfo.java | 41 +- .../civisibility/ci/AwsCodePipelineInfo.java | 11 +- .../civisibility/ci/AzurePipelinesInfo.java | 49 +- .../trace/civisibility/ci/BitBucketInfo.java | 29 +- .../trace/civisibility/ci/BitriseInfo.java | 38 +- .../trace/civisibility/ci/BuddyInfo.java | 31 +- .../trace/civisibility/ci/BuildkiteInfo.java | 37 +- .../datadog/trace/civisibility/ci/CIInfo.java | 13 +- .../ci/CIProviderInfoFactory.java | 71 +-- .../trace/civisibility/ci/CircleCIInfo.java | 27 +- .../trace/civisibility/ci/CodefreshInfo.java | 27 +- .../trace/civisibility/ci/GitLabInfo.java | 43 +- .../civisibility/ci/GithubActionsInfo.java | 50 +- .../trace/civisibility/ci/JenkinsInfo.java | 35 +- .../trace/civisibility/ci/TeamcityInfo.java | 13 +- .../trace/civisibility/ci/TravisInfo.java | 38 +- .../trace/civisibility/ci/UnknownCIInfo.java | 11 +- .../civisibility/ci/env/CiEnvironment.java | 10 + .../ci/env/CiEnvironmentImpl.java | 22 + .../ci/env/CompositeCiEnvironment.java | 35 ++ .../git/CIProviderGitInfoBuilder.java | 12 +- .../CiVisibilityServicesTest.groovy | 33 ++ .../ci/CIProviderInfoFactoryTest.groovy | 3 +- .../civisibility/ci/CITagsProviderTest.groovy | 13 +- .../ci/GithubActionsInfoTest.groovy | 3 +- .../civisibility/ci/UnknownCIInfoTest.groovy | 7 +- .../ci/env/CiEnvironmentImplTest.groovy | 25 + .../ci/env/CompositeCiEnvironmentTest.groovy | 41 ++ .../config/ConfigurationApiImplTest.groovy | 4 +- .../git/CIProviderGitInfoBuilderTest.groovy | 5 +- .../trace/api/config/CiVisibilityConfig.java | 4 + .../trace/common/writer/WriterFactory.java | 1 + .../common/writer/ddintake/DDIntakeApi.java | 2 +- .../main/java/datadog/trace/api/Config.java | 539 +----------------- 38 files changed, 665 insertions(+), 772 deletions(-) create mode 100644 dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironment.java create mode 100644 dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironmentImpl.java create mode 100644 dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CompositeCiEnvironment.java create mode 100644 dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/CiVisibilityServicesTest.groovy create mode 100644 dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CiEnvironmentImplTest.groovy create mode 100644 dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CompositeCiEnvironmentTest.groovy diff --git a/communication/src/main/java/datadog/communication/BackendApiFactory.java b/communication/src/main/java/datadog/communication/BackendApiFactory.java index 296d22cb36f..f60eaa7e215 100644 --- a/communication/src/main/java/datadog/communication/BackendApiFactory.java +++ b/communication/src/main/java/datadog/communication/BackendApiFactory.java @@ -34,8 +34,13 @@ public BackendApiFactory(Config config, SharedCommunicationObjects sharedCommuni "Agentless mode is enabled and api key is not set. Please set application key"); } String traceId = config.getIdGenerationStrategy().generateTraceId().toString(); - long timeoutMillis = config.getCiVisibilityBackendApiTimeoutMillis(); - return new IntakeApi(agentlessUrl, apiKey, traceId, timeoutMillis, retryPolicyFactory, true); + return new IntakeApi( + agentlessUrl, + apiKey, + traceId, + retryPolicyFactory, + sharedCommunicationObjects.okHttpClient, + true); } DDAgentFeaturesDiscovery featuresDiscovery = diff --git a/communication/src/main/java/datadog/communication/IntakeApi.java b/communication/src/main/java/datadog/communication/IntakeApi.java index ff29dc89124..3f1fe9df67f 100644 --- a/communication/src/main/java/datadog/communication/IntakeApi.java +++ b/communication/src/main/java/datadog/communication/IntakeApi.java @@ -37,16 +37,15 @@ public IntakeApi( HttpUrl hostUrl, String apiKey, String traceId, - long timeoutMillis, HttpRetryPolicy.Factory retryPolicyFactory, + OkHttpClient httpClient, boolean responseCompression) { this.hostUrl = hostUrl; this.apiKey = apiKey; this.traceId = traceId; this.retryPolicyFactory = retryPolicyFactory; this.responseCompression = responseCompression; - - httpClient = OkHttpUtils.buildHttpClient(hostUrl, timeoutMillis); + this.httpClient = httpClient; } @Override diff --git a/communication/src/main/java/datadog/communication/ddagent/SharedCommunicationObjects.java b/communication/src/main/java/datadog/communication/ddagent/SharedCommunicationObjects.java index 8c02098fe81..14de312dadc 100644 --- a/communication/src/main/java/datadog/communication/ddagent/SharedCommunicationObjects.java +++ b/communication/src/main/java/datadog/communication/ddagent/SharedCommunicationObjects.java @@ -36,11 +36,21 @@ public void createRemaining(Config config) { } } if (okHttpClient == null) { - String unixDomainSocket = SocketUtils.discoverApmSocket(config); - String namedPipe = config.getAgentNamedPipe(); + String unixDomainSocket; + String namedPipe; + HttpUrl url; + if (!config.isCiVisibilityAgentlessEnabled()) { + unixDomainSocket = SocketUtils.discoverApmSocket(config); + namedPipe = config.getAgentNamedPipe(); + url = agentUrl; + } else { + unixDomainSocket = null; + namedPipe = null; + url = null; + } okHttpClient = OkHttpUtils.buildHttpClient( - agentUrl, unixDomainSocket, namedPipe, getHttpClientTimeout(config)); + url, unixDomainSocket, namedPipe, getHttpClientTimeout(config)); } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java index 93e1271316b..31fd0ff0cfd 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java @@ -1,12 +1,20 @@ package datadog.trace.civisibility; +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.Moshi; +import com.squareup.moshi.Types; import datadog.communication.BackendApi; import datadog.communication.BackendApiFactory; import datadog.communication.ddagent.SharedCommunicationObjects; +import datadog.communication.http.HttpRetryPolicy; +import datadog.communication.http.OkHttpUtils; import datadog.trace.api.Config; import datadog.trace.api.civisibility.telemetry.CiVisibilityMetricCollector; import datadog.trace.api.git.GitInfoProvider; import datadog.trace.civisibility.ci.CIProviderInfoFactory; +import datadog.trace.civisibility.ci.env.CiEnvironment; +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl; +import datadog.trace.civisibility.ci.env.CompositeCiEnvironment; import datadog.trace.civisibility.config.CachingJvmInfoFactory; import datadog.trace.civisibility.config.JvmInfoFactory; import datadog.trace.civisibility.config.JvmInfoFactoryImpl; @@ -19,19 +27,22 @@ import datadog.trace.civisibility.source.ByteCodeMethodLinesResolver; import datadog.trace.civisibility.source.CompilerAidedMethodLinesResolver; import datadog.trace.civisibility.source.MethodLinesResolver; -import datadog.trace.civisibility.source.index.CachingRepoIndexBuilderFactory; -import datadog.trace.civisibility.source.index.ConventionBasedResourceResolver; -import datadog.trace.civisibility.source.index.PackageResolver; -import datadog.trace.civisibility.source.index.PackageResolverImpl; -import datadog.trace.civisibility.source.index.RepoIndexFetcher; -import datadog.trace.civisibility.source.index.RepoIndexProvider; -import datadog.trace.civisibility.source.index.ResourceResolver; +import datadog.trace.civisibility.source.index.*; import datadog.trace.civisibility.utils.ProcessHierarchyUtils; +import java.lang.reflect.Type; import java.net.InetSocketAddress; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; +import java.util.Collections; +import java.util.Map; import javax.annotation.Nullable; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Services that do not need repository root location to be instantiated. Can be shared between @@ -39,8 +50,12 @@ */ public class CiVisibilityServices { + private static final Logger logger = LoggerFactory.getLogger(CiVisibilityServices.class); + private static final String GIT_FOLDER_NAME = ".git"; + static final String DD_ENV_VARS_PROVIDER_KEY_HEADER = "DD-Env-Vars-Provider-Key"; + final Config config; final CiVisibilityMetricCollector metricCollector; final BackendApi backendApi; @@ -63,13 +78,15 @@ public class CiVisibilityServices { new BackendApiFactory(config, sco).createBackendApi(BackendApiFactory.Intake.API); this.jvmInfoFactory = new CachingJvmInfoFactory(config, new JvmInfoFactoryImpl()); this.gitClientFactory = new GitClient.Factory(config, metricCollector); - this.ciProviderInfoFactory = new CIProviderInfoFactory(config); + + CiEnvironment environment = buildCiEnvironment(config, sco); + this.ciProviderInfoFactory = new CIProviderInfoFactory(config, environment); this.methodLinesResolver = new BestEffortMethodLinesResolver( new CompilerAidedMethodLinesResolver(), new ByteCodeMethodLinesResolver()); this.gitInfoProvider = gitInfoProvider; - gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder()); + gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder(config, environment)); gitInfoProvider.registerGitInfoBuilder( new CILocalGitInfoBuilder(gitClientFactory, GIT_FOLDER_NAME)); gitInfoProvider.registerGitInfoBuilder(new GitClientGitInfoBuilder(config, gitClientFactory)); @@ -94,6 +111,55 @@ public class CiVisibilityServices { } } + @NotNull + private static CiEnvironment buildCiEnvironment(Config config, SharedCommunicationObjects sco) { + String remoteEnvVarsProviderUrl = config.getCiVisibilityRemoteEnvVarsProviderUrl(); + if (remoteEnvVarsProviderUrl != null) { + String remoteEnvVarsProviderKey = config.getCiVisibilityRemoteEnvVarsProviderKey(); + CiEnvironment remoteEnvironment = + new CiEnvironmentImpl( + getRemoteEnvironment( + remoteEnvVarsProviderUrl, remoteEnvVarsProviderKey, sco.okHttpClient)); + CiEnvironment localEnvironment = new CiEnvironmentImpl(System.getenv()); + return new CompositeCiEnvironment(remoteEnvironment, localEnvironment); + } else { + return new CiEnvironmentImpl(System.getenv()); + } + } + + static Map getRemoteEnvironment(String url, String key, OkHttpClient httpClient) { + HttpRetryPolicy.Factory retryPolicyFactory = new HttpRetryPolicy.Factory(5, 100, 2.0, true); + + HttpUrl httpUrl = HttpUrl.get(url); + Request request = + new Request.Builder() + .url(httpUrl) + .header(DD_ENV_VARS_PROVIDER_KEY_HEADER, key) + .get() + .build(); + try (okhttp3.Response response = + OkHttpUtils.sendWithRetries(httpClient, retryPolicyFactory, request)) { + + if (response.isSuccessful()) { + Moshi moshi = new Moshi.Builder().build(); + Type type = Types.newParameterizedType(Map.class, String.class, String.class); + JsonAdapter> adapter = moshi.adapter(type); + return adapter.fromJson(response.body().source()); + } else { + logger.warn( + "Could not get remote CI environment (HTTP code " + + response.code() + + ")" + + (response.body() != null ? ": " + response.body().string() : "")); + return Collections.emptyMap(); + } + + } catch (Exception e) { + logger.warn("Could not get remote CI environment", e); + return Collections.emptyMap(); + } + } + CiVisibilityRepoServices repoServices(Path path) { return new CiVisibilityRepoServices(this, path); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AppVeyorInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AppVeyorInfo.java index 80315deb1d8..d5e97d581b3 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AppVeyorInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AppVeyorInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class AppVeyorInfo implements CIProviderInfo { @@ -31,13 +32,19 @@ class AppVeyorInfo implements CIProviderInfo { public static final String APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL = "APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL"; + private final CiEnvironment environment; + + AppVeyorInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { - final String repoProvider = System.getenv(APPVEYOR_REPO_PROVIDER); - final String messageSubject = System.getenv(APPVEYOR_REPO_COMMIT_MESSAGE_SUBJECT); - final String messageBody = System.getenv(APPVEYOR_REPO_COMMIT_MESSAGE_BODY); + final String repoProvider = environment.get(APPVEYOR_REPO_PROVIDER); + final String messageSubject = environment.get(APPVEYOR_REPO_COMMIT_MESSAGE_SUBJECT); + final String messageBody = environment.get(APPVEYOR_REPO_COMMIT_MESSAGE_BODY); return new GitInfo( - buildGitRepositoryUrl(repoProvider, System.getenv(APPVEYOR_REPO_NAME)), + buildGitRepositoryUrl(repoProvider, environment.get(APPVEYOR_REPO_NAME)), buildGitBranch(repoProvider), buildGitTag(repoProvider), new CommitInfo( @@ -60,23 +67,23 @@ private static String getCommitMessage(String messageSubject, String messageBody @Override public CIInfo buildCIInfo() { final String url = - buildPipelineUrl(System.getenv(APPVEYOR_REPO_NAME), System.getenv(APPVEYOR_BUILD_ID)); - return CIInfo.builder() + buildPipelineUrl(environment.get(APPVEYOR_REPO_NAME), environment.get(APPVEYOR_BUILD_ID)); + return CIInfo.builder(environment) .ciProviderName(APPVEYOR_PROVIDER_NAME) - .ciPipelineId(System.getenv(APPVEYOR_BUILD_ID)) - .ciPipelineName(System.getenv(APPVEYOR_REPO_NAME)) - .ciPipelineNumber(System.getenv(APPVEYOR_PIPELINE_NUMBER)) + .ciPipelineId(environment.get(APPVEYOR_BUILD_ID)) + .ciPipelineName(environment.get(APPVEYOR_REPO_NAME)) + .ciPipelineNumber(environment.get(APPVEYOR_PIPELINE_NUMBER)) .ciPipelineUrl(url) .ciJobUrl(url) - .ciWorkspace(expandTilde(System.getenv(APPVEYOR_WORKSPACE_PATH))) + .ciWorkspace(expandTilde(environment.get(APPVEYOR_WORKSPACE_PATH))) .build(); } private String buildGitBranch(final String repoProvider) { if ("github".equals(repoProvider)) { - String branch = System.getenv(APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH); + String branch = environment.get(APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH); if (branch == null || branch.isEmpty()) { - branch = System.getenv(APPVEYOR_REPO_BRANCH); + branch = environment.get(APPVEYOR_REPO_BRANCH); } return normalizeBranch(branch); } @@ -85,14 +92,14 @@ private String buildGitBranch(final String repoProvider) { private String buildGitTag(final String repoProvider) { if ("github".equals(repoProvider)) { - return normalizeTag(System.getenv(APPVEYOR_REPO_TAG_NAME)); + return normalizeTag(environment.get(APPVEYOR_REPO_TAG_NAME)); } return null; } private String buildGitCommit() { - if ("github".equals(System.getenv(APPVEYOR_REPO_PROVIDER))) { - return System.getenv(APPVEYOR_REPO_COMMIT); + if ("github".equals(environment.get(APPVEYOR_REPO_PROVIDER))) { + return environment.get(APPVEYOR_REPO_COMMIT); } return null; } @@ -110,8 +117,8 @@ private String buildPipelineUrl(final String repoName, final String buildId) { private PersonInfo buildGitCommitAuthor() { return new PersonInfo( - System.getenv(APPVEYOR_REPO_COMMIT_AUTHOR_NAME), - System.getenv(APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL)); + environment.get(APPVEYOR_REPO_COMMIT_AUTHOR_NAME), + environment.get(APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL)); } @Override diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AwsCodePipelineInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AwsCodePipelineInfo.java index fcae8d11248..72d672e0528 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AwsCodePipelineInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AwsCodePipelineInfo.java @@ -2,6 +2,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class AwsCodePipelineInfo implements CIProviderInfo { @@ -11,6 +12,12 @@ class AwsCodePipelineInfo implements CIProviderInfo { public static final String AWS_CODEPIPELINE_ACTION_EXECUTION_ID = "DD_ACTION_EXECUTION_ID"; public static final String AWS_CODEPIPELINE_ARN = "CODEBUILD_BUILD_ARN"; + private final CiEnvironment environment; + + AwsCodePipelineInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return GitInfo.NOOP; @@ -18,9 +25,9 @@ public GitInfo buildCIGitInfo() { @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(AWS_CODEPIPELINE_PROVIDER_NAME) - .ciPipelineId(System.getenv(AWS_CODEPIPELINE_EXECUTION_ID)) + .ciPipelineId(environment.get(AWS_CODEPIPELINE_EXECUTION_ID)) .ciEnvVars( AWS_CODEPIPELINE_EXECUTION_ID, AWS_CODEPIPELINE_ACTION_EXECUTION_ID, diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AzurePipelinesInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AzurePipelinesInfo.java index 65cabf1d603..708a6bea6be 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AzurePipelinesInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AzurePipelinesInfo.java @@ -10,6 +10,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class AzurePipelinesInfo implements CIProviderInfo { @@ -39,6 +40,12 @@ class AzurePipelinesInfo implements CIProviderInfo { public static final String AZURE_BUILD_REQUESTED_FOR_ID = "BUILD_REQUESTEDFORID"; public static final String AZURE_BUILD_REQUESTED_FOR_EMAIL = "BUILD_REQUESTEDFOREMAIL"; + private final CiEnvironment environment; + + AzurePipelinesInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( @@ -49,27 +56,27 @@ public GitInfo buildCIGitInfo() { buildGitCommit(), buildGitCommitAuthor(), PersonInfo.NOOP, - System.getenv(AZURE_BUILD_SOURCEVERSION_MESSAGE))); + environment.get(AZURE_BUILD_SOURCEVERSION_MESSAGE))); } @Override public CIInfo buildCIInfo() { - final String uri = System.getenv(AZURE_SYSTEM_TEAMFOUNDATIONSERVERURI); - final String project = System.getenv(AZURE_SYSTEM_TEAMPROJECTID); - final String buildId = System.getenv(AZURE_BUILD_BUILDID); - final String jobId = System.getenv(AZURE_SYSTEM_JOBID); - final String taskId = System.getenv(AZURE_SYSTEM_TASKINSTANCEID); + final String uri = environment.get(AZURE_SYSTEM_TEAMFOUNDATIONSERVERURI); + final String project = environment.get(AZURE_SYSTEM_TEAMPROJECTID); + final String buildId = environment.get(AZURE_BUILD_BUILDID); + final String jobId = environment.get(AZURE_SYSTEM_JOBID); + final String taskId = environment.get(AZURE_SYSTEM_TASKINSTANCEID); - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(AZURE_PROVIDER_NAME) - .ciPipelineId(System.getenv(AZURE_BUILD_BUILDID)) - .ciPipelineName(System.getenv(AZURE_PIPELINE_NAME)) + .ciPipelineId(environment.get(AZURE_BUILD_BUILDID)) + .ciPipelineName(environment.get(AZURE_PIPELINE_NAME)) .ciPipelineNumber(buildId) .ciPipelineUrl(buildCiPipelineUrl(uri, project, buildId)) - .ciStageName(System.getenv(AZURE_SYSTEM_STAGEDISPLAYNAME)) - .ciJobName(System.getenv(AZURE_SYSTEM_JOBDISPLAYNAME)) + .ciStageName(environment.get(AZURE_SYSTEM_STAGEDISPLAYNAME)) + .ciJobName(environment.get(AZURE_SYSTEM_JOBDISPLAYNAME)) .ciJobUrl(buildCiJobUrl(uri, project, buildId, jobId, taskId)) - .ciWorkspace(expandTilde(System.getenv(AZURE_WORKSPACE_PATH))) + .ciWorkspace(expandTilde(environment.get(AZURE_WORKSPACE_PATH))) .ciEnvVars(AZURE_SYSTEM_TEAMPROJECTID, AZURE_BUILD_BUILDID, AZURE_SYSTEM_JOBID) .build(); } @@ -92,26 +99,26 @@ private String buildGitTag() { } } - private static String getGitBranchOrTag() { - String gitBranchOrTag = System.getenv(AZURE_SYSTEM_PULLREQUEST_SOURCEBRANCH); + private String getGitBranchOrTag() { + String gitBranchOrTag = environment.get(AZURE_SYSTEM_PULLREQUEST_SOURCEBRANCH); if (gitBranchOrTag == null || gitBranchOrTag.isEmpty()) { - gitBranchOrTag = System.getenv(AZURE_BUILD_SOURCEBRANCH); + gitBranchOrTag = environment.get(AZURE_BUILD_SOURCEBRANCH); } return gitBranchOrTag; } private String buildGitCommit() { - String commit = System.getenv(AZURE_SYSTEM_PULLREQUEST_SOURCECOMMITID); + String commit = environment.get(AZURE_SYSTEM_PULLREQUEST_SOURCECOMMITID); if (commit == null || commit.isEmpty()) { - commit = System.getenv(AZURE_BUILD_SOURCEVERSION); + commit = environment.get(AZURE_BUILD_SOURCEVERSION); } return commit; } private String buildGitRepositoryUrl() { - String repoUrl = System.getenv(AZURE_SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI); + String repoUrl = environment.get(AZURE_SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI); if (repoUrl == null || repoUrl.isEmpty()) { - repoUrl = System.getenv(AZURE_BUILD_REPOSITORY_URI); + repoUrl = environment.get(AZURE_BUILD_REPOSITORY_URI); } return filterSensitiveInfo(repoUrl); } @@ -132,8 +139,8 @@ private String buildCiPipelineUrl(final String uri, final String project, final private PersonInfo buildGitCommitAuthor() { return new PersonInfo( - System.getenv(AZURE_BUILD_REQUESTED_FOR_ID), - System.getenv(AZURE_BUILD_REQUESTED_FOR_EMAIL)); + environment.get(AZURE_BUILD_REQUESTED_FOR_ID), + environment.get(AZURE_BUILD_REQUESTED_FOR_EMAIL)); } @Override diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitBucketInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitBucketInfo.java index 80c1e705dc5..63b9eace1e5 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitBucketInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitBucketInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import datadog.trace.util.Strings; class BitBucketInfo implements CIProviderInfo { @@ -25,21 +26,27 @@ class BitBucketInfo implements CIProviderInfo { public static final String BITBUCKET_GIT_BRANCH = "BITBUCKET_BRANCH"; public static final String BITBUCKET_GIT_TAG = "BITBUCKET_TAG"; + private final CiEnvironment environment; + + BitBucketInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( getRepositoryURL(), - normalizeBranch(System.getenv(BITBUCKET_GIT_BRANCH)), - normalizeTag(System.getenv(BITBUCKET_GIT_TAG)), - new CommitInfo(System.getenv(BITBUCKET_GIT_COMMIT))); + normalizeBranch(environment.get(BITBUCKET_GIT_BRANCH)), + normalizeTag(environment.get(BITBUCKET_GIT_TAG)), + new CommitInfo(environment.get(BITBUCKET_GIT_COMMIT))); } - private static String getRepositoryURL() { - String gitRepoUrl = System.getenv(BITBUCKET_GIT_REPOSITORY_URL); + private String getRepositoryURL() { + String gitRepoUrl = environment.get(BITBUCKET_GIT_REPOSITORY_URL); if (Strings.isNotBlank(gitRepoUrl)) { return filterSensitiveInfo(gitRepoUrl); } - String httpsRepoUrl = System.getenv(BITBUCKET_HTTPS_REPOSITORY_URL); + String httpsRepoUrl = environment.get(BITBUCKET_HTTPS_REPOSITORY_URL); if (Strings.isNotBlank(httpsRepoUrl)) { return filterSensitiveInfo(httpsRepoUrl); } @@ -48,18 +55,18 @@ private static String getRepositoryURL() { @Override public CIInfo buildCIInfo() { - final String repo = System.getenv(BITBUCKET_REPO_FULL_NAME); - final String number = System.getenv(BITBUCKET_BUILD_NUMBER); + final String repo = environment.get(BITBUCKET_REPO_FULL_NAME); + final String number = environment.get(BITBUCKET_BUILD_NUMBER); final String url = buildPipelineUrl(repo, number); - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(BITBUCKET_PROVIDER_NAME) .ciPipelineId(buildPipelineId()) .ciPipelineName(repo) .ciPipelineNumber(number) .ciPipelineUrl(url) .ciJobUrl(url) - .ciWorkspace(expandTilde(System.getenv(BITBUCKET_WORKSPACE_PATH))) + .ciWorkspace(expandTilde(environment.get(BITBUCKET_WORKSPACE_PATH))) .build(); } @@ -69,7 +76,7 @@ private String buildPipelineUrl(final String repo, final String number) { } private String buildPipelineId() { - String id = System.getenv(BITBUCKET_PIPELINE_ID); + String id = environment.get(BITBUCKET_PIPELINE_ID); if (id != null) { id = Strings.replace(id, "{", ""); id = Strings.replace(id, "}", ""); diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitriseInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitriseInfo.java index 7428fe5ff24..b5af995835a 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitriseInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitriseInfo.java @@ -9,6 +9,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class BitriseInfo implements CIProviderInfo { @@ -30,40 +31,47 @@ class BitriseInfo implements CIProviderInfo { public static final String BITRISE_GIT_COMMITER_NAME = "GIT_CLONE_COMMIT_COMMITER_NAME"; public static final String BITRISE_GIT_COMMITER_EMAIL = "GIT_CLONE_COMMIT_COMMITER_EMAIL"; + private final CiEnvironment environment; + + BitriseInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( - filterSensitiveInfo(System.getenv(BITRISE_GIT_REPOSITORY_URL)), - normalizeBranch(System.getenv(BITRISE_GIT_BRANCH)), - normalizeTag(System.getenv(BITRISE_GIT_TAG)), + filterSensitiveInfo(environment.get(BITRISE_GIT_REPOSITORY_URL)), + normalizeBranch(environment.get(BITRISE_GIT_BRANCH)), + normalizeTag(environment.get(BITRISE_GIT_TAG)), new CommitInfo( buildGitCommit(), new PersonInfo( - System.getenv(BITRISE_GIT_AUTHOR_NAME), System.getenv(BITRISE_GIT_AUTHOR_EMAIL)), + environment.get(BITRISE_GIT_AUTHOR_NAME), + environment.get(BITRISE_GIT_AUTHOR_EMAIL)), new PersonInfo( - System.getenv(BITRISE_GIT_COMMITER_NAME), - System.getenv(BITRISE_GIT_COMMITER_EMAIL)), - System.getenv(BITRISE_GIT_MESSAGE))); + environment.get(BITRISE_GIT_COMMITER_NAME), + environment.get(BITRISE_GIT_COMMITER_EMAIL)), + environment.get(BITRISE_GIT_MESSAGE))); } @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(BITRISE_PROVIDER_NAME) - .ciPipelineId(System.getenv(BITRISE_PIPELINE_ID)) - .ciPipelineName(System.getenv(BITRISE_PIPELINE_NAME)) - .ciPipelineNumber(System.getenv(BITRISE_PIPELINE_NUMBER)) - .ciPipelineUrl(System.getenv(BITRISE_PIPELINE_URL)) - .ciWorkspace(expandTilde(System.getenv(BITRISE_WORKSPACE_PATH))) + .ciPipelineId(environment.get(BITRISE_PIPELINE_ID)) + .ciPipelineName(environment.get(BITRISE_PIPELINE_NAME)) + .ciPipelineNumber(environment.get(BITRISE_PIPELINE_NUMBER)) + .ciPipelineUrl(environment.get(BITRISE_PIPELINE_URL)) + .ciWorkspace(expandTilde(environment.get(BITRISE_WORKSPACE_PATH))) .build(); } private String buildGitCommit() { - final String fromCommit = System.getenv(BITRISE_GIT_PR_COMMIT); + final String fromCommit = environment.get(BITRISE_GIT_PR_COMMIT); if (fromCommit != null && !fromCommit.isEmpty()) { return fromCommit; } else { - return System.getenv(BITRISE_GIT_COMMIT); + return environment.get(BITRISE_GIT_COMMIT); } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuddyInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuddyInfo.java index 2315f806f2f..8118c9c22c8 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuddyInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuddyInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class BuddyInfo implements CIProviderInfo { @@ -26,33 +27,39 @@ class BuddyInfo implements CIProviderInfo { public static final String BUDDY_GIT_COMMIT_AUTHOR = "BUDDY_EXECUTION_REVISION_COMMITTER_NAME"; public static final String BUDDY_GIT_COMMIT_EMAIL = "BUDDY_EXECUTION_REVISION_COMMITTER_EMAIL"; + private final CiEnvironment environment; + + BuddyInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( - filterSensitiveInfo(System.getenv(BUDDY_GIT_REPOSITORY_URL)), - normalizeBranch(System.getenv(BUDDY_GIT_BRANCH)), - normalizeTag(System.getenv(BUDDY_GIT_TAG)), + filterSensitiveInfo(environment.get(BUDDY_GIT_REPOSITORY_URL)), + normalizeBranch(environment.get(BUDDY_GIT_BRANCH)), + normalizeTag(environment.get(BUDDY_GIT_TAG)), new CommitInfo( - System.getenv(BUDDY_GIT_COMMIT), + environment.get(BUDDY_GIT_COMMIT), PersonInfo.NOOP, buildGitCommiter(), - System.getenv(BUDDY_GIT_COMMIT_MESSAGE))); + environment.get(BUDDY_GIT_COMMIT_MESSAGE))); } @Override public CIInfo buildCIInfo() { - String pipelineNumber = System.getenv(BUDDY_PIPELINE_EXECUTION_ID); - return CIInfo.builder() + String pipelineNumber = environment.get(BUDDY_PIPELINE_EXECUTION_ID); + return CIInfo.builder(environment) .ciProviderName(BUDDY_PROVIDER_NAME) .ciPipelineId(getPipelineId(pipelineNumber)) - .ciPipelineName(System.getenv(BUDDY_PIPELINE_NAME)) + .ciPipelineName(environment.get(BUDDY_PIPELINE_NAME)) .ciPipelineNumber(pipelineNumber) - .ciPipelineUrl(System.getenv(BUDDY_PIPELINE_EXECUTION_URL)) + .ciPipelineUrl(environment.get(BUDDY_PIPELINE_EXECUTION_URL)) .build(); } - private static String getPipelineId(String pipelineNumber) { - String pipelineId = System.getenv(BUDDY_PIPELINE_ID); + private String getPipelineId(String pipelineNumber) { + String pipelineId = environment.get(BUDDY_PIPELINE_ID); if (pipelineId == null) { return pipelineNumber; } @@ -64,7 +71,7 @@ private static String getPipelineId(String pipelineNumber) { private PersonInfo buildGitCommiter() { return new PersonInfo( - System.getenv(BUDDY_GIT_COMMIT_AUTHOR), System.getenv(BUDDY_GIT_COMMIT_EMAIL)); + environment.get(BUDDY_GIT_COMMIT_AUTHOR), environment.get(BUDDY_GIT_COMMIT_EMAIL)); } @Override diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuildkiteInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuildkiteInfo.java index 72ba40ee611..4aa2a6781b9 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuildkiteInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuildkiteInfo.java @@ -10,6 +10,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -36,32 +37,38 @@ class BuildkiteInfo implements CIProviderInfo { public static final String BUILDKITE_AGENT_ID = "BUILDKITE_AGENT_ID"; private static final String BUILDKITE_CI_NODE_LABEL_PREFIX = "BUILDKITE_AGENT_META_DATA_"; + private final CiEnvironment environment; + + BuildkiteInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( - filterSensitiveInfo(System.getenv(BUILDKITE_GIT_REPOSITORY_URL)), - normalizeBranch(System.getenv(BUILDKITE_GIT_BRANCH)), - normalizeTag(System.getenv(BUILDKITE_GIT_TAG)), + filterSensitiveInfo(environment.get(BUILDKITE_GIT_REPOSITORY_URL)), + normalizeBranch(environment.get(BUILDKITE_GIT_BRANCH)), + normalizeTag(environment.get(BUILDKITE_GIT_TAG)), new CommitInfo( - System.getenv(BUILDKITE_GIT_COMMIT), + environment.get(BUILDKITE_GIT_COMMIT), buildGitCommitAuthor(), PersonInfo.NOOP, - System.getenv(BUILDKITE_GIT_MESSAGE))); + environment.get(BUILDKITE_GIT_MESSAGE))); } @Override public CIInfo buildCIInfo() { - final String ciPipelineUrl = System.getenv(BUILDKITE_BUILD_URL); + final String ciPipelineUrl = environment.get(BUILDKITE_BUILD_URL); - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(BUILDKITE_PROVIDER_NAME) - .ciPipelineId(System.getenv(BUILDKITE_PIPELINE_ID)) - .ciPipelineName(System.getenv(BUILDKITE_PIPELINE_NAME)) - .ciPipelineNumber(System.getenv(BUILDKITE_PIPELINE_NUMBER)) + .ciPipelineId(environment.get(BUILDKITE_PIPELINE_ID)) + .ciPipelineName(environment.get(BUILDKITE_PIPELINE_NAME)) + .ciPipelineNumber(environment.get(BUILDKITE_PIPELINE_NUMBER)) .ciPipelineUrl(ciPipelineUrl) - .ciJobUrl(String.format("%s#%s", ciPipelineUrl, System.getenv(BUILDKITE_JOB_ID))) - .ciWorkspace(expandTilde(System.getenv(BUILDKITE_WORKSPACE_PATH))) - .ciNodeName(System.getenv(BUILDKITE_AGENT_ID)) + .ciJobUrl(String.format("%s#%s", ciPipelineUrl, environment.get(BUILDKITE_JOB_ID))) + .ciWorkspace(expandTilde(environment.get(BUILDKITE_WORKSPACE_PATH))) + .ciNodeName(environment.get(BUILDKITE_AGENT_ID)) .ciNodeLabels(buildCiNodeLabels()) .ciEnvVars(BUILDKITE_PIPELINE_ID, BUILDKITE_JOB_ID) .build(); @@ -69,7 +76,7 @@ public CIInfo buildCIInfo() { private String buildCiNodeLabels() { List labels = new ArrayList<>(); - for (Map.Entry e : System.getenv().entrySet()) { + for (Map.Entry e : environment.get().entrySet()) { String envVar = e.getKey(); if (envVar.startsWith(BUILDKITE_CI_NODE_LABEL_PREFIX)) { String labelKey = @@ -83,7 +90,7 @@ private String buildCiNodeLabels() { private PersonInfo buildGitCommitAuthor() { return new PersonInfo( - System.getenv(BUILDKITE_GIT_AUTHOR_NAME), System.getenv(BUILDKITE_GIT_AUTHOR_EMAIL)); + environment.get(BUILDKITE_GIT_AUTHOR_NAME), environment.get(BUILDKITE_GIT_AUTHOR_EMAIL)); } @Override diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIInfo.java index 3c7ffc31825..9fb2bbfb81f 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIInfo.java @@ -2,6 +2,7 @@ import static datadog.trace.api.git.GitUtils.filterSensitiveInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import datadog.trace.civisibility.utils.FileUtils; import java.io.File; import java.util.HashMap; @@ -11,11 +12,13 @@ public class CIInfo { public static final CIInfo NOOP = new CIInfo(); - public static Builder builder() { - return new Builder(); + public static Builder builder(CiEnvironment environment) { + return new Builder(environment); } public static final class Builder { + private final CiEnvironment environment; + private String ciProviderName; private String ciPipelineId; private String ciPipelineName; @@ -30,6 +33,10 @@ public static final class Builder { private Map ciEnvVars; private Map additionalTags; + public Builder(CiEnvironment environment) { + this.environment = environment; + } + public Builder ciProviderName(String ciProviderName) { this.ciProviderName = ciProviderName; return this; @@ -92,7 +99,7 @@ public Builder ciEnvVars(String... ciEnvVarKeysArray) { ciEnvVars = new HashMap<>(); for (String ciEnvVarKey : ciEnvVarKeysArray) { - final String envVarVal = filterSensitiveInfo(System.getenv(ciEnvVarKey)); + final String envVarVal = filterSensitiveInfo(environment.get(ciEnvVarKey)); if (envVarVal != null && !envVarVal.isEmpty()) { ciEnvVars.put(ciEnvVarKey, envVarVal); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIProviderInfoFactory.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIProviderInfoFactory.java index 37a651678b7..df6dd218a88 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIProviderInfoFactory.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIProviderInfoFactory.java @@ -1,61 +1,64 @@ package datadog.trace.civisibility.ci; import datadog.trace.api.Config; +import datadog.trace.civisibility.ci.env.CiEnvironment; import java.nio.file.Path; public class CIProviderInfoFactory { private final String targetFolder; private final Config config; + private final CiEnvironment environment; - public CIProviderInfoFactory(Config config) { - this(config, ".git"); + public CIProviderInfoFactory(Config config, CiEnvironment environment) { + this(config, ".git", environment); } - CIProviderInfoFactory(Config config, String targetFolder) { + CIProviderInfoFactory(Config config, String targetFolder, CiEnvironment environment) { this.targetFolder = targetFolder; this.config = config; + this.environment = environment; } public CIProviderInfo createCIProviderInfo(Path currentPath) { if (!config.isCiVisibilityCiProviderIntegrationEnabled()) { - return new UnknownCIInfo(targetFolder, currentPath); + return new UnknownCIInfo(environment, targetFolder, currentPath); } // CI and Git information is obtained // from different environment variables // depending on which CI server is running the build. - if (System.getenv(JenkinsInfo.JENKINS) != null) { - return new JenkinsInfo(); - } else if (System.getenv(GitLabInfo.GITLAB) != null) { - return new GitLabInfo(); - } else if (System.getenv(TravisInfo.TRAVIS) != null) { - return new TravisInfo(); - } else if (System.getenv(CircleCIInfo.CIRCLECI) != null) { - return new CircleCIInfo(); - } else if (System.getenv(AppVeyorInfo.APPVEYOR) != null) { - return new AppVeyorInfo(); - } else if (System.getenv(AzurePipelinesInfo.AZURE) != null) { - return new AzurePipelinesInfo(); - } else if (System.getenv(BitBucketInfo.BITBUCKET) != null) { - return new BitBucketInfo(); - } else if (System.getenv(GithubActionsInfo.GHACTIONS) != null) { - return new GithubActionsInfo(); - } else if (System.getenv(BuildkiteInfo.BUILDKITE) != null) { - return new BuildkiteInfo(); - } else if (System.getenv(BitriseInfo.BITRISE) != null) { - return new BitriseInfo(); - } else if (System.getenv(BuddyInfo.BUDDY) != null) { - return new BuddyInfo(); - } else if (System.getenv(CodefreshInfo.CODEFRESH) != null) { - return new CodefreshInfo(); - } else if (System.getenv(TeamcityInfo.TEAMCITY) != null) { - return new TeamcityInfo(); - } else if (System.getenv(AwsCodePipelineInfo.AWS_CODEPIPELINE) != null - && System.getenv(AwsCodePipelineInfo.AWS_CODEPIPELINE).startsWith("codepipeline")) { - return new AwsCodePipelineInfo(); + if (environment.get(JenkinsInfo.JENKINS) != null) { + return new JenkinsInfo(environment); + } else if (environment.get(GitLabInfo.GITLAB) != null) { + return new GitLabInfo(environment); + } else if (environment.get(TravisInfo.TRAVIS) != null) { + return new TravisInfo(environment); + } else if (environment.get(CircleCIInfo.CIRCLECI) != null) { + return new CircleCIInfo(environment); + } else if (environment.get(AppVeyorInfo.APPVEYOR) != null) { + return new AppVeyorInfo(environment); + } else if (environment.get(AzurePipelinesInfo.AZURE) != null) { + return new AzurePipelinesInfo(environment); + } else if (environment.get(BitBucketInfo.BITBUCKET) != null) { + return new BitBucketInfo(environment); + } else if (environment.get(GithubActionsInfo.GHACTIONS) != null) { + return new GithubActionsInfo(environment); + } else if (environment.get(BuildkiteInfo.BUILDKITE) != null) { + return new BuildkiteInfo(environment); + } else if (environment.get(BitriseInfo.BITRISE) != null) { + return new BitriseInfo(environment); + } else if (environment.get(BuddyInfo.BUDDY) != null) { + return new BuddyInfo(environment); + } else if (environment.get(CodefreshInfo.CODEFRESH) != null) { + return new CodefreshInfo(environment); + } else if (environment.get(TeamcityInfo.TEAMCITY) != null) { + return new TeamcityInfo(environment); + } else if (environment.get(AwsCodePipelineInfo.AWS_CODEPIPELINE) != null + && environment.get(AwsCodePipelineInfo.AWS_CODEPIPELINE).startsWith("codepipeline")) { + return new AwsCodePipelineInfo(environment); } else { - return new UnknownCIInfo(targetFolder, currentPath); + return new UnknownCIInfo(environment, targetFolder, currentPath); } } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CircleCIInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CircleCIInfo.java index 690bcac6f38..f18fab7c949 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CircleCIInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CircleCIInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class CircleCIInfo implements CIProviderInfo { @@ -25,26 +26,32 @@ class CircleCIInfo implements CIProviderInfo { public static final String CIRCLECI_GIT_TAG = "CIRCLE_TAG"; public static final String CIRCLECI_JOB_NAME = "CIRCLE_JOB"; + private final CiEnvironment environment; + + CircleCIInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( - filterSensitiveInfo(System.getenv(CIRCLECI_GIT_REPOSITORY_URL)), - normalizeBranch(System.getenv(CIRCLECI_GIT_BRANCH)), - normalizeTag(System.getenv(CIRCLECI_GIT_TAG)), - new CommitInfo(System.getenv(CIRCLECI_GIT_COMMIT))); + filterSensitiveInfo(environment.get(CIRCLECI_GIT_REPOSITORY_URL)), + normalizeBranch(environment.get(CIRCLECI_GIT_BRANCH)), + normalizeTag(environment.get(CIRCLECI_GIT_TAG)), + new CommitInfo(environment.get(CIRCLECI_GIT_COMMIT))); } @Override public CIInfo buildCIInfo() { - final String pipelineId = System.getenv(CIRCLECI_PIPELINE_ID); - return CIInfo.builder() + final String pipelineId = environment.get(CIRCLECI_PIPELINE_ID); + return CIInfo.builder(environment) .ciProviderName(CIRCLECI_PROVIDER_NAME) .ciPipelineId(pipelineId) - .ciPipelineName(System.getenv(CIRCLECI_PIPELINE_NAME)) + .ciPipelineName(environment.get(CIRCLECI_PIPELINE_NAME)) .ciPipelineUrl(buildPipelineUrl(pipelineId)) - .ciJobName(System.getenv(CIRCLECI_JOB_NAME)) - .ciJobUrl(System.getenv(CIRCLECI_BUILD_URL)) - .ciWorkspace(expandTilde(System.getenv(CIRCLECI_WORKSPACE_PATH))) + .ciJobName(environment.get(CIRCLECI_JOB_NAME)) + .ciJobUrl(environment.get(CIRCLECI_BUILD_URL)) + .ciWorkspace(expandTilde(environment.get(CIRCLECI_WORKSPACE_PATH))) .ciEnvVars(CIRCLECI_PIPELINE_ID, CIRCLECI_BUILD_NUM) .build(); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CodefreshInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CodefreshInfo.java index a639ff53ca9..5dcdbe1abcb 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CodefreshInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CodefreshInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; public class CodefreshInfo implements CIProviderInfo { public static final String CODEFRESH = "CF_BUILD_ID"; @@ -20,6 +21,12 @@ public class CodefreshInfo implements CIProviderInfo { private static final String CF_COMMIT_MESSAGE = "CF_COMMIT_MESSAGE"; private static final String CF_COMMIT_AUTHOR = "CF_COMMIT_AUTHOR"; + private final CiEnvironment environment; + + CodefreshInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( @@ -27,10 +34,10 @@ public GitInfo buildCIGitInfo() { buildGitBranch(), buildGitTag(), new CommitInfo( - System.getenv(CF_REVISION), - new PersonInfo(System.getenv(CF_COMMIT_AUTHOR), null), + environment.get(CF_REVISION), + new PersonInfo(environment.get(CF_COMMIT_AUTHOR), null), PersonInfo.NOOP, - System.getenv(CF_COMMIT_MESSAGE))); + environment.get(CF_COMMIT_MESSAGE))); } private String buildGitBranch() { @@ -51,18 +58,18 @@ private String buildGitTag() { } } - private static String getGitBranchOrTag() { - return System.getenv(CF_BRANCH); + private String getGitBranchOrTag() { + return environment.get(CF_BRANCH); } @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(CODEFRESH_PROVIDER_NAME) - .ciPipelineId(System.getenv(CODEFRESH)) - .ciPipelineName(System.getenv(CF_PIPELINE_NAME)) - .ciPipelineUrl(System.getenv(CF_BUILD_URL)) - .ciJobName(System.getenv(CF_STEP_NAME)) + .ciPipelineId(environment.get(CODEFRESH)) + .ciPipelineName(environment.get(CF_PIPELINE_NAME)) + .ciPipelineUrl(environment.get(CF_BUILD_URL)) + .ciJobName(environment.get(CF_STEP_NAME)) .ciEnvVars(CODEFRESH) .build(); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GitLabInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GitLabInfo.java index ba31b498ef7..ce99e955371 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GitLabInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GitLabInfo.java @@ -10,6 +10,7 @@ import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.GitUtils; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import de.thetaphi.forbiddenapis.SuppressForbidden; @SuppressForbidden @@ -38,46 +39,52 @@ class GitLabInfo implements CIProviderInfo { public static final String GITLAB_CI_RUNNER_ID = "CI_RUNNER_ID"; public static final String GITLAB_CI_RUNNER_TAGS = "CI_RUNNER_TAGS"; + private final CiEnvironment environment; + + GitLabInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( - filterSensitiveInfo(System.getenv(GITLAB_GIT_REPOSITORY_URL)), - normalizeBranch(System.getenv(GITLAB_GIT_BRANCH)), - normalizeTag(System.getenv(GITLAB_GIT_TAG)), + filterSensitiveInfo(environment.get(GITLAB_GIT_REPOSITORY_URL)), + normalizeBranch(environment.get(GITLAB_GIT_BRANCH)), + normalizeTag(environment.get(GITLAB_GIT_TAG)), new CommitInfo( - System.getenv(GITLAB_GIT_COMMIT), + environment.get(GITLAB_GIT_COMMIT), buildGitCommitAuthor(), PersonInfo.NOOP, - System.getenv(GITLAB_GIT_COMMIT_MESSAGE))); + environment.get(GITLAB_GIT_COMMIT_MESSAGE))); } @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(GITLAB_PROVIDER_NAME) - .ciPipelineId(System.getenv(GITLAB_PIPELINE_ID)) - .ciPipelineName(System.getenv(GITLAB_PIPELINE_NAME)) - .ciPipelineNumber(System.getenv(GITLAB_PIPELINE_NUMBER)) - .ciPipelineUrl(System.getenv(GITLAB_PIPELINE_URL)) - .ciStageName(System.getenv(GITLAB_STAGE_NAME)) - .ciJobName(System.getenv(GITLAB_JOB_NAME)) - .ciJobUrl(System.getenv(GITLAB_JOB_URL)) - .ciWorkspace(expandTilde(System.getenv(GITLAB_WORKSPACE_PATH))) - .ciNodeName(System.getenv(GITLAB_CI_RUNNER_ID)) - .ciNodeLabels(System.getenv(GITLAB_CI_RUNNER_TAGS)) + .ciPipelineId(environment.get(GITLAB_PIPELINE_ID)) + .ciPipelineName(environment.get(GITLAB_PIPELINE_NAME)) + .ciPipelineNumber(environment.get(GITLAB_PIPELINE_NUMBER)) + .ciPipelineUrl(environment.get(GITLAB_PIPELINE_URL)) + .ciStageName(environment.get(GITLAB_STAGE_NAME)) + .ciJobName(environment.get(GITLAB_JOB_NAME)) + .ciJobUrl(environment.get(GITLAB_JOB_URL)) + .ciWorkspace(expandTilde(environment.get(GITLAB_WORKSPACE_PATH))) + .ciNodeName(environment.get(GITLAB_CI_RUNNER_ID)) + .ciNodeLabels(environment.get(GITLAB_CI_RUNNER_TAGS)) .ciEnvVars(GITLAB_PROJECT_URL, GITLAB_PIPELINE_ID, GITLAB_JOB_ID) .build(); } private PersonInfo buildGitCommitAuthor() { - final String gitAuthor = System.getenv(GITLAB_GIT_COMMIT_AUTHOR); + final String gitAuthor = environment.get(GITLAB_GIT_COMMIT_AUTHOR); if (gitAuthor == null || gitAuthor.isEmpty()) { return PersonInfo.NOOP; } final PersonInfo personInfo = GitUtils.splitAuthorAndEmail(gitAuthor); return new PersonInfo( - personInfo.getName(), personInfo.getEmail(), System.getenv(GITLAB_GIT_COMMIT_TIMESTAMP)); + personInfo.getName(), personInfo.getEmail(), environment.get(GITLAB_GIT_COMMIT_TIMESTAMP)); } @Override diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java index 6260c2e3070..ee38ed4aefc 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java @@ -12,6 +12,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import datadog.trace.util.Strings; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -47,50 +48,57 @@ class GithubActionsInfo implements CIProviderInfo { public static final String GIT_PULL_REQUEST_BASE_BRANCH_SHA = "git.pull_request.base_branch_sha"; public static final String GIT_COMMIT_HEAD_SHA = "git.commit.head_sha"; + private final CiEnvironment environment; + + GithubActionsInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( buildGitRepositoryUrl( - filterSensitiveInfo(System.getenv(GHACTIONS_URL)), System.getenv(GHACTIONS_REPOSITORY)), + filterSensitiveInfo(environment.get(GHACTIONS_URL)), + environment.get(GHACTIONS_REPOSITORY)), buildGitBranch(), buildGitTag(), - new CommitInfo(System.getenv(GHACTIONS_SHA))); + new CommitInfo(environment.get(GHACTIONS_SHA))); } @Override public CIInfo buildCIInfo() { final String pipelineUrl = buildPipelineUrl( - filterSensitiveInfo(System.getenv(GHACTIONS_URL)), - System.getenv(GHACTIONS_REPOSITORY), - System.getenv(GHACTIONS_PIPELINE_ID), - System.getenv(GHACTIONS_PIPELINE_RETRY)); + filterSensitiveInfo(environment.get(GHACTIONS_URL)), + environment.get(GHACTIONS_REPOSITORY), + environment.get(GHACTIONS_PIPELINE_ID), + environment.get(GHACTIONS_PIPELINE_RETRY)); final String jobUrl = buildJobUrl( - filterSensitiveInfo(System.getenv(GHACTIONS_URL)), - System.getenv(GHACTIONS_REPOSITORY), - System.getenv(GHACTIONS_SHA)); + filterSensitiveInfo(environment.get(GHACTIONS_URL)), + environment.get(GHACTIONS_REPOSITORY), + environment.get(GHACTIONS_SHA)); - CIInfo.Builder builder = CIInfo.builder(); + CIInfo.Builder builder = CIInfo.builder(environment); setAdditionalTagsIfApplicable(builder); return builder .ciProviderName(GHACTIONS_PROVIDER_NAME) - .ciPipelineId(System.getenv(GHACTIONS_PIPELINE_ID)) - .ciPipelineName(System.getenv(GHACTIONS_PIPELINE_NAME)) - .ciPipelineNumber(System.getenv(GHACTIONS_PIPELINE_NUMBER)) + .ciPipelineId(environment.get(GHACTIONS_PIPELINE_ID)) + .ciPipelineName(environment.get(GHACTIONS_PIPELINE_NAME)) + .ciPipelineNumber(environment.get(GHACTIONS_PIPELINE_NUMBER)) .ciPipelineUrl(pipelineUrl) - .ciJobName(System.getenv(GHACTIONS_JOB)) + .ciJobName(environment.get(GHACTIONS_JOB)) .ciJobUrl(jobUrl) - .ciWorkspace(expandTilde(System.getenv(GHACTIONS_WORKSPACE_PATH))) + .ciWorkspace(expandTilde(environment.get(GHACTIONS_WORKSPACE_PATH))) .ciEnvVars( GHACTIONS_URL, GHACTIONS_REPOSITORY, GHACTIONS_PIPELINE_ID, GHACTIONS_PIPELINE_RETRY) .build(); } - private static void setAdditionalTagsIfApplicable(CIInfo.Builder builder) { - String baseRef = System.getenv(GITHUB_BASE_REF); + private void setAdditionalTagsIfApplicable(CIInfo.Builder builder) { + String baseRef = environment.get(GITHUB_BASE_REF); if (!Strings.isNotBlank(baseRef)) { return; } @@ -99,7 +107,7 @@ private static void setAdditionalTagsIfApplicable(CIInfo.Builder builder) { Map additionalTags = new HashMap<>(); additionalTags.put(GIT_PULL_REQUEST_BASE_BRANCH, baseRef); - Path eventPath = Paths.get(System.getenv(GITHUB_EVENT_PATH)); + Path eventPath = Paths.get(environment.get(GITHUB_EVENT_PATH)); String event = new String(Files.readAllBytes(eventPath), StandardCharsets.UTF_8); Moshi moshi = new Moshi.Builder().build(); @@ -147,10 +155,10 @@ private String buildGitTag() { } } - private static String getGitBranchOrTag() { - String gitBranchOrTag = System.getenv(GHACTIONS_HEAD_REF); + private String getGitBranchOrTag() { + String gitBranchOrTag = environment.get(GHACTIONS_HEAD_REF); if (gitBranchOrTag == null || gitBranchOrTag.isEmpty()) { - gitBranchOrTag = System.getenv(GHACTIONS_REF); + gitBranchOrTag = environment.get(GHACTIONS_REF); } return gitBranchOrTag; } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/JenkinsInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/JenkinsInfo.java index a4d65533428..bb3d56f81e3 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/JenkinsInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/JenkinsInfo.java @@ -9,6 +9,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import datadog.trace.util.Strings; import de.thetaphi.forbiddenapis.SuppressForbidden; import java.util.Arrays; @@ -37,34 +38,40 @@ class JenkinsInfo implements CIProviderInfo { public static final String JENKINS_NODE_NAME = "NODE_NAME"; public static final String JENKINS_NODE_LABELS = "NODE_LABELS"; + private final CiEnvironment environment; + + JenkinsInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( filterSensitiveInfo(buildGitRepositoryUrl()), buildGitBranch(), buildGitTag(), - new CommitInfo(System.getenv(JENKINS_GIT_COMMIT))); + new CommitInfo(environment.get(JENKINS_GIT_COMMIT))); } @Override public CIInfo buildCIInfo() { final String gitBranch = buildGitBranch(); - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(JENKINS_PROVIDER_NAME) - .ciPipelineId(System.getenv(JENKINS_PIPELINE_ID)) + .ciPipelineId(environment.get(JENKINS_PIPELINE_ID)) .ciPipelineName(buildCiPipelineName(gitBranch)) - .ciPipelineNumber(System.getenv(JENKINS_PIPELINE_NUMBER)) - .ciPipelineUrl(System.getenv(JENKINS_PIPELINE_URL)) - .ciWorkspace(expandTilde(System.getenv(JENKINS_WORKSPACE_PATH))) - .ciNodeName(System.getenv(JENKINS_NODE_NAME)) + .ciPipelineNumber(environment.get(JENKINS_PIPELINE_NUMBER)) + .ciPipelineUrl(environment.get(JENKINS_PIPELINE_URL)) + .ciWorkspace(expandTilde(environment.get(JENKINS_WORKSPACE_PATH))) + .ciNodeName(environment.get(JENKINS_NODE_NAME)) .ciNodeLabels(buildCiNodeLabels()) .ciEnvVars(JENKINS_DD_CUSTOM_TRACE_ID) .build(); } private String buildCiNodeLabels() { - String labels = System.getenv(JENKINS_NODE_LABELS); + String labels = environment.get(JENKINS_NODE_LABELS); if (labels == null || labels.isEmpty()) { return labels; } @@ -73,13 +80,13 @@ private String buildCiNodeLabels() { } private String buildGitRepositoryUrl() { - return System.getenv(JENKINS_GIT_REPOSITORY_URL) != null - ? System.getenv(JENKINS_GIT_REPOSITORY_URL) - : System.getenv(JENKINS_GIT_REPOSITORY_URL_ALT); + return environment.get(JENKINS_GIT_REPOSITORY_URL) != null + ? environment.get(JENKINS_GIT_REPOSITORY_URL) + : environment.get(JENKINS_GIT_REPOSITORY_URL_ALT); } private String buildGitBranch() { - final String gitBranchOrTag = System.getenv(JENKINS_GIT_BRANCH); + final String gitBranchOrTag = environment.get(JENKINS_GIT_BRANCH); if (!isTagReference(gitBranchOrTag)) { return normalizeBranch(gitBranchOrTag); } else { @@ -88,7 +95,7 @@ private String buildGitBranch() { } private String buildGitTag() { - final String gitBranchOrTag = System.getenv(JENKINS_GIT_BRANCH); + final String gitBranchOrTag = environment.get(JENKINS_GIT_BRANCH); if (isTagReference(gitBranchOrTag)) { return normalizeTag(gitBranchOrTag); } else { @@ -97,7 +104,7 @@ private String buildGitTag() { } private String buildCiPipelineName(final String branch) { - final String jobName = System.getenv(JENKINS_PIPELINE_NAME); + final String jobName = environment.get(JENKINS_PIPELINE_NAME); return filterJenkinsJobName(jobName, branch); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TeamcityInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TeamcityInfo.java index ed2a0f2de20..996576f134a 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TeamcityInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TeamcityInfo.java @@ -3,6 +3,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; public class TeamcityInfo implements CIProviderInfo { public static final String TEAMCITY = "TEAMCITY_VERSION"; @@ -10,6 +11,12 @@ public class TeamcityInfo implements CIProviderInfo { private static final String TEAMCITY_BUILDCONF_NAME = "TEAMCITY_BUILDCONF_NAME"; private static final String BUILD_URL = "BUILD_URL"; + private final CiEnvironment environment; + + TeamcityInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo(null, null, null, new CommitInfo(null)); @@ -17,10 +24,10 @@ public GitInfo buildCIGitInfo() { @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(TEAMCITY_PROVIDER_NAME) - .ciJobName(System.getenv(TEAMCITY_BUILDCONF_NAME)) - .ciJobUrl(System.getenv(BUILD_URL)) + .ciJobName(environment.get(TEAMCITY_BUILDCONF_NAME)) + .ciJobUrl(environment.get(BUILD_URL)) .build(); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TravisInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TravisInfo.java index 830f9056291..8bcad157624 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TravisInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TravisInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class TravisInfo implements CIProviderInfo { @@ -27,46 +28,51 @@ class TravisInfo implements CIProviderInfo { public static final String TRAVIS_GIT_TAG = "TRAVIS_TAG"; public static final String TRAVIS_GIT_COMMIT_MESSAGE = "TRAVIS_COMMIT_MESSAGE"; + private final CiEnvironment environment; + + TravisInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { - return new GitInfo( buildGitRepositoryUrl(), buildGitBranch(), - normalizeTag(System.getenv(TRAVIS_GIT_TAG)), + normalizeTag(environment.get(TRAVIS_GIT_TAG)), new CommitInfo( - System.getenv(TRAVIS_GIT_COMMIT), + environment.get(TRAVIS_GIT_COMMIT), PersonInfo.NOOP, PersonInfo.NOOP, - System.getenv(TRAVIS_GIT_COMMIT_MESSAGE))); + environment.get(TRAVIS_GIT_COMMIT_MESSAGE))); } @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(TRAVIS_PROVIDER_NAME) - .ciPipelineId(System.getenv(TRAVIS_PIPELINE_ID)) + .ciPipelineId(environment.get(TRAVIS_PIPELINE_ID)) .ciPipelineName(buildCiPipelineName()) - .ciPipelineNumber(System.getenv(TRAVIS_PIPELINE_NUMBER)) - .ciPipelineUrl(System.getenv(TRAVIS_PIPELINE_URL)) - .ciJobUrl(System.getenv(TRAVIS_JOB_URL)) - .ciWorkspace(expandTilde(System.getenv(TRAVIS_WORKSPACE_PATH))) + .ciPipelineNumber(environment.get(TRAVIS_PIPELINE_NUMBER)) + .ciPipelineUrl(environment.get(TRAVIS_PIPELINE_URL)) + .ciJobUrl(environment.get(TRAVIS_JOB_URL)) + .ciWorkspace(expandTilde(environment.get(TRAVIS_WORKSPACE_PATH))) .build(); } private String buildGitBranch() { - final String fromBranch = System.getenv(TRAVIS_GIT_PR_BRANCH); + final String fromBranch = environment.get(TRAVIS_GIT_PR_BRANCH); if (fromBranch != null && !fromBranch.isEmpty()) { return normalizeBranch(fromBranch); } else { - return normalizeBranch(System.getenv(TRAVIS_GIT_BRANCH)); + return normalizeBranch(environment.get(TRAVIS_GIT_BRANCH)); } } private String buildGitRepositoryUrl() { - String repoSlug = System.getenv(TRAVIS_PR_REPOSITORY_SLUG); + String repoSlug = environment.get(TRAVIS_PR_REPOSITORY_SLUG); if (repoSlug == null || repoSlug.isEmpty()) { - repoSlug = System.getenv(TRAVIS_REPOSITORY_SLUG); + repoSlug = environment.get(TRAVIS_REPOSITORY_SLUG); } if (repoSlug == null || repoSlug.isEmpty()) { @@ -76,9 +82,9 @@ private String buildGitRepositoryUrl() { } private String buildCiPipelineName() { - String repoSlug = System.getenv(TRAVIS_PR_REPOSITORY_SLUG); + String repoSlug = environment.get(TRAVIS_PR_REPOSITORY_SLUG); if (repoSlug == null || repoSlug.isEmpty()) { - repoSlug = System.getenv(TRAVIS_REPOSITORY_SLUG); + repoSlug = environment.get(TRAVIS_REPOSITORY_SLUG); } return repoSlug; } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/UnknownCIInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/UnknownCIInfo.java index 02dfed2bd4a..72ddbb4017c 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/UnknownCIInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/UnknownCIInfo.java @@ -4,6 +4,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import java.nio.file.Path; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,14 +29,12 @@ class UnknownCIInfo implements CIProviderInfo { public static final String UNKNOWN_PROVIDER_NAME = "unknown"; + private final CiEnvironment environment; private final String targetFolder; private final Path currentPath; - UnknownCIInfo(Path currentPath) { - this(".git", currentPath); - } - - UnknownCIInfo(String targetFolder, Path currentPath) { + UnknownCIInfo(CiEnvironment environment, String targetFolder, Path currentPath) { + this.environment = environment; this.targetFolder = targetFolder; this.currentPath = currentPath; } @@ -58,7 +57,7 @@ public CIInfo buildCIInfo() { LOGGER.debug("Could not get real path for workspace folder {}", workspace, e); } - return CIInfo.builder().ciWorkspace(workspace.toAbsolutePath().toString()).build(); + return CIInfo.builder(environment).ciWorkspace(workspace.toAbsolutePath().toString()).build(); } protected String getTargetFolder() { diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironment.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironment.java new file mode 100644 index 00000000000..f649701e382 --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironment.java @@ -0,0 +1,10 @@ +package datadog.trace.civisibility.ci.env; + +import java.util.Map; + +public interface CiEnvironment { + + String get(String name); + + Map get(); +} diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironmentImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironmentImpl.java new file mode 100644 index 00000000000..0030df98768 --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironmentImpl.java @@ -0,0 +1,22 @@ +package datadog.trace.civisibility.ci.env; + +import java.util.Map; + +public class CiEnvironmentImpl implements CiEnvironment { + + private final Map env; + + public CiEnvironmentImpl(Map env) { + this.env = env; + } + + @Override + public String get(String name) { + return env.get(name); + } + + @Override + public Map get() { + return env; + } +} diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CompositeCiEnvironment.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CompositeCiEnvironment.java new file mode 100644 index 00000000000..2a723606d76 --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CompositeCiEnvironment.java @@ -0,0 +1,35 @@ +package datadog.trace.civisibility.ci.env; + +import java.util.HashMap; +import java.util.Map; + +public class CompositeCiEnvironment implements CiEnvironment { + + private final CiEnvironment[] delegates; + + public CompositeCiEnvironment(CiEnvironment... delegates) { + this.delegates = delegates; + } + + @Override + public String get(String name) { + for (CiEnvironment delegate : delegates) { + String value = delegate.get(name); + if (value != null) { + return value; + } + } + return null; + } + + @Override + public Map get() { + Map combinedEnvironment = new HashMap<>(); + for (int i = delegates.length - 1; i >= 0; i--) { + // iterating over delegates in reverse order, + // since delegates with lower indices have higher priority + combinedEnvironment.putAll(delegates[i].get()); + } + return combinedEnvironment; + } +} diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/CIProviderGitInfoBuilder.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/CIProviderGitInfoBuilder.java index 7a138f2f10e..b4a6d6f0d30 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/CIProviderGitInfoBuilder.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/CIProviderGitInfoBuilder.java @@ -5,15 +5,25 @@ import datadog.trace.api.git.GitInfoBuilder; import datadog.trace.civisibility.ci.CIProviderInfo; import datadog.trace.civisibility.ci.CIProviderInfoFactory; +import datadog.trace.civisibility.ci.env.CiEnvironment; import java.nio.file.Path; import java.nio.file.Paths; import javax.annotation.Nullable; public class CIProviderGitInfoBuilder implements GitInfoBuilder { + + private final Config config; + private final CiEnvironment environment; + + public CIProviderGitInfoBuilder(Config config, CiEnvironment environment) { + this.config = config; + this.environment = environment; + } + @Override public GitInfo build(@Nullable String repositoryPath) { Path currentPath = repositoryPath != null ? Paths.get(repositoryPath) : null; - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get()); + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(config, environment); CIProviderInfo ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(currentPath); return ciProviderInfo.buildCIGitInfo(); } diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/CiVisibilityServicesTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/CiVisibilityServicesTest.groovy new file mode 100644 index 00000000000..8e7cbf71a5a --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/CiVisibilityServicesTest.groovy @@ -0,0 +1,33 @@ +package datadog.trace.civisibility + +import datadog.trace.agent.test.server.http.TestHttpServer +import datadog.trace.agent.test.utils.OkHttpUtils +import spock.lang.Specification + +import static datadog.trace.agent.test.server.http.TestHttpServer.httpServer + +class CiVisibilityServicesTest extends Specification { + + def "test get remote environment"() { + given: + def key = "the-key" + + TestHttpServer remoteEnvironmentServer = httpServer { + handlers { + prefix("/") { + if (request.getHeader(CiVisibilityServices.DD_ENV_VARS_PROVIDER_KEY_HEADER) == key) { + response.status(200).send(""" { "a": 1, "b": "2" } """) + } else { + response.status(404).send() + } + } + } + } + + expect: + CiVisibilityServices.getRemoteEnvironment(remoteEnvironmentServer.address.toString(), key, OkHttpUtils.client()) == ["a": "1", "b": "2"] + + cleanup: + remoteEnvironmentServer.stop() + } +} diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CIProviderInfoFactoryTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CIProviderInfoFactoryTest.groovy index 62d9ec6108b..08b21a8d318 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CIProviderInfoFactoryTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CIProviderInfoFactoryTest.groovy @@ -1,6 +1,7 @@ package datadog.trace.civisibility.ci import datadog.trace.api.Config +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl import org.junit.Rule import org.junit.contrib.java.lang.system.EnvironmentVariables import org.junit.contrib.java.lang.system.RestoreSystemProperties @@ -38,7 +39,7 @@ class CIProviderInfoFactoryTest extends Specification { environmentVariables.set(ciKeySelector, "true") when: - def ciProviderInfoFactory = new CIProviderInfoFactory(Config.get()) + def ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(Paths.get("").toAbsolutePath()) then: diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy index 616f7ea18db..e51a2224f3a 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy @@ -5,6 +5,7 @@ import datadog.trace.api.git.GitInfo import datadog.trace.api.git.GitInfoProvider import datadog.trace.api.git.UserSuppliedGitInfoBuilder import datadog.trace.bootstrap.instrumentation.api.Tags +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl import datadog.trace.civisibility.git.CILocalGitInfoBuilder import datadog.trace.civisibility.git.CIProviderGitInfoBuilder import datadog.trace.civisibility.git.tree.GitClient @@ -46,7 +47,7 @@ abstract class CITagsProviderTest extends Specification { } when: - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath()) def ciInfo = ciProviderInfo.buildCIInfo() def ciTagsProvider = ciTagsProvider() @@ -71,7 +72,7 @@ abstract class CITagsProviderTest extends Specification { environmentVariables.set(GitInfo.DD_GIT_COMMIT_SHA, "1234567890123456789012345678901234567890") when: - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath()) def ciInfo = ciProviderInfo.buildCIInfo() def ciTagsProvider = ciTagsProvider() @@ -90,7 +91,7 @@ abstract class CITagsProviderTest extends Specification { environmentVariables.set(GitInfo.DD_GIT_REPOSITORY_URL, "local supplied repo url") when: - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath()) def ciInfo = ciProviderInfo.buildCIInfo() def ciTagsProvider = ciTagsProvider() @@ -107,7 +108,7 @@ abstract class CITagsProviderTest extends Specification { } when: - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath()) def ciInfo = ciProviderInfo.buildCIInfo() def ciTagsProvider = ciTagsProvider() @@ -139,7 +140,7 @@ abstract class CITagsProviderTest extends Specification { then: if (isCi()) { - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath()) def ciInfo = ciProviderInfo.buildCIInfo() def tags = ciTagsProvider.getCiTags(ciInfo) @@ -173,7 +174,7 @@ abstract class CITagsProviderTest extends Specification { GitInfoProvider gitInfoProvider = new GitInfoProvider() gitInfoProvider.registerGitInfoBuilder(new UserSuppliedGitInfoBuilder()) - gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder()) + gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder(Config.get(), new CiEnvironmentImpl(System.getenv()))) gitInfoProvider.registerGitInfoBuilder(new CILocalGitInfoBuilder(gitClientFactory, GIT_FOLDER_FOR_TESTS)) return new CITagsProvider(gitInfoProvider) } diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy index 784e5e3d529..c54503cb0a7 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy @@ -1,5 +1,6 @@ package datadog.trace.civisibility.ci +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl import java.nio.file.Paths @@ -36,7 +37,7 @@ class GithubActionsInfoTest extends CITagsProviderTest { environmentVariables.set(GithubActionsInfo.GITHUB_EVENT_PATH, githubEventPath.toString()) when: - def cIInfo = new GithubActionsInfo().buildCIInfo() + def cIInfo = new GithubActionsInfo(new CiEnvironmentImpl(System.getenv())).buildCIInfo() then: cIInfo.getAdditionalTags() == [ diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/UnknownCIInfoTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/UnknownCIInfoTest.groovy index 333f554c8d4..77d1dda2f7b 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/UnknownCIInfoTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/UnknownCIInfoTest.groovy @@ -4,6 +4,7 @@ import datadog.trace.api.Config import datadog.trace.api.git.GitInfoProvider import datadog.trace.api.git.UserSuppliedGitInfoBuilder import datadog.trace.bootstrap.instrumentation.api.Tags +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl import datadog.trace.civisibility.git.CILocalGitInfoBuilder import datadog.trace.civisibility.git.CIProviderGitInfoBuilder import datadog.trace.civisibility.git.tree.GitClient @@ -44,7 +45,7 @@ class UnknownCIInfoTest extends CITagsProviderTest { ] when: - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(workspaceForTests) def ciInfo = ciProviderInfo.buildCIInfo() def ciTagsProvider = ciTagsProvider() @@ -61,9 +62,9 @@ class UnknownCIInfoTest extends CITagsProviderTest { GitInfoProvider gitInfoProvider = new GitInfoProvider() gitInfoProvider.registerGitInfoBuilder(new UserSuppliedGitInfoBuilder()) - gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder()) + gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder(Config.get(), new CiEnvironmentImpl(System.getenv()))) gitInfoProvider.registerGitInfoBuilder(new CILocalGitInfoBuilder(gitClientFactory, "this-target-folder-does-not-exist")) - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), "this-target-folder-does-not-exist") + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), "this-target-folder-does-not-exist", new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(workspaceForTests) def ciInfo = ciProviderInfo.buildCIInfo() diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CiEnvironmentImplTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CiEnvironmentImplTest.groovy new file mode 100644 index 00000000000..fa8f664cb7c --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CiEnvironmentImplTest.groovy @@ -0,0 +1,25 @@ +package datadog.trace.civisibility.ci.env + + +import spock.lang.Specification + +class CiEnvironmentImplTest extends Specification { + + def "test returns an environment variable"() { + setup: + def environmentVariables = ["MY_ENV_VAR": "MY_VALUE"] + def environment = new CiEnvironmentImpl(environmentVariables) + + expect: + environment.get("MY_ENV_VAR") == "MY_VALUE" + } + + def "test returns all environment variables"() { + setup: + def environmentVariables = ["MY_ENV_VAR": "MY_VALUE", "MY_OTHER_ENV_VAR": "MY_OTHER_VALUE"] + def environment = new CiEnvironmentImpl(environmentVariables) + + expect: + environment.get() == ["MY_ENV_VAR": "MY_VALUE", "MY_OTHER_ENV_VAR": "MY_OTHER_VALUE"] + } +} diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CompositeCiEnvironmentTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CompositeCiEnvironmentTest.groovy new file mode 100644 index 00000000000..1f28d0f5859 --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CompositeCiEnvironmentTest.groovy @@ -0,0 +1,41 @@ +package datadog.trace.civisibility.ci.env + + +import spock.lang.Specification + +class CompositeCiEnvironmentTest extends Specification { + + def "test uses delegate"() { + setup: + def environmentVariables = ["MY_ENV_VAR": "MY_VALUE", "MY_OTHER_ENV_VAR": "MY_OTHER_VALUE"] + def delegate = new CiEnvironmentImpl(environmentVariables) + def environment = new CompositeCiEnvironment(delegate) + + expect: + environment.get("MY_ENV_VAR") == "MY_VALUE" + environment.get() == ["MY_ENV_VAR": "MY_VALUE", "MY_OTHER_ENV_VAR": "MY_OTHER_VALUE"] + } + + def "test uses multiple delegates"() { + setup: + def delegateA = new CiEnvironmentImpl(["A": "1", "AA": "2"]) + def delegateB = new CiEnvironmentImpl(["B": "3", "BB": "4"]) + def environment = new CompositeCiEnvironment(delegateA, delegateB) + + expect: + environment.get("A") == "1" + environment.get("B") == "3" + environment.get() == ["A": "1", "AA": "2", "B": "3", "BB": "4"] + } + + def "test delegates priority"() { + setup: + def delegateA = new CiEnvironmentImpl(["A": "1", "B": "2"]) + def delegateB = new CiEnvironmentImpl(["B": "3", "C": "4"]) + def environment = new CompositeCiEnvironment(delegateA, delegateB) + + expect: + environment.get("B") == "2" + environment.get() == ["A": "1", "B": "2", "C": "4"] + } +} diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy index f56830ff3dc..b630e86fab9 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy @@ -395,7 +395,6 @@ class ConfigurationApiImplTest extends Specification { String apiKey = "api-key" String traceId = "a-trace-id" - long timeoutMillis = 1000 HttpRetryPolicy retryPolicy = Stub(HttpRetryPolicy) retryPolicy.shouldRetry(_) >> false @@ -403,7 +402,8 @@ class ConfigurationApiImplTest extends Specification { HttpRetryPolicy.Factory retryPolicyFactory = Stub(HttpRetryPolicy.Factory) retryPolicyFactory.create() >> retryPolicy - return new IntakeApi(intakeUrl, apiKey, traceId, timeoutMillis, retryPolicyFactory, responseCompression) + OkHttpClient client = OkHttpUtils.buildHttpClient(intakeUrl, REQUEST_TIMEOUT_MILLIS) + return new IntakeApi(intakeUrl, apiKey, traceId, retryPolicyFactory, client, responseCompression) } private static TracerEnvironment givenTracerEnvironment() { diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/CIProviderGitInfoBuilderTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/CIProviderGitInfoBuilderTest.groovy index 1ad5ad74617..1177e64183b 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/CIProviderGitInfoBuilderTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/CIProviderGitInfoBuilderTest.groovy @@ -1,6 +1,7 @@ package datadog.trace.civisibility.git - +import datadog.trace.api.Config +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl import org.junit.Rule import org.junit.contrib.java.lang.system.EnvironmentVariables import spock.lang.Specification @@ -19,7 +20,7 @@ class CIProviderGitInfoBuilderTest extends Specification { def "test builds empty git info in an unknown repository"() { setup: - def builder = new CIProviderGitInfoBuilder() + def builder = new CIProviderGitInfoBuilder(Config.get(), new CiEnvironmentImpl(System.getenv())) when: def gitInfo = builder.build(null) diff --git a/dd-trace-api/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java b/dd-trace-api/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java index 248bf228ab1..a929649e703 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java @@ -69,6 +69,10 @@ public final class CiVisibilityConfig { "civisibility.rum.flush.wait.millis"; public static final String CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER = "civisibility.auto.instrumentation.provider"; + public static final String CIVISIBILITY_REMOTE_ENV_VARS_PROVIDER_URL = + "civisibility.remote.env.vars.provider.url"; + public static final String CIVISIBILITY_REMOTE_ENV_VARS_PROVIDER_KEY = + "civisibility.remote.env.vars.provider.key"; /* COVERAGE SETTINGS */ public static final String CIVISIBILITY_CODE_COVERAGE_ENABLED = diff --git a/dd-trace-core/src/main/java/datadog/trace/common/writer/WriterFactory.java b/dd-trace-core/src/main/java/datadog/trace/common/writer/WriterFactory.java index b4af03b90e7..ef73a0b6fb7 100644 --- a/dd-trace-core/src/main/java/datadog/trace/common/writer/WriterFactory.java +++ b/dd-trace-core/src/main/java/datadog/trace/common/writer/WriterFactory.java @@ -188,6 +188,7 @@ private static RemoteApi createDDIntakeRemoteApi( } return DDIntakeApi.builder() .hostUrl(hostUrl) + .httpClient(commObjects.okHttpClient) .apiKey(config.getApiKey()) .trackType(trackType) .build(); diff --git a/dd-trace-core/src/main/java/datadog/trace/common/writer/ddintake/DDIntakeApi.java b/dd-trace-core/src/main/java/datadog/trace/common/writer/ddintake/DDIntakeApi.java index 165d1a951ab..7abad42d2f1 100644 --- a/dd-trace-core/src/main/java/datadog/trace/common/writer/ddintake/DDIntakeApi.java +++ b/dd-trace-core/src/main/java/datadog/trace/common/writer/ddintake/DDIntakeApi.java @@ -77,7 +77,7 @@ public DDIntakeApiBuilder hostUrl(final HttpUrl hostUrl) { return this; } - DDIntakeApiBuilder httpClient(final OkHttpClient httpClient) { + public DDIntakeApiBuilder httpClient(final OkHttpClient httpClient) { this.httpClient = httpClient; return this; } diff --git a/internal-api/src/main/java/datadog/trace/api/Config.java b/internal-api/src/main/java/datadog/trace/api/Config.java index c461a36806f..75b95385375 100644 --- a/internal-api/src/main/java/datadog/trace/api/Config.java +++ b/internal-api/src/main/java/datadog/trace/api/Config.java @@ -1,500 +1,22 @@ package datadog.trace.api; -import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_HOST; -import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_TIMEOUT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_WRITER_TYPE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ANALYTICS_SAMPLE_RATE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_API_SECURITY_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_API_SECURITY_REQUEST_SAMPLE_RATE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_MAX_STACK_TRACES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_MAX_STACK_TRACE_DEPTH; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_RASP_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_REPORTING_INBAND; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_STACK_TRACE_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_TRACE_RATE_LIMIT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_WAF_METRICS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_WAF_TIMEOUT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_AGENTLESS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_AUTO_CONFIGURATION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_VERSION; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_GIT_REMOTE_NAME; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_GIT_UNSHALLOW_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_GIT_UPLOAD_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_EXCLUDES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_VERSION; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_RESOURCE_FOLDER_NAMES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_SIGNAL_SERVER_HOST; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_SIGNAL_SERVER_PORT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_SOURCE_DATA_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CLIENT_IP_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CLOCK_SYNC_PERIOD; -import static datadog.trace.api.ConfigDefaults.DEFAULT_COUCHBASE_INTERNAL_SPANS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CWS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CWS_TLS_REFRESH; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DATA_JOBS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DATA_STREAMS_BUCKET_DURATION; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DATA_STREAMS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DB_CLIENT_HOST_SPLIT_BY_HOST; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DB_DBM_PROPAGATION_MODE_MODE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_CAPTURE_TIMEOUT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_CLASSFILE_DUMP_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_CODE_ORIGIN_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_DIAGNOSTICS_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_EXCEPTION_CAPTURE_INTERMEDIATE_SPANS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_EXCEPTION_CAPTURE_INTERVAL_SECONDS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_EXCEPTION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_EXCEPTION_MAX_CAPTURED_FRAMES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_EXCEPTION_ONLY_LOCAL_ROOT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_INSTRUMENT_THE_WORLD; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_MAX_EXCEPTION_PER_SECOND; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_MAX_PAYLOAD_SIZE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_METRICS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_POLL_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_SYMBOL_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_SYMBOL_FLUSH_THRESHOLD; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_SYMBOL_FORCE_UPLOAD; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_UPLOAD_BATCH_SIZE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_UPLOAD_FLUSH_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_UPLOAD_TIMEOUT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_VERIFY_BYTECODE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DOGSTATSD_START_DELAY; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ELASTICSEARCH_BODY_AND_PARAMS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ELASTICSEARCH_BODY_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ELASTICSEARCH_PARAMS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_GRPC_CLIENT_ERROR_STATUSES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_GRPC_SERVER_ERROR_STATUSES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HEALTH_METRICS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_CLIENT_ERROR_STATUSES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_CLIENT_SPLIT_BY_DOMAIN; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_CLIENT_TAG_QUERY_STRING; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_SERVER_ERROR_STATUSES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_SERVER_ROUTE_BASED_NAMING; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_SERVER_TAG_QUERY_STRING; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_ANONYMOUS_CLASSES_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_DEBUG_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_HARDCODED_SECRET_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_REDACTION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_REDACTION_NAME_PATTERN; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_REDACTION_VALUE_PATTERN; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_STACKTRACE_LEAK_SUPPRESS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_TRUNCATION_MAX_VALUE_LENGTH; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_WEAK_CIPHER_ALGORITHMS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_WEAK_HASH_ALGORITHMS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_JMX_FETCH_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_LOGS_INJECTION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PARTIAL_FLUSH_MIN_SPANS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PERF_METRICS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PRIORITY_SAMPLING_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PRIORITY_SAMPLING_FORCE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PROPAGATION_STYLE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_MAX_EXTRA_SERVICES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_MAX_PAYLOAD_SIZE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_POLL_INTERVAL_SECONDS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_TARGETS_KEY; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_TARGETS_KEY_ID; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SCOPE_DEPTH_LIMIT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SCOPE_ITERATION_KEEP_ALIVE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SECURE_RANDOM; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SERVICE_NAME; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SITE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_STARTUP_LOGS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_DEPENDENCY_RESOLUTION_QUEUE_SIZE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_HEARTBEAT_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_LOG_COLLECTION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_METRICS_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_128_BIT_TRACEID_GENERATION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_AGENT_PORT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_AGENT_V05_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ANALYTICS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_LONG_RUNNING_INITIAL_FLUSH_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_PROPAGATION_EXTRACT_FIRST; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_PROPAGATION_STYLE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_RATE_LIMIT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_REPORT_HOSTNAME; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_RESOLVER_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_X_DATADOG_TAGS_MAX_LENGTH; -import static datadog.trace.api.ConfigDefaults.DEFAULT_WRITER_BAGGAGE_INJECT; -import static datadog.trace.api.DDTags.APM_ENABLED; -import static datadog.trace.api.DDTags.HOST_TAG; -import static datadog.trace.api.DDTags.INTERNAL_HOST_NAME; -import static datadog.trace.api.DDTags.LANGUAGE_TAG_KEY; -import static datadog.trace.api.DDTags.LANGUAGE_TAG_VALUE; -import static datadog.trace.api.DDTags.PID_TAG; +import static datadog.trace.api.ConfigDefaults.*; +import static datadog.trace.api.DDTags.*; import static datadog.trace.api.DDTags.PROFILING_ENABLED; -import static datadog.trace.api.DDTags.RUNTIME_ID_TAG; -import static datadog.trace.api.DDTags.RUNTIME_VERSION_TAG; -import static datadog.trace.api.DDTags.SCHEMA_VERSION_TAG_KEY; -import static datadog.trace.api.DDTags.SERVICE; -import static datadog.trace.api.DDTags.SERVICE_TAG; -import static datadog.trace.api.config.AppSecConfig.API_SECURITY_ENABLED; -import static datadog.trace.api.config.AppSecConfig.API_SECURITY_ENABLED_EXPERIMENTAL; -import static datadog.trace.api.config.AppSecConfig.API_SECURITY_REQUEST_SAMPLE_RATE; -import static datadog.trace.api.config.AppSecConfig.APPSEC_AUTOMATED_USER_EVENTS_TRACKING; -import static datadog.trace.api.config.AppSecConfig.APPSEC_AUTO_USER_INSTRUMENTATION_MODE; -import static datadog.trace.api.config.AppSecConfig.APPSEC_HTTP_BLOCKED_TEMPLATE_HTML; -import static datadog.trace.api.config.AppSecConfig.APPSEC_HTTP_BLOCKED_TEMPLATE_JSON; -import static datadog.trace.api.config.AppSecConfig.APPSEC_IP_ADDR_HEADER; -import static datadog.trace.api.config.AppSecConfig.APPSEC_MAX_STACK_TRACES; -import static datadog.trace.api.config.AppSecConfig.APPSEC_MAX_STACK_TRACE_DEPTH; -import static datadog.trace.api.config.AppSecConfig.APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP; -import static datadog.trace.api.config.AppSecConfig.APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP; -import static datadog.trace.api.config.AppSecConfig.APPSEC_RASP_ENABLED; -import static datadog.trace.api.config.AppSecConfig.APPSEC_REPORTING_INBAND; -import static datadog.trace.api.config.AppSecConfig.APPSEC_REPORT_TIMEOUT_SEC; -import static datadog.trace.api.config.AppSecConfig.APPSEC_RULES_FILE; -import static datadog.trace.api.config.AppSecConfig.APPSEC_SCA_ENABLED; -import static datadog.trace.api.config.AppSecConfig.APPSEC_STACK_TRACE_ENABLED; -import static datadog.trace.api.config.AppSecConfig.APPSEC_STANDALONE_ENABLED; -import static datadog.trace.api.config.AppSecConfig.APPSEC_TRACE_RATE_LIMIT; -import static datadog.trace.api.config.AppSecConfig.APPSEC_WAF_METRICS; -import static datadog.trace.api.config.AppSecConfig.APPSEC_WAF_TIMEOUT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ADDITIONAL_CHILD_PROCESS_JVM_ARGS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENTLESS_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENTLESS_URL; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENT_JAR_URI; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AUTO_CONFIGURATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CIPROVIDER_INTEGRATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_EXCLUDES; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_INCLUDES; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_LINES_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_REPORT_DUMP_DIR; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_ROOT_PACKAGES_LIMIT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_COMPILER_PLUGIN_VERSION; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_DEBUG_PORT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_EARLY_FLAKE_DETECTION_LOWER_LIMIT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_EXECUTION_SETTINGS_CACHE_SIZE; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_COUNT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_ONLY_KNOWN_FLAKES; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_REMOTE_NAME; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UNSHALLOW_DEFER; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UNSHALLOW_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UPLOAD_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GRADLE_SOURCE_SETS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_INJECTED_TRACER_VERSION; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ITR_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JACOCO_PLUGIN_VERSION; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JVM_INFO_CACHE_SIZE; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_ID; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_NAME; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_REPO_INDEX_SHARING_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_RESOURCE_FOLDER_NAMES; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SESSION_ID; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_CLIENT_TIMEOUT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_HOST; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_PORT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SOURCE_DATA_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TELEMETRY_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TEST_COMMAND; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TEST_SKIPPING_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TOTAL_FLAKY_RETRY_COUNT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TRACE_SANITATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.TEST_SESSION_NAME; -import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_AGENTLESS; -import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_AGENTLESS_DEFAULT; -import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_TAGS; +import static datadog.trace.api.config.AppSecConfig.*; +import static datadog.trace.api.config.CiVisibilityConfig.*; +import static datadog.trace.api.config.CrashTrackingConfig.*; import static datadog.trace.api.config.CwsConfig.CWS_ENABLED; import static datadog.trace.api.config.CwsConfig.CWS_TLS_REFRESH; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_CAPTURE_TIMEOUT; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_CLASSFILE_DUMP_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_CODE_ORIGIN_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_DIAGNOSTICS_INTERVAL; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_CAPTURE_INTERMEDIATE_SPANS_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_CAPTURE_INTERVAL_SECONDS; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_CAPTURE_MAX_FRAMES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_MAX_CAPTURED_FRAMES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_ONLY_LOCAL_ROOT; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCLUDE_FILES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_INSTRUMENT_THE_WORLD; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_MAX_EXCEPTION_PER_SECOND; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_MAX_PAYLOAD_SIZE; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_METRICS_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_POLL_INTERVAL; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_PROBE_FILE_LOCATION; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTED_IDENTIFIERS; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTED_TYPES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTION_EXCLUDED_IDENTIFIERS; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_FLUSH_THRESHOLD; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_FORCE_UPLOAD; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_INCLUDES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_BATCH_SIZE; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_FLUSH_INTERVAL; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_TIMEOUT; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_VERIFY_BYTECODE; -import static datadog.trace.api.config.DebuggerConfig.EXCEPTION_REPLAY_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.THIRD_PARTY_EXCLUDES; -import static datadog.trace.api.config.DebuggerConfig.THIRD_PARTY_INCLUDES; -import static datadog.trace.api.config.GeneralConfig.API_KEY; -import static datadog.trace.api.config.GeneralConfig.API_KEY_FILE; -import static datadog.trace.api.config.GeneralConfig.APPLICATION_KEY; -import static datadog.trace.api.config.GeneralConfig.APPLICATION_KEY_FILE; -import static datadog.trace.api.config.GeneralConfig.AZURE_APP_SERVICES; -import static datadog.trace.api.config.GeneralConfig.DATA_JOBS_COMMAND_PATTERN; -import static datadog.trace.api.config.GeneralConfig.DATA_JOBS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.DATA_STREAMS_BUCKET_DURATION_SECONDS; -import static datadog.trace.api.config.GeneralConfig.DATA_STREAMS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_ARGS; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_HOST; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_NAMED_PIPE; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_PATH; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_PORT; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_START_DELAY; -import static datadog.trace.api.config.GeneralConfig.ENV; -import static datadog.trace.api.config.GeneralConfig.GLOBAL_TAGS; -import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_HOST; -import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_PORT; -import static datadog.trace.api.config.GeneralConfig.LOG_LEVEL; -import static datadog.trace.api.config.GeneralConfig.PERF_METRICS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.PRIMARY_TAG; -import static datadog.trace.api.config.GeneralConfig.RUNTIME_ID_ENABLED; -import static datadog.trace.api.config.GeneralConfig.RUNTIME_METRICS_ENABLED; +import static datadog.trace.api.config.DebuggerConfig.*; +import static datadog.trace.api.config.GeneralConfig.*; import static datadog.trace.api.config.GeneralConfig.SERVICE_NAME; -import static datadog.trace.api.config.GeneralConfig.SITE; -import static datadog.trace.api.config.GeneralConfig.STARTUP_LOGS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_QUEUE_SIZE; -import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_SOCKET_BUFFER; -import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_SOCKET_TIMEOUT; -import static datadog.trace.api.config.GeneralConfig.TAGS; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_DEPENDENCY_COLLECTION_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_DEPENDENCY_RESOLUTION_QUEUE_SIZE; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_HEARTBEAT_INTERVAL; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_LOG_COLLECTION_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_METRICS_INTERVAL; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_BUFFERING_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_IGNORED_RESOURCES; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_MAX_AGGREGATES; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_MAX_PENDING; -import static datadog.trace.api.config.GeneralConfig.TRACE_DEBUG; -import static datadog.trace.api.config.GeneralConfig.TRACE_TAGS; -import static datadog.trace.api.config.GeneralConfig.TRACE_TRIAGE; -import static datadog.trace.api.config.GeneralConfig.TRIAGE_REPORT_DIR; -import static datadog.trace.api.config.GeneralConfig.TRIAGE_REPORT_TRIGGER; -import static datadog.trace.api.config.GeneralConfig.VERSION; -import static datadog.trace.api.config.IastConfig.IAST_ANONYMOUS_CLASSES_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_CONTEXT_MODE; -import static datadog.trace.api.config.IastConfig.IAST_DEBUG_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_DETECTION_MODE; -import static datadog.trace.api.config.IastConfig.IAST_HARDCODED_SECRET_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_REDACTION_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_REDACTION_NAME_PATTERN; -import static datadog.trace.api.config.IastConfig.IAST_REDACTION_VALUE_PATTERN; -import static datadog.trace.api.config.IastConfig.IAST_SOURCE_MAPPING_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_SOURCE_MAPPING_MAX_SIZE; -import static datadog.trace.api.config.IastConfig.IAST_STACKTRACE_LEAK_SUPPRESS; -import static datadog.trace.api.config.IastConfig.IAST_TELEMETRY_VERBOSITY; -import static datadog.trace.api.config.IastConfig.IAST_TRUNCATION_MAX_VALUE_LENGTH; -import static datadog.trace.api.config.IastConfig.IAST_WEAK_CIPHER_ALGORITHMS; -import static datadog.trace.api.config.IastConfig.IAST_WEAK_HASH_ALGORITHMS; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CHECK_PERIOD; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CONFIG; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CONFIG_DIR; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_ENABLED; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_INITIAL_REFRESH_BEANS_PERIOD; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_METRICS_CONFIGS; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_REFRESH_BEANS_PERIOD; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_START_DELAY; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_HOST; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_PORT; -import static datadog.trace.api.config.JmxFetchConfig.JMX_TAGS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_VERY_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_VERY_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_BACKPRESSURE_SAMPLE_LIMIT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_BACKPRESSURE_SAMPLING_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_BACKPRESSURE_SAMPLING_ENABLED_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_RECORD_MESSAGE; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_RECORD_MESSAGE_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_SAMPLE_LIMIT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_SAMPLE_LIMIT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCLUDE_AGENT_THREADS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_HOST; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PASSWORD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PORT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PORT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_USERNAME; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_DELAY; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_DELAY_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_FORCE_FIRST; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_FORCE_FIRST_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_TAGS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_TEMPLATE_OVERRIDE_FILE; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_COMPRESSION; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_COMPRESSION_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_PERIOD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_PERIOD_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_SUMMARY_ON_413; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_SUMMARY_ON_413_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_TIMEOUT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_TIMEOUT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_URL; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIGURATION_ENABLED; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_ENABLED; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_MAX_EXTRA_SERVICES; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_MAX_PAYLOAD_SIZE; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_POLL_INTERVAL_SECONDS; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_TARGETS_KEY; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_TARGETS_KEY_ID; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_URL; -import static datadog.trace.api.config.TraceInstrumentationConfig.AXIS_PROMOTE_RESOURCE_NAME; -import static datadog.trace.api.config.TraceInstrumentationConfig.COUCHBASE_INTERNAL_SPANS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_HOST; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_DBM_PROPAGATION_MODE_MODE; -import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_AND_PARAMS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_PARAMS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.GOOGLE_PUBSUB_IGNORED_GRPC_METHODS; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_CLIENT_ERROR_STATUSES; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_IGNORED_INBOUND_METHODS; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_IGNORED_OUTBOUND_METHODS; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_SERVER_ERROR_STATUSES; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_SERVER_TRIM_PACKAGE_RESOURCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_TAG_HEADERS; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_TAG_QUERY_STRING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_DECODED_RESOURCE_PRESERVE_SPACES; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_QUERY_STRING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_RESOURCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_ROUTE_BASED_NAMING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_TAG_QUERY_STRING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HYSTRIX_MEASURED_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.HYSTRIX_TAGS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.IGNITE_CACHE_INCLUDE_KEYS; -import static datadog.trace.api.config.TraceInstrumentationConfig.INTEGRATION_SYNAPSE_LEGACY_OPERATION_NAME; -import static datadog.trace.api.config.TraceInstrumentationConfig.JAX_RS_EXCEPTION_AS_ERROR_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_PROPAGATION_DISABLED_QUEUES; -import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_PROPAGATION_DISABLED_TOPICS; -import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_UNACKNOWLEDGED_MAX_AGE; -import static datadog.trace.api.config.TraceInstrumentationConfig.KAFKA_CLIENT_BASE64_DECODING_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS; -import static datadog.trace.api.config.TraceInstrumentationConfig.LOGS_INJECTION; -import static datadog.trace.api.config.TraceInstrumentationConfig.LOGS_INJECTION_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.MESSAGE_BROKER_SPLIT_BY_DESTINATION; -import static datadog.trace.api.config.TraceInstrumentationConfig.OBFUSCATION_QUERY_STRING_REGEXP; -import static datadog.trace.api.config.TraceInstrumentationConfig.PLAY_REPORT_HTTP_STATUS; -import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_INCLUDE_ROUTINGKEY_IN_RESOURCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_PROPAGATION_DISABLED_EXCHANGES; -import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_PROPAGATION_DISABLED_QUEUES; -import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ASYNC_TIMEOUT_ERROR; -import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_PRINCIPAL_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ROOT_CONTEXT_SERVICE_NAME; -import static datadog.trace.api.config.TraceInstrumentationConfig.SPARK_APP_NAME_AS_SERVICE; -import static datadog.trace.api.config.TraceInstrumentationConfig.SPARK_TASK_HISTOGRAM_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME; -import static datadog.trace.api.config.TracerConfig.AGENT_HOST; -import static datadog.trace.api.config.TracerConfig.AGENT_NAMED_PIPE; -import static datadog.trace.api.config.TracerConfig.AGENT_PORT_LEGACY; -import static datadog.trace.api.config.TracerConfig.AGENT_TIMEOUT; -import static datadog.trace.api.config.TracerConfig.AGENT_UNIX_DOMAIN_SOCKET; -import static datadog.trace.api.config.TracerConfig.BAGGAGE_MAPPING; -import static datadog.trace.api.config.TracerConfig.CLIENT_IP_ENABLED; -import static datadog.trace.api.config.TracerConfig.CLOCK_SYNC_PERIOD; -import static datadog.trace.api.config.TracerConfig.ENABLE_TRACE_AGENT_V05; -import static datadog.trace.api.config.TracerConfig.HEADER_TAGS; -import static datadog.trace.api.config.TracerConfig.HTTP_CLIENT_ERROR_STATUSES; -import static datadog.trace.api.config.TracerConfig.HTTP_SERVER_ERROR_STATUSES; -import static datadog.trace.api.config.TracerConfig.ID_GENERATION_STRATEGY; -import static datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_ENABLED; -import static datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_MIN_SPANS; -import static datadog.trace.api.config.TracerConfig.PRIORITY_SAMPLING; -import static datadog.trace.api.config.TracerConfig.PRIORITY_SAMPLING_FORCE; -import static datadog.trace.api.config.TracerConfig.PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED; -import static datadog.trace.api.config.TracerConfig.PROPAGATION_STYLE_EXTRACT; -import static datadog.trace.api.config.TracerConfig.PROPAGATION_STYLE_INJECT; -import static datadog.trace.api.config.TracerConfig.PROXY_NO_PROXY; -import static datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS; -import static datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS_COMMA_ALLOWED; -import static datadog.trace.api.config.TracerConfig.RESPONSE_HEADER_TAGS; -import static datadog.trace.api.config.TracerConfig.SCOPE_DEPTH_LIMIT; -import static datadog.trace.api.config.TracerConfig.SCOPE_INHERIT_ASYNC_PROPAGATION; -import static datadog.trace.api.config.TracerConfig.SCOPE_ITERATION_KEEP_ALIVE; -import static datadog.trace.api.config.TracerConfig.SCOPE_STRICT_MODE; -import static datadog.trace.api.config.TracerConfig.SECURE_RANDOM; -import static datadog.trace.api.config.TracerConfig.SERVICE_MAPPING; -import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES; -import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES_FILE; -import static datadog.trace.api.config.TracerConfig.SPAN_TAGS; -import static datadog.trace.api.config.TracerConfig.SPLIT_BY_TAGS; -import static datadog.trace.api.config.TracerConfig.TRACE_128_BIT_TRACEID_GENERATION_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_ARGS; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_PATH; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_PORT; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_URL; -import static datadog.trace.api.config.TracerConfig.TRACE_ANALYTICS_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_HEADER; -import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_RESOLVER_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_GIT_METADATA_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING; -import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH; -import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_SERVER_PATH_RESOURCE_NAME_MAPPING; -import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_COMPONENT_OVERRIDES; -import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_DEFAULTS_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_MAPPING; -import static datadog.trace.api.config.TracerConfig.TRACE_POST_PROCESSING_TIMEOUT; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_EXTRACT_FIRST; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE_EXTRACT; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE_INJECT; -import static datadog.trace.api.config.TracerConfig.TRACE_RATE_LIMIT; -import static datadog.trace.api.config.TracerConfig.TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_REPORT_HOSTNAME; -import static datadog.trace.api.config.TracerConfig.TRACE_RESOLVER_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLE_RATE; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_OPERATION_RULES; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_RULES; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_SERVICE_RULES; -import static datadog.trace.api.config.TracerConfig.TRACE_SPAN_ATTRIBUTE_SCHEMA; -import static datadog.trace.api.config.TracerConfig.TRACE_STRICT_WRITES_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_X_DATADOG_TAGS_MAX_LENGTH; -import static datadog.trace.api.config.TracerConfig.WRITER_BAGGAGE_INJECT; -import static datadog.trace.api.config.TracerConfig.WRITER_TYPE; +import static datadog.trace.api.config.IastConfig.*; +import static datadog.trace.api.config.JmxFetchConfig.*; +import static datadog.trace.api.config.ProfilingConfig.*; +import static datadog.trace.api.config.RemoteConfigConfig.*; +import static datadog.trace.api.config.TraceInstrumentationConfig.*; +import static datadog.trace.api.config.TracerConfig.*; import static datadog.trace.api.iast.IastDetectionMode.DEFAULT; import static datadog.trace.api.telemetry.LogCollector.SEND_TELEMETRY; import static datadog.trace.util.CollectionUtils.tryMakeImmutableList; @@ -523,30 +45,13 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; -import java.net.InetAddress; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.UnknownHostException; +import java.net.*; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.SortedSet; -import java.util.UUID; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Supplier; @@ -853,6 +358,8 @@ public static String getHostName() { private final boolean ciVisibilityTelemetryEnabled; private final long ciVisibilityRumFlushWaitMillis; private final boolean ciVisibilityAutoInjected; + private final String ciVisibilityRemoteEnvVarsProviderUrl; + private final String ciVisibilityRemoteEnvVarsProviderKey; private final boolean remoteConfigEnabled; private final boolean remoteConfigIntegrityCheckEnabled; @@ -1928,6 +1435,10 @@ PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment()) configProvider.getLong(CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS, 500); ciVisibilityAutoInjected = Strings.isNotBlank(configProvider.getString(CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER)); + ciVisibilityRemoteEnvVarsProviderUrl = + configProvider.getString(CIVISIBILITY_REMOTE_ENV_VARS_PROVIDER_URL); + ciVisibilityRemoteEnvVarsProviderKey = + configProvider.getString(CIVISIBILITY_REMOTE_ENV_VARS_PROVIDER_KEY); remoteConfigEnabled = configProvider.getBoolean( @@ -3291,6 +2802,14 @@ public boolean isCiVisibilityAutoInjected() { return ciVisibilityAutoInjected; } + public String getCiVisibilityRemoteEnvVarsProviderUrl() { + return ciVisibilityRemoteEnvVarsProviderUrl; + } + + public String getCiVisibilityRemoteEnvVarsProviderKey() { + return ciVisibilityRemoteEnvVarsProviderKey; + } + public String getAppSecRulesFile() { return appSecRulesFile; } From e46eaa259035b5d05dc0430a16bfe441207415d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20=C3=81lvarez=20=C3=81lvarez?= Date: Sun, 29 Sep 2024 17:13:19 +0200 Subject: [PATCH 16/18] Fix stack overflow in spock making junit ignore test failures (#7674) Fix stack overflow on TooManyInvocationsError --- .../agent/tooling/InstrumenterModule.java | 11 +++- .../lang/StringBuilderCallSiteTest.groovy | 2 +- .../owasp/esapi/EncoderCallSiteTest.groovy | 2 +- ...portValueInstrumentationForkedTest.groovy} | 8 +-- .../datadog/trace/agent/test/SpockRunner.java | 55 +++++++++++++++++++ ...TooManyInvocationsErrorListenerTest.groovy | 38 +++++++++++++ .../datadog/trace/api/InstrumenterConfig.java | 8 +++ 7 files changed, 115 insertions(+), 9 deletions(-) rename dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/{ErrorReportValueInstrumentationTest.groovy => ErrorReportValueInstrumentationForkedTest.groovy} (80%) create mode 100644 dd-java-agent/testing/src/test/groovy/TooManyInvocationsErrorListenerTest.groovy diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/InstrumenterModule.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/InstrumenterModule.java index f1afd39e2f7..253eacc8331 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/InstrumenterModule.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/InstrumenterModule.java @@ -249,9 +249,14 @@ public List typeInstrumentations() { @Override public boolean isApplicable(Set enabledSystems) { - return enabledSystems.contains(TargetSystem.IAST) - || (isOptOutEnabled() - && InstrumenterConfig.get().getAppSecActivation() == ProductActivation.FULLY_ENABLED); + if (enabledSystems.contains(TargetSystem.IAST)) { + return true; + } + final InstrumenterConfig cfg = InstrumenterConfig.get(); + if (!isOptOutEnabled() || cfg.isIastFullyDisabled()) { + return false; + } + return cfg.getAppSecActivation() == ProductActivation.FULLY_ENABLED; } /** diff --git a/dd-java-agent/instrumentation/java-lang/src/test/groovy/datadog/trace/instrumentation/java/lang/StringBuilderCallSiteTest.groovy b/dd-java-agent/instrumentation/java-lang/src/test/groovy/datadog/trace/instrumentation/java/lang/StringBuilderCallSiteTest.groovy index f8a25369ebb..109262fab2f 100644 --- a/dd-java-agent/instrumentation/java-lang/src/test/groovy/datadog/trace/instrumentation/java/lang/StringBuilderCallSiteTest.groovy +++ b/dd-java-agent/instrumentation/java-lang/src/test/groovy/datadog/trace/instrumentation/java/lang/StringBuilderCallSiteTest.groovy @@ -57,7 +57,7 @@ class StringBuilderCallSiteTest extends AgentTestRunner { if (param.class == String) { 1 * iastModule.onStringBuilderAppend(target, (String) param) } else { - 1 * iastModule.onStringBuilderAppend(target, param.toString()) + 1 * iastModule.onStringBuilderAppend(target, { it -> it.toString() == param.toString() } ) } _ * TEST_PROFILING_CONTEXT_INTEGRATION._ 0 * _ diff --git a/dd-java-agent/instrumentation/owasp-esapi-2/src/test/groovy/datadog/trace/instrumentation/owasp/esapi/EncoderCallSiteTest.groovy b/dd-java-agent/instrumentation/owasp-esapi-2/src/test/groovy/datadog/trace/instrumentation/owasp/esapi/EncoderCallSiteTest.groovy index 800b7653a77..c90ad8e96bc 100644 --- a/dd-java-agent/instrumentation/owasp-esapi-2/src/test/groovy/datadog/trace/instrumentation/owasp/esapi/EncoderCallSiteTest.groovy +++ b/dd-java-agent/instrumentation/owasp-esapi-2/src/test/groovy/datadog/trace/instrumentation/owasp/esapi/EncoderCallSiteTest.groovy @@ -25,7 +25,7 @@ class EncoderCallSiteTest extends AgentTestRunner { testSuite.&"$method".call(args) then: - 1 * module.taintObjectIfTainted(_, _, false, mark) + 1 * module.taintStringIfTainted(_, _, false, mark) 0 * module._ where: diff --git a/dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationTest.groovy b/dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationForkedTest.groovy similarity index 80% rename from dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationTest.groovy rename to dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationForkedTest.groovy index 3cc5ec706c8..9d176479d73 100644 --- a/dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationForkedTest.groovy @@ -7,7 +7,7 @@ import org.apache.catalina.connector.Request import org.apache.catalina.connector.Response import org.apache.catalina.valves.ErrorReportValve -class ErrorReportValueInstrumentationTest extends AgentTestRunner { +class ErrorReportValueInstrumentationForkedTest extends AgentTestRunner { void 'test vulnerability detection'() { given: @@ -37,7 +37,7 @@ class ErrorReportValueInstrumentationTest extends AgentTestRunner { } } -class AppSecErrorReportValueInstrumentationTest extends ErrorReportValueInstrumentationTest { +class AppSecErrorReportValueInstrumentationForkedTest extends ErrorReportValueInstrumentationForkedTest { @Override protected void configurePreAgent() { @@ -51,7 +51,7 @@ class AppSecErrorReportValueInstrumentationTest extends ErrorReportValueInstrume } } -class IastErrorReportValueInstrumentationTest extends ErrorReportValueInstrumentationTest { +class IastErrorReportValueInstrumentationForkedTest extends ErrorReportValueInstrumentationForkedTest { @Override protected void configurePreAgent() { @@ -65,7 +65,7 @@ class IastErrorReportValueInstrumentationTest extends ErrorReportValueInstrument } } -class IastDisabledErrorReportValueInstrumentationTest extends ErrorReportValueInstrumentationTest { +class IastDisabledErrorReportValueInstrumentationForkedTest extends ErrorReportValueInstrumentationForkedTest { @Override protected void configurePreAgent() { diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java index 2e1703aa4d5..bb2f9ab0b3c 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java @@ -9,13 +9,18 @@ import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.jar.JarFile; import net.bytebuddy.agent.ByteBuddyAgent; import net.bytebuddy.dynamic.ClassFileLocator; import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunListener; import org.junit.runner.notification.RunNotifier; +import org.spockframework.mock.IMockInvocation; +import org.spockframework.mock.TooManyInvocationsError; /** * Runs a spock test in an agent-friendly way. @@ -129,10 +134,13 @@ private static Class shadowTestClass(final Class clazz) { @Override public void run(final RunNotifier notifier) { final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + final RunListener listener = new TooManyInvocationsErrorListener(); try { Thread.currentThread().setContextClassLoader(customLoader); + notifier.addFirstListener(listener); super.run(notifier); } finally { + notifier.removeListener(listener); Thread.currentThread().setContextClassLoader(contextLoader); } } @@ -222,4 +230,51 @@ protected Class loadClass(final String name, final boolean resolve) } } } + + /** + * This class tries to fix {@link TooManyInvocationsError} exceptions when the assertion error is + * caught by a mock triggering a stack overflow while composing the failure message. + */ + @SuppressWarnings("ResultOfMethodCallIgnored") + @RunListener.ThreadSafe + private static class TooManyInvocationsErrorListener extends RunListener { + + @Override + public void testFailure(final Failure failure) throws Exception { + if (failure.getException() instanceof TooManyInvocationsError) { + final TooManyInvocationsError assertion = (TooManyInvocationsError) failure.getException(); + try { + // try to trigger an error (e.g. stack overflow) + assertion.getMessage(); + } catch (final Throwable e) { + fixTooManyInvocationsError(assertion); + } + } + } + + private void fixTooManyInvocationsError(final TooManyInvocationsError error) { + final List accepted = error.getAcceptedInvocations(); + for (final IMockInvocation invocation : accepted) { + try { + invocation.toString(); + } catch (final Throwable t) { + final List arguments = invocation.getArguments(); + for (int i = 0; i < arguments.size(); i++) { + final Object arg = arguments.get(i); + if (arg instanceof AssertionError) { + final AssertionError updatedAssertion = + new AssertionError( + "'" + + arg.getClass().getName() + + "' hidden due to '" + + t.getClass().getName() + + "'", + t); + invocation.getArguments().set(i, updatedAssertion); + } + } + } + } + } + } } diff --git a/dd-java-agent/testing/src/test/groovy/TooManyInvocationsErrorListenerTest.groovy b/dd-java-agent/testing/src/test/groovy/TooManyInvocationsErrorListenerTest.groovy new file mode 100644 index 00000000000..265a63e8fc0 --- /dev/null +++ b/dd-java-agent/testing/src/test/groovy/TooManyInvocationsErrorListenerTest.groovy @@ -0,0 +1,38 @@ +import datadog.trace.agent.test.AgentTestRunner +import datadog.trace.agent.test.SpockRunner +import org.junit.runner.Description +import org.junit.runner.notification.Failure +import org.spockframework.mock.IMockInteraction +import org.spockframework.mock.IMockMethod +import org.spockframework.mock.IMockObject +import org.spockframework.mock.IResponseGenerator +import org.spockframework.mock.TooManyInvocationsError +import org.spockframework.mock.runtime.MockInvocation + +class TooManyInvocationsErrorListenerTest extends AgentTestRunner { + + @SuppressWarnings('GroovyAccessibility') + void 'test that listener modifies failure'() { + setup: + final error = new TooManyInvocationsError(Stub(IMockInteraction), []) + error.acceptedInvocations.add(new MockInvocation(Stub(IMockObject), + Stub(IMockMethod), + [error], + Stub(IResponseGenerator))) + final failure = new Failure(new Description(TooManyInvocationsErrorListenerTest, 'test'), error) + + when: + failure.getMessage() + + then: + thrown(StackOverflowError) + + when: + final listener = new SpockRunner.TooManyInvocationsErrorListener() + listener.testFailure(failure) + failure.getMessage() + + then: + noExceptionThrown() + } +} diff --git a/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java b/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java index f0aa03e83f8..78152292a48 100644 --- a/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java +++ b/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java @@ -108,6 +108,7 @@ public class InstrumenterConfig { private final boolean ciVisibilityEnabled; private final ProductActivation appSecActivation; private final ProductActivation iastActivation; + private final boolean iastFullyDisabled; private final boolean usmEnabled; private final boolean telemetryEnabled; @@ -194,6 +195,8 @@ private InstrumenterConfig() { iastActivation = ProductActivation.fromString( configProvider.getStringNotEmpty(IAST_ENABLED, DEFAULT_IAST_ENABLED)); + final Boolean iastEnabled = configProvider.getBoolean(IAST_ENABLED); + iastFullyDisabled = iastEnabled != null && !iastEnabled; usmEnabled = configProvider.getBoolean(USM_ENABLED, DEFAULT_USM_ENABLED); telemetryEnabled = configProvider.getBoolean(TELEMETRY_ENABLED, DEFAULT_TELEMETRY_ENABLED); } else { @@ -201,6 +204,7 @@ private InstrumenterConfig() { ciVisibilityEnabled = false; appSecActivation = ProductActivation.FULLY_DISABLED; iastActivation = ProductActivation.FULLY_DISABLED; + iastFullyDisabled = true; telemetryEnabled = false; usmEnabled = false; } @@ -321,6 +325,10 @@ public ProductActivation getIastActivation() { return iastActivation; } + public boolean isIastFullyDisabled() { + return iastFullyDisabled; + } + public boolean isUsmEnabled() { return usmEnabled; } From 59ce38a456687303f1c94ef80c542f0d23b18a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20=C3=81lvarez=20=C3=81lvarez?= Date: Sun, 29 Sep 2024 18:31:53 +0200 Subject: [PATCH 17/18] Add support for user tracking in spring security (#7633) --- .../appsec/user/AppSecEventTrackerImpl.java | 9 + .../AppSecEventTrackerSpecification.groovy | 19 + .../spring-security-5/build.gradle | 40 +- .../spring-security-5/gradle.lockfile | 403 ++++++++++-------- .../AppSecDeferredContext.java | 22 + ...AuthenticationProviderInstrumentation.java | 19 +- .../SecurityContextHolderInstrumentation.java | 90 ++++ .../SpringSecurityUserEventDecorator.java | 19 + .../UserDetailsManagerInstrumentation.java | 17 +- ...rnameNotFoundExceptionInstrumentation.java | 11 +- .../AuthenticationProviderAdvice.java | 19 - .../UserDetailsManagerAdvice.java | 17 - .../UsernameNotFoundExceptionAdvice.java | 11 - .../springsecurity5/SecurityConfig.groovy | 33 +- .../SpringBootBasedTest.groovy | 40 +- .../springsecurity5/TestEndpoint.groovy | 1 + .../custom/CustomAuthenticationFilter.java | 6 +- .../src/test/resources/schema.sql | 30 -- .../spring-security-6/build.gradle | 32 ++ .../spring-security-6/gradle.lockfile | 272 ++++++++++++ .../springsecurity6/AppConfig.groovy | 11 + .../springsecurity6/SecurityConfig.groovy | 58 +++ .../SpringBootBasedTest.groovy | 291 +++++++++++++ .../springsecurity6/TestEndpoint.groovy | 50 +++ .../springsecurity6/UserController.groovy | 45 ++ .../custom/CustomAuthenticationFilter.java | 33 ++ .../custom/CustomAuthenticationProvider.java | 18 + .../custom/CustomAuthenticationToken.java | 24 ++ .../trace/api/appsec/AppSecEventTracker.java | 2 + settings.gradle | 1 + 30 files changed, 1326 insertions(+), 317 deletions(-) create mode 100644 dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AppSecDeferredContext.java create mode 100644 dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SecurityContextHolderInstrumentation.java rename dd-java-agent/instrumentation/spring-security-5/src/main/{java17 => java}/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java (91%) delete mode 100644 dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderAdvice.java delete mode 100644 dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerAdvice.java delete mode 100644 dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionAdvice.java delete mode 100644 dd-java-agent/instrumentation/spring-security-5/src/test/resources/schema.sql create mode 100644 dd-java-agent/instrumentation/spring-security-6/build.gradle create mode 100644 dd-java-agent/instrumentation/spring-security-6/gradle.lockfile create mode 100644 dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/AppConfig.groovy create mode 100644 dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SecurityConfig.groovy create mode 100644 dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SpringBootBasedTest.groovy create mode 100644 dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/TestEndpoint.groovy create mode 100644 dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/UserController.groovy create mode 100644 dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationFilter.java create mode 100644 dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationProvider.java create mode 100644 dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationToken.java diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/user/AppSecEventTrackerImpl.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/user/AppSecEventTrackerImpl.java index 039312c7c93..e7cf336fa11 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/user/AppSecEventTrackerImpl.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/user/AppSecEventTrackerImpl.java @@ -96,6 +96,15 @@ public void onLoginFailureEvent( } } + @Override + public void onUserEvent(UserIdCollectionMode mode, String userId) { + TraceSegment segment = beforeEvent(mode, userId); + if (segment == null) { + return; + } + onUserId(mode, segment, userId, EVENTS.userId()); + } + @Override public void onCustomEvent( final UserIdCollectionMode mode, final String eventName, final Map metadata) { diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy index 8ec0447c9e6..f38200fff1b 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy @@ -237,6 +237,25 @@ class AppSecEventTrackerSpecification extends DDSpecification { 'ident' | 'identification' | 'user doesn\'t exist' | USER_ID } + def "test onUserEvent (#mode)"() { + setup: + final collectionMode = UserIdCollectionMode.fromString(mode, null) + + when: + tracker.onUserEvent(collectionMode, USER_ID) + + then: + 1 * traceSegment.getTagTop('_dd.appsec.user.collection_mode') >> null + 1 * userCallback.apply(_ as RequestContext, collectionMode, expectedUserId) >> NoopFlow.INSTANCE + 0 * _ + + where: + mode | modeTag | expectedUserId + 'anon' | 'anonymization' | ANONYMIZED_USER_ID + 'ident' | 'identification' | USER_ID + } + + def "test onUserNotFound (#mode)"() { setup: final collectionMode = UserIdCollectionMode.fromString(mode, null) diff --git a/dd-java-agent/instrumentation/spring-security-5/build.gradle b/dd-java-agent/instrumentation/spring-security-5/build.gradle index dd425272adc..51bc36007cf 100644 --- a/dd-java-agent/instrumentation/spring-security-5/build.gradle +++ b/dd-java-agent/instrumentation/spring-security-5/build.gradle @@ -3,39 +3,27 @@ muzzle { group = 'org.springframework.security' module = 'spring-security-core' versions = "[5.5.0,)" - // assertInverse = true } } -ext { - minJavaVersionForTests = JavaVersion.VERSION_17 -} - apply from: "$rootDir/gradle/java.gradle" +addTestSuiteForDir('latestDepTest', 'test') -[compileMain_java17Java, compileTestJava].each { - it.configure { - setJavaVersion(it, 17) - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } -} - -compileTestGroovy { - javaLauncher = getJavaLauncherFor(17) -} +final springSecurityVersion = '5.8.2' +final springBootVersion = '2.6.0' dependencies { - main_java17CompileOnly group: 'org.springframework.security', name: 'spring-security-core', version: '5.5.0' - compileOnly group: 'org.springframework.security', name: 'spring-security-core', version: '5.5.0' - - testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '3.0.0' - testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '3.0.0' - testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '3.0.0' - testImplementation 'org.springframework.boot:spring-boot-starter-jdbc:3.0.0' + compileOnly group: 'org.springframework.security', name: 'spring-security-core', version: springSecurityVersion testImplementation testFixtures(project(':dd-java-agent:appsec')) - testImplementation project(':dd-java-agent:instrumentation:tomcat-appsec-6') - testImplementation project(':dd-java-agent:instrumentation:tomcat-5.5') - testImplementation 'com.h2database:h2:2.1.212' + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springBootVersion + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: springBootVersion + + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.+' + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.+' + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '2.+' + + testRuntimeOnly project(':dd-java-agent:instrumentation:tomcat-appsec-6') + testRuntimeOnly project(':dd-java-agent:instrumentation:tomcat-5.5') } diff --git a/dd-java-agent/instrumentation/spring-security-5/gradle.lockfile b/dd-java-agent/instrumentation/spring-security-5/gradle.lockfile index 8dd9809b3b3..c4422c4872b 100644 --- a/dd-java-agent/instrumentation/spring-security-5/gradle.lockfile +++ b/dd-java-agent/instrumentation/spring-security-5/gradle.lockfile @@ -1,219 +1,258 @@ # This is a Gradle generated file for dependency locking. # Manual edits can break the build and are not advised. # This file is expected to be part of source control. -cafe.cryptography:curve25519-elisabeth:0.1.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -cafe.cryptography:ed25519-elisabeth:0.1.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -ch.qos.logback:logback-classic:1.4.5=testCompileClasspath,testRuntimeClasspath -ch.qos.logback:logback-core:1.4.5=testCompileClasspath,testRuntimeClasspath -com.beust:jcommander:1.78=testRuntimeClasspath -com.blogspot.mydailyjava:weak-lock-free:0.17=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq.okhttp3:okhttp:3.12.15=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq.okio:okio:1.17.6=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq:dd-javac-plugin-client:0.1.7=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq:java-dogstatsd-client:4.4.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.datadoghq:sketches-java:0.8.3=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-parameter-names:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson:jackson-bom:2.14.1=testCompileClasspath,testRuntimeClasspath -com.github.javaparser:javaparser-core:3.25.1=testCompileClasspath,testRuntimeClasspath -com.github.jnr:jffi:1.3.13=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-a64asm:1.0.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-constants:0.10.4=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-enxio:0.32.17=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-ffi:2.2.16=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-posix:3.1.19=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-unixsocket:0.38.22=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-x86asm:1.0.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.2.0=compileClasspath,testCompileClasspath,testRuntimeClasspath +cafe.cryptography:curve25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +cafe.cryptography:ed25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +ch.qos.logback:logback-classic:1.2.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +ch.qos.logback:logback-classic:1.2.7=testCompileClasspath,testRuntimeClasspath +ch.qos.logback:logback-core:1.2.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +ch.qos.logback:logback-core:1.2.7=testCompileClasspath,testRuntimeClasspath +com.beust:jcommander:1.78=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.blogspot.mydailyjava:weak-lock-free:0.17=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okhttp3:okhttp:3.12.15=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okio:okio:1.17.6=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:dd-javac-plugin-client:0.1.7=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:java-dogstatsd-client:4.4.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.datadoghq:sketches-java:0.8.3=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.github.javaparser:javaparser-core:3.25.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.jnr:jffi:1.3.13=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-a64asm:1.0.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-constants:0.10.4=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-enxio:0.32.17=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-ffi:2.2.16=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-posix:3.1.19=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-unixsocket:0.38.22=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-x86asm:1.0.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.spotbugs:spotbugs-annotations:4.2.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath com.github.spotbugs:spotbugs-annotations:4.7.3=spotbugs com.github.spotbugs:spotbugs:4.7.3=spotbugs -com.github.stefanbirkner:system-rules:1.19.0=testCompileClasspath,testRuntimeClasspath -com.google.auto.service:auto-service-annotations:1.0-rc7=annotationProcessor,compileClasspath,testAnnotationProcessor,testCompileClasspath -com.google.auto.service:auto-service:1.0-rc7=annotationProcessor,testAnnotationProcessor -com.google.auto:auto-common:0.10=annotationProcessor,testAnnotationProcessor -com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +com.github.stefanbirkner:system-rules:1.19.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.auto.service:auto-service-annotations:1.0-rc7=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,testAnnotationProcessor,testCompileClasspath +com.google.auto.service:auto-service:1.0-rc7=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.auto:auto-common:0.10=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath com.google.code.gson:gson:2.9.1=spotbugs -com.google.errorprone:error_prone_annotations:2.2.0=annotationProcessor,testAnnotationProcessor -com.google.guava:failureaccess:1.0.1=annotationProcessor,testAnnotationProcessor -com.google.guava:guava:20.0=testCompileClasspath,testRuntimeClasspath -com.google.guava:guava:27.0.1-jre=annotationProcessor,testAnnotationProcessor -com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,testAnnotationProcessor -com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,testAnnotationProcessor -com.google.re2j:re2j:1.7=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.h2database:h2:2.1.212=testCompileClasspath,testRuntimeClasspath -com.jayway.jsonpath:json-path:2.7.0=testCompileClasspath,testRuntimeClasspath -com.squareup.moshi:moshi:1.11.0=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.squareup.okhttp3:logging-interceptor:3.12.12=testCompileClasspath,testRuntimeClasspath -com.squareup.okhttp3:okhttp:3.12.12=testCompileClasspath,testRuntimeClasspath -com.squareup.okio:okio:1.17.5=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.thoughtworks.qdox:qdox:1.12.1=testRuntimeClasspath -com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspath,testRuntimeClasspath -com.zaxxer:HikariCP:5.0.1=testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.2.0=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:failureaccess:1.0.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:guava:20.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:27.0.1-jre=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.re2j:re2j:1.7=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.jayway.jsonpath:json-path:2.6.0=testCompileClasspath,testRuntimeClasspath +com.jayway.jsonpath:json-path:2.7.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.squareup.moshi:moshi:1.11.0=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:logging-interceptor:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:okhttp:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okio:okio:1.17.5=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.thoughtworks.qdox:qdox:1.12.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.vaadin.external.google:android-json:0.0.20131108.vaadin1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath commons-codec:commons-codec:1.15=spotbugs -commons-fileupload:commons-fileupload:1.5=testCompileClasspath,testRuntimeClasspath -commons-io:commons-io:2.11.0=testCompileClasspath,testRuntimeClasspath +commons-fileupload:commons-fileupload:1.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-io:commons-io:2.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath de.thetaphi:forbiddenapis:3.1=compileClasspath -info.picocli:picocli:4.6.3=testRuntimeClasspath -io.micrometer:micrometer-commons:1.10.1=testCompileClasspath,testRuntimeClasspath -io.micrometer:micrometer-observation:1.10.1=testCompileClasspath,testRuntimeClasspath -io.sqreen:libsqreen:11.0.1=testRuntimeClasspath -jakarta.activation:jakarta.activation-api:2.1.0=testCompileClasspath,testRuntimeClasspath -jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath -jakarta.xml.bind:jakarta.xml.bind-api:4.0.0=testCompileClasspath,testRuntimeClasspath -javax.servlet:javax.servlet-api:3.1.0=testCompileClasspath,testRuntimeClasspath +info.picocli:picocli:4.6.3=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.sqreen:libsqreen:11.0.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +jakarta.activation:jakarta.activation-api:1.2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +jakarta.annotation:jakarta.annotation-api:1.3.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +jakarta.xml.bind:jakarta.xml.bind-api:2.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +javax.servlet:javax.servlet-api:3.1.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath jaxen:jaxen:1.2.0=spotbugs -jline:jline:2.14.6=testRuntimeClasspath -junit:junit-dep:4.11=testCompileClasspath,testRuntimeClasspath -junit:junit:4.13.2=testCompileClasspath,testRuntimeClasspath -net.bytebuddy:byte-buddy-agent:1.14.18=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -net.bytebuddy:byte-buddy:1.14.18=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -net.java.dev.jna:jna-platform:5.8.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -net.java.dev.jna:jna:5.8.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -net.jcip:jcip-annotations:1.0=compileClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath -net.minidev:accessors-smart:2.4.7=testCompileClasspath,testRuntimeClasspath -net.minidev:json-smart:2.4.7=testCompileClasspath,testRuntimeClasspath +jline:jline:2.14.6=latestDepTestRuntimeClasspath,testRuntimeClasspath +junit:junit-dep:4.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +junit:junit:4.13.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy-agent:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.java.dev.jna:jna-platform:5.8.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +net.java.dev.jna:jna:5.8.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +net.jcip:jcip-annotations:1.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +net.minidev:accessors-smart:2.4.7=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +net.minidev:json-smart:2.4.7=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:11.4=spotbugs -org.apache.ant:ant-antlr:1.10.12=testRuntimeClasspath +org.apache.ant:ant-antlr:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath org.apache.ant:ant-antlr:1.9.15=codenarc -org.apache.ant:ant-junit:1.10.12=testRuntimeClasspath +org.apache.ant:ant-junit:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath org.apache.ant:ant-junit:1.9.15=codenarc -org.apache.ant:ant-launcher:1.10.12=testRuntimeClasspath -org.apache.ant:ant:1.10.12=testCompileClasspath,testRuntimeClasspath +org.apache.ant:ant-launcher:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.apache.ant:ant:1.10.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.bcel:bcel:6.5.0=spotbugs org.apache.commons:commons-lang3:3.12.0=spotbugs org.apache.commons:commons-text:1.10.0=spotbugs org.apache.httpcomponents.client5:httpclient5:5.1.3=spotbugs org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=spotbugs org.apache.httpcomponents.core5:httpcore5:5.1.3=spotbugs -org.apache.logging.log4j:log4j-api:2.19.0=spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-api:2.14.1=testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-api:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.logging.log4j:log4j-api:2.19.0=spotbugs org.apache.logging.log4j:log4j-core:2.19.0=spotbugs -org.apache.logging.log4j:log4j-to-slf4j:2.19.0=testCompileClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-core:10.1.1=testCompileClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-el:10.1.1=testCompileClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-websocket:10.1.1=testCompileClasspath,testRuntimeClasspath -org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath -org.assertj:assertj-core:3.23.1=testCompileClasspath,testRuntimeClasspath -org.checkerframework:checker-qual:2.5.2=annotationProcessor,testAnnotationProcessor -org.codehaus.groovy:groovy-all:3.0.17=testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-to-slf4j:2.14.1=testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-to-slf4j:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-core:9.0.55=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-core:9.0.83=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-el:9.0.55=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-el:9.0.83=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-websocket:9.0.55=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-websocket:9.0.83=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apiguardian:apiguardian-api:1.1.2=latestDepTestCompileClasspath,testCompileClasspath +org.assertj:assertj-core:3.21.0=testCompileClasspath,testRuntimeClasspath +org.assertj:assertj-core:3.22.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.checkerframework:checker-qual:2.5.2=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +org.codehaus.groovy:groovy-all:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-ant:2.5.14=codenarc -org.codehaus.groovy:groovy-ant:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-astbuilder:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-cli-picocli:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-console:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-datetime:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-docgenerator:3.0.17=testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-ant:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-astbuilder:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-cli-picocli:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-console:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-datetime:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-docgenerator:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-groovydoc:2.5.14=codenarc -org.codehaus.groovy:groovy-groovydoc:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-groovysh:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-jmx:3.0.17=testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-groovydoc:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-groovysh:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-jmx:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-json:2.5.14=codenarc -org.codehaus.groovy:groovy-json:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-jsr223:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-macro:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-nio:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-servlet:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-sql:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-swing:3.0.17=testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-json:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-jsr223:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-macro:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-nio:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-servlet:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-sql:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-swing:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-templates:2.5.14=codenarc -org.codehaus.groovy:groovy-templates:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-test-junit5:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-test:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-testng:3.0.17=testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-templates:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-test-junit5:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-test:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-testng:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-xml:2.5.14=codenarc -org.codehaus.groovy:groovy-xml:3.0.17=testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-xml:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy:2.5.14=codenarc -org.codehaus.groovy:groovy:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,testAnnotationProcessor +org.codehaus.groovy:groovy:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor org.codenarc:CodeNarc:2.2.0=codenarc org.dom4j:dom4j:2.1.3=spotbugs -org.eclipse.jetty:jetty-http:9.2.30.v20200428=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-io:9.2.30.v20200428=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-server:9.2.30.v20200428=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-util:9.2.30.v20200428=testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-http:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-io:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-server:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-util:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.gmetrics:GMetrics:1.1=codenarc -org.hamcrest:hamcrest-core:1.3=testCompileClasspath,testRuntimeClasspath -org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath -org.jctools:jctools-core:3.3.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-api:5.9.2=testCompileClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-engine:5.9.2=testRuntimeClasspath -org.junit.jupiter:junit-jupiter-params:5.9.2=testCompileClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter:5.9.2=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-commons:1.9.2=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-engine:1.9.2=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-launcher:1.9.2=testRuntimeClasspath -org.junit.platform:junit-platform-runner:1.9.2=testRuntimeClasspath -org.junit.platform:junit-platform-suite-api:1.9.2=testRuntimeClasspath -org.junit.platform:junit-platform-suite-commons:1.9.2=testRuntimeClasspath -org.junit:junit-bom:5.9.1=spotbugs -org.junit:junit-bom:5.9.2=testCompileClasspath,testRuntimeClasspath -org.mockito:mockito-core:4.8.1=testCompileClasspath,testRuntimeClasspath -org.mockito:mockito-junit-jupiter:4.8.1=testCompileClasspath,testRuntimeClasspath -org.objenesis:objenesis:3.3=testCompileClasspath,testRuntimeClasspath -org.opentest4j:opentest4j:1.2.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.hamcrest:hamcrest-core:1.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.hamcrest:hamcrest:2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jctools:jctools-core:3.3.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-api:5.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-engine:5.9.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-params:5.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter:5.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-commons:1.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-engine:1.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-launcher:1.9.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-runner:1.9.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-suite-api:1.9.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-suite-commons:1.9.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit:junit-bom:5.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-core:4.0.0=testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-core:4.5.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.mockito:mockito-junit-jupiter:4.0.0=testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-junit-jupiter:4.5.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.objenesis:objenesis:3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.opentest4j:opentest4j:1.2.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.ow2.asm:asm-analysis:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm-analysis:9.4=spotbugs -org.ow2.asm:asm-commons:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-commons:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm-commons:9.4=spotbugs -org.ow2.asm:asm-tree:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-tree:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm-tree:9.4=spotbugs -org.ow2.asm:asm-util:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-util:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm-util:9.4=spotbugs -org.ow2.asm:asm:9.1=testCompileClasspath -org.ow2.asm:asm:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm:9.1=latestDepTestCompileClasspath,testCompileClasspath +org.ow2.asm:asm:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm:9.4=spotbugs -org.skyscreamer:jsonassert:1.5.1=testCompileClasspath,testRuntimeClasspath -org.slf4j:jcl-over-slf4j:1.7.30=testCompileClasspath,testRuntimeClasspath -org.slf4j:jul-to-slf4j:2.0.4=testCompileClasspath,testRuntimeClasspath -org.slf4j:log4j-over-slf4j:1.7.30=testCompileClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:1.7.30=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath +org.skyscreamer:jsonassert:1.5.0=testCompileClasspath,testRuntimeClasspath +org.skyscreamer:jsonassert:1.5.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.slf4j:jcl-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:jul-to-slf4j:1.7.32=testCompileClasspath,testRuntimeClasspath +org.slf4j:jul-to-slf4j:1.7.36=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.slf4j:log4j-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:slf4j-api:1.7.30=compileClasspath,instrumentPluginClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath +org.slf4j:slf4j-api:1.7.32=testCompileClasspath,testRuntimeClasspath +org.slf4j:slf4j-api:1.7.36=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.slf4j:slf4j-api:2.0.0=spotbugs,spotbugsSlf4j -org.slf4j:slf4j-api:2.0.4=testCompileClasspath,testRuntimeClasspath org.slf4j:slf4j-simple:2.0.0=spotbugsSlf4j -org.spockframework:spock-core:2.2-groovy-3.0=testCompileClasspath,testRuntimeClasspath -org.spockframework:spock-junit4:2.2-groovy-3.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-autoconfigure:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-jdbc:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-json:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-logging:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-security:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-test:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-tomcat:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-web:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-test-autoconfigure:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-test:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.security:spring-security-config:6.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.security:spring-security-core:5.5.0=compileClasspath,main_java17CompileClasspath -org.springframework.security:spring-security-core:6.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.security:spring-security-crypto:5.5.0=compileClasspath,main_java17CompileClasspath -org.springframework.security:spring-security-crypto:6.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.security:spring-security-web:6.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-aop:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-aop:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-beans:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-beans:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-context:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-context:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-core:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-core:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-expression:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-expression:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-jcl:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-jcl:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-jdbc:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-test:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-tx:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-web:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-webmvc:6.0.2=testCompileClasspath,testRuntimeClasspath -org.testng:testng:7.5=testRuntimeClasspath -org.webjars:jquery:3.5.1=testRuntimeClasspath +org.spockframework:spock-core:2.2-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.spockframework:spock-junit4:2.2-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-autoconfigure:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-autoconfigure:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-json:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-json:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-logging:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-logging:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-security:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-security:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-test:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-test:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-tomcat:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-tomcat:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-web:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-web:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-test-autoconfigure:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-test-autoconfigure:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-test:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-test:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-config:5.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-config:5.7.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-core:5.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-core:5.7.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-core:5.8.2=compileClasspath +org.springframework.security:spring-security-crypto:5.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-crypto:5.7.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-crypto:5.8.2=compileClasspath +org.springframework.security:spring-security-web:5.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-web:5.7.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-aop:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-aop:5.3.25=compileClasspath +org.springframework:spring-aop:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-beans:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-beans:5.3.25=compileClasspath +org.springframework:spring-beans:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-context:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-context:5.3.25=compileClasspath +org.springframework:spring-context:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-core:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-core:5.3.25=compileClasspath +org.springframework:spring-core:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-expression:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-expression:5.3.25=compileClasspath +org.springframework:spring-expression:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-jcl:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-jcl:5.3.25=compileClasspath +org.springframework:spring-jcl:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-test:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-test:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-web:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-web:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-webmvc:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-webmvc:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.testng:testng:7.5=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.webjars:jquery:3.5.1=latestDepTestRuntimeClasspath,testRuntimeClasspath org.xmlresolver:xmlresolver:4.4.3=spotbugs -org.xmlunit:xmlunit-core:2.9.0=testCompileClasspath,testRuntimeClasspath -org.yaml:snakeyaml:1.33=testCompileClasspath,testRuntimeClasspath +org.xmlunit:xmlunit-core:2.8.3=testCompileClasspath,testRuntimeClasspath +org.xmlunit:xmlunit-core:2.9.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.yaml:snakeyaml:1.29=testCompileClasspath,testRuntimeClasspath +org.yaml:snakeyaml:1.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath xml-apis:xml-apis:1.4.01=spotbugs -empty=main_java17AnnotationProcessor,spotbugsPlugins +empty=spotbugsPlugins diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AppSecDeferredContext.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AppSecDeferredContext.java new file mode 100644 index 00000000000..bfdea675ef9 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AppSecDeferredContext.java @@ -0,0 +1,22 @@ +package datadog.trace.instrumentation.springsecurity5; + +import java.util.function.Supplier; +import org.springframework.security.core.context.SecurityContext; + +public class AppSecDeferredContext implements Supplier { + + private final Supplier delegate; + + public AppSecDeferredContext(final Supplier delegate) { + this.delegate = delegate; + } + + @Override + public SecurityContext get() { + SecurityContext context = delegate.get(); + if (context != null) { + SpringSecurityUserEventDecorator.DECORATE.onUser(context.getAuthentication()); + } + return context; + } +} diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderInstrumentation.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderInstrumentation.java index 2eedc42e624..77d1e3b4531 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderInstrumentation.java +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderInstrumentation.java @@ -10,8 +10,12 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.bootstrap.ActiveSubsystems; +import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; @AutoService(InstrumenterModule.class) public class AuthenticationProviderInstrumentation extends InstrumenterModule.AppSec @@ -46,6 +50,19 @@ public void methodAdvice(MethodTransformer transformer) { .and(takesArgument(0, named("org.springframework.security.core.Authentication"))) .and(returns(named("org.springframework.security.core.Authentication"))) .and(isPublic()), - packageName + ".AuthenticationProviderAdvice"); + getClass().getName() + "$AuthenticationProviderAdvice"); + } + + public static class AuthenticationProviderAdvice { + + @Advice.OnMethodExit(onThrowable = AuthenticationException.class, suppress = Throwable.class) + public static void onExit( + @Advice.Argument(value = 0, readOnly = false) Authentication authentication, + @Advice.Return final Authentication result, + @Advice.Thrown final AuthenticationException throwable) { + if (ActiveSubsystems.APPSEC_ACTIVE) { + SpringSecurityUserEventDecorator.DECORATE.onLogin(authentication, throwable, result); + } + } } } diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SecurityContextHolderInstrumentation.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SecurityContextHolderInstrumentation.java new file mode 100644 index 00000000000..31cc383c28a --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SecurityContextHolderInstrumentation.java @@ -0,0 +1,90 @@ +package datadog.trace.instrumentation.springsecurity5; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface; +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.isPublic; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import com.google.auto.service.AutoService; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.bootstrap.ActiveSubsystems; +import java.util.function.Supplier; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.springframework.security.core.context.SecurityContext; + +@AutoService(InstrumenterModule.class) +public class SecurityContextHolderInstrumentation extends InstrumenterModule.AppSec + implements Instrumenter.ForTypeHierarchy { + + public SecurityContextHolderInstrumentation() { + super("spring-security"); + } + + @Override + public String hierarchyMarkerType() { + return "org.springframework.security.core.context.SecurityContextHolderStrategy"; + } + + @Override + public ElementMatcher hierarchyMatcher() { + return implementsInterface(named(hierarchyMarkerType())); + } + + @Override + public String[] helperClassNames() { + return new String[] { + "datadog.trace.instrumentation.springsecurity5.SpringSecurityUserEventDecorator", + "datadog.trace.instrumentation.springsecurity5.AppSecDeferredContext" + }; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + isMethod() + .and(named("setContext")) + .and(takesArguments(1)) + .and( + takesArgument( + 0, named("org.springframework.security.core.context.SecurityContext"))) + .and(isPublic()), + getClass().getName() + "$SetSecurityContextAdvice"); + transformer.applyAdvice( + isMethod().and(named("setDeferredContext")).and(takesArguments(1)).and(isPublic()), + getClass().getName() + "$SetDeferredSecurityContextAdvice"); + } + + public static class SetSecurityContextAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter(@Advice.Argument(0) final SecurityContext context) { + if (context == null) { + return; + } + if (!ActiveSubsystems.APPSEC_ACTIVE) { + return; + } + SpringSecurityUserEventDecorator.DECORATE.onUser(context.getAuthentication()); + } + } + + public static class SetDeferredSecurityContextAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter( + @Advice.Argument(value = 0, readOnly = false) Supplier deferred) { + if (deferred == null) { + return; + } + if (!ActiveSubsystems.APPSEC_ACTIVE) { + return; + } + deferred = new AppSecDeferredContext(deferred); + } + } +} diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java similarity index 91% rename from dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java rename to dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java index 175470b5ea8..25c20548ec0 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java @@ -111,6 +111,25 @@ public void onLogin(Authentication authentication, Throwable throwable, Authenti } } + public void onUser(final Authentication authentication) { + if (authentication == null) { + return; + } + + final AppSecEventTracker tracker = AppSecEventTracker.getEventTracker(); + if (tracker == null) { + return; + } + + if (shouldSkipAuthentication(authentication)) { + return; + } + + UserIdCollectionMode mode = UserIdCollectionMode.get(); + String userId = authentication.getName(); + tracker.onUserEvent(mode, userId); + } + private static boolean shouldSkipAuthentication(final Authentication authentication) { if (authentication instanceof UsernamePasswordAuthenticationToken) { return false; diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerInstrumentation.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerInstrumentation.java index 1545edd41e0..cdbefae8760 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerInstrumentation.java +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerInstrumentation.java @@ -9,8 +9,11 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.bootstrap.ActiveSubsystems; +import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.springframework.security.core.userdetails.UserDetails; @AutoService(InstrumenterModule.class) public class UserDetailsManagerInstrumentation extends InstrumenterModule.AppSec @@ -46,6 +49,18 @@ public void methodAdvice(MethodTransformer transformer) { takesArgument( 0, named("org.springframework.security.core.userdetails.UserDetails"))) .and(isPublic()), - packageName + ".UserDetailsManagerAdvice"); + getClass().getName() + "$UserDetailsManagerAdvice"); + } + + public static class UserDetailsManagerAdvice { + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void onExit( + @Advice.Argument(value = 0, readOnly = false) UserDetails user, + @Advice.Thrown Throwable throwable) { + if (ActiveSubsystems.APPSEC_ACTIVE) { + SpringSecurityUserEventDecorator.DECORATE.onSignup(user, throwable); + } + } } } diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionInstrumentation.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionInstrumentation.java index a2bf67c779a..38cd80fc061 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionInstrumentation.java +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionInstrumentation.java @@ -9,6 +9,7 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; +import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -41,6 +42,14 @@ public String[] helperClassNames() { public void methodAdvice(MethodTransformer transformer) { transformer.applyAdvice( isConstructor().and(takesArgument(0, named("java.lang.String"))).and(isPublic()), - packageName + ".UsernameNotFoundExceptionAdvice"); + getClass().getName() + "$UsernameNotFoundExceptionAdvice"); + } + + public static class UsernameNotFoundExceptionAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter() { + SpringSecurityUserEventDecorator.DECORATE.onUserNotFound(); + } } } diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderAdvice.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderAdvice.java deleted file mode 100644 index 9afaa255ff0..00000000000 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderAdvice.java +++ /dev/null @@ -1,19 +0,0 @@ -package datadog.trace.instrumentation.springsecurity5; - -import datadog.trace.bootstrap.ActiveSubsystems; -import net.bytebuddy.asm.Advice; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; - -public class AuthenticationProviderAdvice { - - @Advice.OnMethodExit(onThrowable = AuthenticationException.class, suppress = Throwable.class) - public static void onExit( - @Advice.Argument(value = 0, readOnly = false) Authentication authentication, - @Advice.Return final Authentication result, - @Advice.Thrown final AuthenticationException throwable) { - if (ActiveSubsystems.APPSEC_ACTIVE) { - SpringSecurityUserEventDecorator.DECORATE.onLogin(authentication, throwable, result); - } - } -} diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerAdvice.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerAdvice.java deleted file mode 100644 index fe36885e437..00000000000 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerAdvice.java +++ /dev/null @@ -1,17 +0,0 @@ -package datadog.trace.instrumentation.springsecurity5; - -import datadog.trace.bootstrap.ActiveSubsystems; -import net.bytebuddy.asm.Advice; -import org.springframework.security.core.userdetails.UserDetails; - -public class UserDetailsManagerAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit( - @Advice.Argument(value = 0, readOnly = false) UserDetails user, - @Advice.Thrown Throwable throwable) { - if (ActiveSubsystems.APPSEC_ACTIVE) { - SpringSecurityUserEventDecorator.DECORATE.onSignup(user, throwable); - } - } -} diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionAdvice.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionAdvice.java deleted file mode 100644 index f3d24b75ea0..00000000000 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionAdvice.java +++ /dev/null @@ -1,11 +0,0 @@ -package datadog.trace.instrumentation.springsecurity5; - -import net.bytebuddy.asm.Advice; - -public class UsernameNotFoundExceptionAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter() { - SpringSecurityUserEventDecorator.DECORATE.onUserNotFound(); - } -} diff --git a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SecurityConfig.groovy b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SecurityConfig.groovy index e865ef18e5c..d5ce025ad32 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SecurityConfig.groovy +++ b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SecurityConfig.groovy @@ -2,20 +2,18 @@ package datadog.trace.instrumentation.springsecurity5 import custom.CustomAuthenticationFilter import custom.CustomAuthenticationProvider -import org.springframework.boot.jdbc.DataSourceBuilder import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer -import org.springframework.security.provisioning.JdbcUserDetailsManager +import org.springframework.security.core.userdetails.UserDetails +import org.springframework.security.provisioning.InMemoryUserDetailsManager import org.springframework.security.provisioning.UserDetailsManager import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter -import javax.sql.DataSource - import static datadog.trace.instrumentation.springsecurity5.SecurityConfig.CustomDsl.customDsl @Configuration @@ -26,28 +24,25 @@ class SecurityConfig { SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.apply(customDsl()) http - .authorizeHttpRequests( - (requests) -> requests - .requestMatchers("/", "/success", "/register", "/login", "/custom").permitAll() - .anyRequest().authenticated()) .csrf().disable() .formLogin((form) -> form.loginPage("/login").permitAll()) + .authorizeRequests() + .antMatchers("/", "/success", "/register", "/login", "/custom").permitAll() + .anyRequest().authenticated() return http.build() } - @Bean - DataSource getDataSource() { - DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create() - dataSourceBuilder.driverClassName("org.h2.Driver") - dataSourceBuilder.url("jdbc:h2:mem:authDB;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:schema.sql';") - dataSourceBuilder.username("SA") - dataSourceBuilder.password("") - return dataSourceBuilder.build() - } - @Bean UserDetailsManager userDetailsService() { - return new JdbcUserDetailsManager(dataSource) + return new InMemoryUserDetailsManager() { + @Override + void createUser(UserDetails user) { + if (user.username == 'cant_create_me') { + throw new IllegalArgumentException('cannot create user') + } + super.createUser(user) + } + } } static class CustomDsl extends AbstractHttpConfigurer { diff --git a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SpringBootBasedTest.groovy b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SpringBootBasedTest.groovy index a9262731ef3..96f9c21836c 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SpringBootBasedTest.groovy +++ b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SpringBootBasedTest.groovy @@ -15,10 +15,13 @@ import org.springframework.boot.web.servlet.context.ServletWebServerApplicationC import org.springframework.context.ConfigurableApplicationContext import spock.lang.Shared -import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.LOGIN +import static datadog.trace.agent.test.utils.OkHttpUtils.clientBuilder +import static datadog.trace.agent.test.utils.OkHttpUtils.cookieJar import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.CUSTOM +import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.LOGIN import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.REGISTER +import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.SUCCESS import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.UNKNOWN import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.NOT_FOUND @@ -213,7 +216,7 @@ class SpringBootBasedTest extends AppSecHttpServerTest - (1..length).collect { Character.valueOf((char) (random.nextInt(26) + (char)'a')) } - }.join() + void 'test user event'() { + setup: + def client = clientBuilder().cookieJar(cookieJar()).followRedirects(false).build() + def formBody = new FormBody.Builder() + .add("username", "admin") + .add("password", "admin") + .build() + + def loginRequest = request(LOGIN, "POST", formBody).build() + def loginResponse = client.newCall(loginRequest).execute() + assert loginResponse.code() == LOGIN.status + assert loginResponse.body().string() == LOGIN.body + TEST_WRITER.waitForTraces(1) + TEST_WRITER.start() // clear all traces + + when: + def request = request(SUCCESS, "GET", null).build() + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + def span = TEST_WRITER.flatten().first() as DDSpan + + then: + response.code() == SUCCESS.status + response.body().string() == SUCCESS.body + span.getResourceName().toString() == 'GET /success' + !span.getTags().isEmpty() + span.getTag("usr.id") == 'admin' + span.getTag("_dd.appsec.user.collection_mode") == 'ident' } } diff --git a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/TestEndpoint.groovy b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/TestEndpoint.groovy index bb6d223a7a7..3a558355471 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/TestEndpoint.groovy +++ b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/TestEndpoint.groovy @@ -6,6 +6,7 @@ enum TestEndpoint { NOT_FOUND("not-found", 404, "not found"), UNKNOWN("", 451, null), // This needs to have a valid status code CUSTOM("custom", 302, ""), + SUCCESS("success", 200, ""), private final String path private final String rawPath diff --git a/dd-java-agent/instrumentation/spring-security-5/src/test/java/custom/CustomAuthenticationFilter.java b/dd-java-agent/instrumentation/spring-security-5/src/test/java/custom/CustomAuthenticationFilter.java index b3ec62a572b..f63ccdc574d 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/test/java/custom/CustomAuthenticationFilter.java +++ b/dd-java-agent/instrumentation/spring-security-5/src/test/java/custom/CustomAuthenticationFilter.java @@ -1,9 +1,9 @@ package custom; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; diff --git a/dd-java-agent/instrumentation/spring-security-5/src/test/resources/schema.sql b/dd-java-agent/instrumentation/spring-security-5/src/test/resources/schema.sql deleted file mode 100644 index f7a9a7728ca..00000000000 --- a/dd-java-agent/instrumentation/spring-security-5/src/test/resources/schema.sql +++ /dev/null @@ -1,30 +0,0 @@ -create table IF NOT EXISTS users( - username varchar_ignorecase(50) not null primary key, - password varchar_ignorecase(500) not null, - enabled boolean not null -); - -create table IF NOT EXISTS authorities ( - username varchar_ignorecase(50) not null, - authority varchar_ignorecase(50) not null, - constraint fk_authorities_users foreign key(username) references users(username) -); -create unique index IF NOT EXISTS ix_auth_username on authorities (username,authority); - -create table IF NOT EXISTS groups ( - id bigint generated by default as identity(start with 0) primary key, - group_name varchar_ignorecase(50) not null -); - -create table IF NOT EXISTS group_authorities ( - group_id bigint not null, - authority varchar(50) not null, - constraint fk_group_authorities_group foreign key(group_id) references groups(id) -); - -create table IF NOT EXISTS group_members ( - id bigint generated by default as identity(start with 0) primary key, - username varchar(50) not null, - group_id bigint not null, - constraint fk_group_members_group foreign key(group_id) references groups(id) -); \ No newline at end of file diff --git a/dd-java-agent/instrumentation/spring-security-6/build.gradle b/dd-java-agent/instrumentation/spring-security-6/build.gradle new file mode 100644 index 00000000000..e746ed3f9c5 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/build.gradle @@ -0,0 +1,32 @@ +ext { + minJavaVersionForTests = JavaVersion.VERSION_17 +} + +apply from: "$rootDir/gradle/java.gradle" +addTestSuiteForDir('latestDepTest', 'test') + +final springBootVersion = '3.0.0' + +tasks.withType(AbstractCompile).configureEach { + setJavaVersion(it, 17) +} + +tasks.withType(GroovyCompile).configureEach { + javaLauncher = getJavaLauncherFor(17) +} + +dependencies { + + testImplementation testFixtures(project(':dd-java-agent:appsec')) + testImplementation project(':dd-java-agent:instrumentation:spring-security-5') + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springBootVersion + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: springBootVersion + + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '+' + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '+' + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '+' + + testRuntimeOnly project(':dd-java-agent:instrumentation:tomcat-appsec-6') + testRuntimeOnly project(':dd-java-agent:instrumentation:tomcat-5.5') +} diff --git a/dd-java-agent/instrumentation/spring-security-6/gradle.lockfile b/dd-java-agent/instrumentation/spring-security-6/gradle.lockfile new file mode 100644 index 00000000000..0f542362a9c --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/gradle.lockfile @@ -0,0 +1,272 @@ +# This is a Gradle generated file for dependency locking. +# Manual edits can break the build and are not advised. +# This file is expected to be part of source control. +cafe.cryptography:curve25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +cafe.cryptography:ed25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +ch.qos.logback:logback-classic:1.4.5=testCompileClasspath,testRuntimeClasspath +ch.qos.logback:logback-classic:1.5.7=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +ch.qos.logback:logback-core:1.4.5=testCompileClasspath,testRuntimeClasspath +ch.qos.logback:logback-core:1.5.7=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.beust:jcommander:1.78=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.blogspot.mydailyjava:weak-lock-free:0.17=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okhttp3:okhttp:3.12.15=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okio:okio:1.17.6=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:dd-javac-plugin-client:0.1.7=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:java-dogstatsd-client:4.4.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.datadoghq:sketches-java:0.8.3=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.github.javaparser:javaparser-core:3.25.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.jnr:jffi:1.3.13=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-a64asm:1.0.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-constants:0.10.4=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-enxio:0.32.17=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-ffi:2.2.16=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-posix:3.1.19=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-unixsocket:0.38.22=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-x86asm:1.0.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.spotbugs:spotbugs-annotations:4.2.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.spotbugs:spotbugs-annotations:4.7.3=spotbugs +com.github.spotbugs:spotbugs:4.7.3=spotbugs +com.github.stefanbirkner:system-rules:1.19.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.auto.service:auto-service-annotations:1.0-rc7=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,testAnnotationProcessor,testCompileClasspath +com.google.auto.service:auto-service:1.0-rc7=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.auto:auto-common:0.10=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.9.1=spotbugs +com.google.errorprone:error_prone_annotations:2.2.0=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:failureaccess:1.0.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:guava:20.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:27.0.1-jre=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.re2j:re2j:1.7=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.jayway.jsonpath:json-path:2.7.0=testCompileClasspath,testRuntimeClasspath +com.jayway.jsonpath:json-path:2.9.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.squareup.moshi:moshi:1.11.0=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:logging-interceptor:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:okhttp:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okio:okio:1.17.5=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.thoughtworks.qdox:qdox:1.12.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.vaadin.external.google:android-json:0.0.20131108.vaadin1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-codec:commons-codec:1.15=spotbugs +commons-fileupload:commons-fileupload:1.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-io:commons-io:2.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +de.thetaphi:forbiddenapis:3.1=compileClasspath +info.picocli:picocli:4.6.3=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.micrometer:micrometer-commons:1.10.1=testCompileClasspath,testRuntimeClasspath +io.micrometer:micrometer-commons:1.12.9=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.micrometer:micrometer-observation:1.10.1=testCompileClasspath,testRuntimeClasspath +io.micrometer:micrometer-observation:1.12.9=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.sqreen:libsqreen:11.0.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +jakarta.activation:jakarta.activation-api:2.1.0=testCompileClasspath,testRuntimeClasspath +jakarta.activation:jakarta.activation-api:2.1.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +jakarta.annotation:jakarta.annotation-api:2.1.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +jakarta.xml.bind:jakarta.xml.bind-api:4.0.0=testCompileClasspath,testRuntimeClasspath +jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +javax.servlet:javax.servlet-api:3.1.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +jaxen:jaxen:1.2.0=spotbugs +jline:jline:2.14.6=latestDepTestRuntimeClasspath,testRuntimeClasspath +junit:junit-dep:4.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +junit:junit:4.13.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy-agent:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.java.dev.jna:jna-platform:5.8.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +net.java.dev.jna:jna:5.8.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +net.jcip:jcip-annotations:1.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +net.minidev:accessors-smart:2.4.7=testCompileClasspath,testRuntimeClasspath +net.minidev:accessors-smart:2.5.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +net.minidev:json-smart:2.4.7=testCompileClasspath,testRuntimeClasspath +net.minidev:json-smart:2.5.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +net.sf.saxon:Saxon-HE:11.4=spotbugs +org.apache.ant:ant-antlr:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.apache.ant:ant-antlr:1.9.15=codenarc +org.apache.ant:ant-junit:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.apache.ant:ant-junit:1.9.15=codenarc +org.apache.ant:ant-launcher:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.apache.ant:ant:1.10.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.bcel:bcel:6.5.0=spotbugs +org.apache.commons:commons-lang3:3.12.0=spotbugs +org.apache.commons:commons-text:1.10.0=spotbugs +org.apache.httpcomponents.client5:httpclient5:5.1.3=spotbugs +org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=spotbugs +org.apache.httpcomponents.core5:httpcore5:5.1.3=spotbugs +org.apache.logging.log4j:log4j-api:2.19.0=spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-api:2.23.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.logging.log4j:log4j-core:2.19.0=spotbugs +org.apache.logging.log4j:log4j-to-slf4j:2.19.0=testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-to-slf4j:2.23.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-core:10.1.1=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-core:10.1.28=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-el:10.1.1=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-el:10.1.28=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-websocket:10.1.1=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-websocket:10.1.28=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apiguardian:apiguardian-api:1.1.2=latestDepTestCompileClasspath,testCompileClasspath +org.assertj:assertj-core:3.23.1=testCompileClasspath,testRuntimeClasspath +org.assertj:assertj-core:3.25.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.awaitility:awaitility:4.2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.checkerframework:checker-qual:2.5.2=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +org.codehaus.groovy:groovy-all:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-ant:2.5.14=codenarc +org.codehaus.groovy:groovy-ant:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-astbuilder:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-cli-picocli:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-console:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-datetime:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-docgenerator:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-groovydoc:2.5.14=codenarc +org.codehaus.groovy:groovy-groovydoc:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-groovysh:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-jmx:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-json:2.5.14=codenarc +org.codehaus.groovy:groovy-json:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-jsr223:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-macro:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-nio:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-servlet:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-sql:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-swing:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-templates:2.5.14=codenarc +org.codehaus.groovy:groovy-templates:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-test-junit5:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-test:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-testng:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-xml:2.5.14=codenarc +org.codehaus.groovy:groovy-xml:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy:2.5.14=codenarc +org.codehaus.groovy:groovy:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +org.codenarc:CodeNarc:2.2.0=codenarc +org.dom4j:dom4j:2.1.3=spotbugs +org.eclipse.jetty:jetty-http:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-io:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-server:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-util:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.gmetrics:GMetrics:1.1=codenarc +org.hamcrest:hamcrest-core:1.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.hamcrest:hamcrest:2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jctools:jctools-core:3.3.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-api:5.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.jupiter:junit-jupiter-api:5.9.2=testCompileClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-engine:5.10.3=latestDepTestRuntimeClasspath +org.junit.jupiter:junit-jupiter-engine:5.9.2=testRuntimeClasspath +org.junit.jupiter:junit-jupiter-params:5.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.jupiter:junit-jupiter-params:5.9.2=testCompileClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter:5.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.jupiter:junit-jupiter:5.9.2=testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-commons:1.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-commons:1.9.2=testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-engine:1.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-engine:1.9.2=testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-launcher:1.10.3=latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-launcher:1.9.2=testRuntimeClasspath +org.junit.platform:junit-platform-runner:1.10.3=latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-runner:1.9.2=testRuntimeClasspath +org.junit.platform:junit-platform-suite-api:1.10.3=latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-suite-api:1.9.2=testRuntimeClasspath +org.junit.platform:junit-platform-suite-commons:1.10.3=latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-suite-commons:1.9.2=testRuntimeClasspath +org.junit:junit-bom:5.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit:junit-bom:5.9.2=testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-core:4.8.1=testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-core:5.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.mockito:mockito-junit-jupiter:4.8.1=testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-junit-jupiter:5.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.objenesis:objenesis:3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.opentest4j:opentest4j:1.2.0=testCompileClasspath,testRuntimeClasspath +org.opentest4j:opentest4j:1.3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.ow2.asm:asm-analysis:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-analysis:9.4=spotbugs +org.ow2.asm:asm-commons:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-commons:9.4=spotbugs +org.ow2.asm:asm-tree:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-tree:9.4=spotbugs +org.ow2.asm:asm-util:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-util:9.4=spotbugs +org.ow2.asm:asm:9.1=testCompileClasspath +org.ow2.asm:asm:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm:9.4=spotbugs +org.ow2.asm:asm:9.6=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.skyscreamer:jsonassert:1.5.1=testCompileClasspath,testRuntimeClasspath +org.skyscreamer:jsonassert:1.5.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.slf4j:jcl-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:jul-to-slf4j:2.0.16=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.slf4j:jul-to-slf4j:2.0.4=testCompileClasspath,testRuntimeClasspath +org.slf4j:log4j-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:slf4j-api:1.7.30=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath +org.slf4j:slf4j-api:2.0.0=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.16=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.slf4j:slf4j-api:2.0.4=testCompileClasspath,testRuntimeClasspath +org.slf4j:slf4j-simple:2.0.0=spotbugsSlf4j +org.spockframework:spock-core:2.2-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.spockframework:spock-junit4:2.2-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-autoconfigure:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-autoconfigure:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-json:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-json:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-logging:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-logging:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-security:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-security:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-test:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-test:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-tomcat:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-tomcat:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-web:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-web:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-test-autoconfigure:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-test-autoconfigure:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-test:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-test:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-config:6.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-config:6.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-core:6.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-core:6.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-crypto:6.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-crypto:6.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-web:6.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-web:6.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-aop:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-aop:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-beans:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-beans:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-context:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-context:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-core:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-core:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-expression:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-expression:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-jcl:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-jcl:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-test:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-test:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-web:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-web:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-webmvc:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-webmvc:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.testng:testng:7.5=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.webjars:jquery:3.5.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.xmlresolver:xmlresolver:4.4.3=spotbugs +org.xmlunit:xmlunit-core:2.9.0=testCompileClasspath,testRuntimeClasspath +org.xmlunit:xmlunit-core:2.9.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.yaml:snakeyaml:1.33=testCompileClasspath,testRuntimeClasspath +org.yaml:snakeyaml:2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +xml-apis:xml-apis:1.4.01=spotbugs +empty=main_java17AnnotationProcessor,spotbugsPlugins diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/AppConfig.groovy b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/AppConfig.groovy new file mode 100644 index 00000000000..c33b48693a4 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/AppConfig.groovy @@ -0,0 +1,11 @@ +package datadog.trace.instrumentation.springsecurity6 + +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer + +// Component scan defeats the purpose of configuring with specific classes +@SpringBootApplication(exclude = [ErrorMvcAutoConfiguration]) +class AppConfig implements WebMvcConfigurer { + +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SecurityConfig.groovy b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SecurityConfig.groovy new file mode 100644 index 00000000000..623698699b7 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SecurityConfig.groovy @@ -0,0 +1,58 @@ +package datadog.trace.instrumentation.springsecurity6 + +import custom.CustomAuthenticationFilter +import custom.CustomAuthenticationProvider +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.security.authentication.AuthenticationManager +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer +import org.springframework.security.core.userdetails.UserDetails +import org.springframework.security.provisioning.InMemoryUserDetailsManager +import org.springframework.security.provisioning.UserDetailsManager +import org.springframework.security.web.SecurityFilterChain +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter + +@Configuration +@EnableWebSecurity +class SecurityConfig { + + @Bean + SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.apply(CustomDsl.customDsl()) + http + .csrf().disable() + .formLogin((form) -> form.loginPage("/login").permitAll()) + .authorizeHttpRequests() + .requestMatchers("/", "/success", "/register", "/login", "/custom").permitAll() + .anyRequest().authenticated() + return http.build() + } + + @Bean + UserDetailsManager userDetailsService() { + return new InMemoryUserDetailsManager() { + @Override + void createUser(UserDetails user) { + if (user.username == 'cant_create_me') { + throw new IllegalArgumentException('cannot create user') + } + super.createUser(user) + } + } + } + + static class CustomDsl extends AbstractHttpConfigurer { + @Override + void configure(HttpSecurity http) throws Exception { + AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager) + http.authenticationProvider(new CustomAuthenticationProvider()) + http.addFilterBefore(new CustomAuthenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter) + } + + static CustomDsl customDsl() { + return new CustomDsl() + } + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SpringBootBasedTest.groovy b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SpringBootBasedTest.groovy new file mode 100644 index 00000000000..0dca21ff574 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SpringBootBasedTest.groovy @@ -0,0 +1,291 @@ +package datadog.trace.instrumentation.springsecurity6 + +import ch.qos.logback.classic.Logger +import ch.qos.logback.core.Appender +import com.datadog.appsec.AppSecHttpServerTest +import datadog.trace.agent.test.base.HttpServer +import datadog.trace.api.config.AppSecConfig +import datadog.trace.core.DDSpan +import datadog.trace.instrumentation.springsecurity5.SpringSecurityUserEventDecorator +import okhttp3.FormBody +import okhttp3.HttpUrl +import okhttp3.Request +import okhttp3.RequestBody +import org.springframework.boot.SpringApplication +import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext +import org.springframework.context.ConfigurableApplicationContext +import spock.lang.Shared + +import static datadog.trace.agent.test.utils.OkHttpUtils.clientBuilder +import static datadog.trace.agent.test.utils.OkHttpUtils.cookieJar +import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.CUSTOM +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.LOGIN +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.NOT_FOUND +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.REGISTER +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.SUCCESS +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.UNKNOWN + +class SpringBootBasedTest extends AppSecHttpServerTest { + + @Shared + def context + + SpringApplication application() { + return new SpringApplication(AppConfig, UserController, SecurityConfig) + } + + class SpringBootServer implements HttpServer { + def port = 0 + final app = application() + + @Override + void start() { + app.setDefaultProperties(["server.port": 0, "server.context-path": "/"]) + context = app.run() + port = (context as ServletWebServerApplicationContext).webServer.port + assert port > 0 + } + + @Override + void stop() { + context.close() + } + + @Override + URI address() { + return new URI("http://localhost:$port/") + } + + @Override + String toString() { + return this.class.name + } + } + + @Override + HttpServer server() { + return new SpringBootServer() + } + + + @Override + int version() { + return 0 + } + + @Override + String service() { + return null + } + + @Override + String operation() { + return null + } + + @Override + protected void configurePreAgent() { + super.configurePreAgent() + injectSysConfig(AppSecConfig.APPSEC_AUTO_USER_INSTRUMENTATION_MODE, 'identification') + } + + Request.Builder request(TestEndpoint uri, String method, RequestBody body) { + def url = HttpUrl.get(uri.resolve(address)).newBuilder() + .encodedQuery(uri.rawQuery) + .fragment(uri.fragment) + .build() + return new Request.Builder() + .url(url) + //.addHeader('user-agent', 'Arachni/v1') + .method(method, body) + } + + static T controller(TestEndpoint endpoint, Closure closure) { + if (endpoint == NOT_FOUND || endpoint == UNKNOWN) { + return closure() + } + return runUnderTrace("controller", closure) + } + + + def "test signup event"() { + setup: + RequestBody formBody = new FormBody.Builder() + .add("username", "admin") + .add("password", "admin") + .build() + + def request = request(REGISTER, "POST", formBody).build() + + when: + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + DDSpan span = TEST_WRITER.flatten().first() + + then: + response.code() == REGISTER.status + response.body().string() == REGISTER.body + !span.getTags().isEmpty() + span.getTag("appsec.events.users.signup.track") == true + span.getTag("_dd.appsec.events.users.signup.auto.mode") == 'identification' + span.getTag("usr.id") == 'admin' + span.getTag("appsec.events.users.signup")['enabled'] == 'true' + span.getTag("appsec.events.users.signup")['authorities'] == 'ROLE_USER' + } + + + def "test failed login with non existing user"() { + setup: + RequestBody formBody = new FormBody.Builder() + .add("username", "not_existing_user") + .add("password", "some_password") + .build() + + def request = request(LOGIN, "POST", formBody).build() + + when: + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + DDSpan span = TEST_WRITER.flatten().first() + + then: + response.code() == LOGIN.status + response.body().string() == LOGIN.body + !span.getTags().isEmpty() + span.getTag("appsec.events.users.login.failure.track") == true + span.getTag("_dd.appsec.events.users.login.failure.auto.mode") == 'identification' + span.getTag("appsec.events.users.login.failure.usr.exists") == false + span.getTag("appsec.events.users.login.failure.usr.id") == 'not_existing_user' + } + + + def "test failed login with existing user but wrong password"() { + setup: + RequestBody formBody = new FormBody.Builder() + .add("username", "admin") + .add("password", "wrong_password").build() + + def request = request(LOGIN, "POST", formBody).build() + + when: + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + DDSpan span = TEST_WRITER.flatten().first() + + then: + response.code() == LOGIN.status + response.body().string() == LOGIN.body + !span.getTags().isEmpty() + span.getTag("appsec.events.users.login.failure.track") == true + span.getTag("_dd.appsec.events.users.login.failure.auto.mode") == 'identification' + // TODO: Ideally should be `false` but we have no reliable method to detect it it is just absent. See APPSEC-12765. + span.getTag("appsec.events.users.login.failure.usr.exists") == null + span.getTag("appsec.events.users.login.failure.usr.id") == 'admin' + } + + + def "test success login"() { + setup: + RequestBody formBody = new FormBody.Builder() + .add("username", "admin") + .add("password", "admin") + .build() + + def request = request(LOGIN, "POST", formBody).build() + + when: + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + DDSpan span = TEST_WRITER.flatten().first() + + then: + response.code() == LOGIN.status + response.body().string() == LOGIN.body + !span.getTags().isEmpty() + span.getTag("appsec.events.users.login.success.track") == true + span.getTag("_dd.appsec.events.users.login.success.auto.mode") == 'identification' + span.getTag("usr.id") == 'admin' + span.getTag("appsec.events.users.login.success")['credentialsNonExpired'] == 'true' + span.getTag("appsec.events.users.login.success")['accountNonExpired'] == 'true' + span.getTag("appsec.events.users.login.success")['enabled'] == 'true' + span.getTag("appsec.events.users.login.success")['authorities'] == 'ROLE_USER' + span.getTag("appsec.events.users.login.success")['accountNonLocked'] == 'true' + } + + void 'test failed signup'() { + setup: + final formBody = new FormBody.Builder() + .add('username', 'cant_create_me') + .add('password', 'cant_create_me') + .build() + + final request = request(REGISTER, 'POST', formBody).build() + + when: + final response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + final span = TEST_WRITER.flatten().first() as DDSpan + + then: + response.code() == 500 + span.getTags().findAll { it.key.startsWith('appsec.events.users.signup') }.isEmpty() + } + + void 'test skipped authentication'() { + setup: + final appender = Mock(Appender) + final logger = SpringSecurityUserEventDecorator.LOGGER as Logger + logger.addAppender(appender) + + and: + final requestCount = 3 + final request = request(CUSTOM, "GET", null).addHeader('X-Custom-User', 'batman').build() + + when: + final response = (1..requestCount).collect { client.newCall(request).execute() }.first() + TEST_WRITER.waitForTraces(3) + final span = TEST_WRITER.flatten().first() as DDSpan + logger.detachAppender(appender) // cant add cleanup + + then: + response.code() == CUSTOM.status + span.context().resourceName.contains(CUSTOM.path) + span.getTags().findAll { key, value -> key.startsWith('appsec.events.users.login')}.isEmpty() + // single call to the appender + 1 * appender.doAppend(_) >> { + assert it[0].toString().contains('Skipped authentication, auth=org.springframework.security.authentication.AbstractAuthenticationToken') + } + 0 * appender._ + } + + void 'test user event'() { + setup: + def client = clientBuilder().cookieJar(cookieJar()).followRedirects(false).build() + def formBody = new FormBody.Builder() + .add("username", "admin") + .add("password", "admin") + .build() + + def loginRequest = request(LOGIN, "POST", formBody).build() + def loginResponse = client.newCall(loginRequest).execute() + assert loginResponse.code() == LOGIN.status + assert loginResponse.body().string() == LOGIN.body + TEST_WRITER.waitForTraces(1) + TEST_WRITER.start() // clear all traces + + when: + def request = request(SUCCESS, "GET", null).build() + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + def span = TEST_WRITER.flatten().first() as DDSpan + + then: + response.code() == SUCCESS.status + response.body().string() == SUCCESS.body + span.getResourceName().toString() == 'GET /success' + !span.getTags().isEmpty() + span.getTag("usr.id") == 'admin' + span.getTag("_dd.appsec.user.collection_mode") == 'ident' + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/TestEndpoint.groovy b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/TestEndpoint.groovy new file mode 100644 index 00000000000..ab0c1528b26 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/TestEndpoint.groovy @@ -0,0 +1,50 @@ +package datadog.trace.instrumentation.springsecurity6 + +enum TestEndpoint { + LOGIN("login", 302, ""), + REGISTER("register", 200, ""), + NOT_FOUND("not-found", 404, "not found"), + UNKNOWN("", 451, null), // This needs to have a valid status code + CUSTOM("custom", 302, ""), + SUCCESS("success", 200, ""), + + private final String path + private final String rawPath + final String query + final String rawQuery + final String fragment + final int status + final String body + + TestEndpoint(String uri, int status, String body) { + def uriObj = URI.create(uri) + this.path = uriObj.path + this.rawPath = uriObj.rawPath + this.query = uriObj.query + this.rawQuery = uriObj.rawQuery + this.fragment = uriObj.fragment + this.status = status + this.body = body + } + + String getPath() { + return "/$path" + } + + String relativePath() { + return path + } + + String getRawPath() { + return "/$rawPath" + } + + String relativeRawPath() { + return rawPath + } + + URI resolve(URI address) { + // must be relative path to allow for servlet context + return address.resolve(relativeRawPath()) + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/UserController.groovy b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/UserController.groovy new file mode 100644 index 00000000000..03b29f7c271 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/UserController.groovy @@ -0,0 +1,45 @@ +package datadog.trace.instrumentation.springsecurity6 + + +import org.springframework.security.core.userdetails.User +import org.springframework.security.provisioning.UserDetailsManager +import org.springframework.stereotype.Controller +import org.springframework.ui.Model +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.ResponseBody + +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.REGISTER +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.SUCCESS + +@Controller +class UserController { + + private final UserDetailsManager userDetailsManager + + UserController(UserDetailsManager userDetailsManager) { + this.userDetailsManager = userDetailsManager + } + + @RequestMapping("/success") + @ResponseBody + String success() { + SpringBootBasedTest.controller(SUCCESS) { + SUCCESS.body + } + } + + @PostMapping("/register") + @ResponseBody + void register( + @RequestParam("username") String username, + @RequestParam("password") String password, + Model model) { + SpringBootBasedTest.controller(REGISTER) { + userDetailsManager.createUser( + User.withUsername(username).password("{noop}" + password).roles("USER").build()) + model.addAttribute("username", username) + } + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationFilter.java b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationFilter.java new file mode 100644 index 00000000000..b3ec62a572b --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationFilter.java @@ -0,0 +1,33 @@ +package custom; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; + +public class CustomAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + + private static final String HEADER_NAME = "X-Custom-User"; + + private final AuthenticationManager authenticationManager; + + public CustomAuthenticationFilter(final AuthenticationManager authenticationManager) { + super("/custom"); + this.authenticationManager = authenticationManager; + } + + @Override + public Authentication attemptAuthentication( + HttpServletRequest request, HttpServletResponse response) + throws AuthenticationException, IOException, ServletException { + final String user = request.getHeader(HEADER_NAME); + if (user == null) { + return null; + } + return authenticationManager.authenticate(new CustomAuthenticationToken(user)); + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationProvider.java b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationProvider.java new file mode 100644 index 00000000000..ac9b8706ab9 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationProvider.java @@ -0,0 +1,18 @@ +package custom; + +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; + +public class CustomAuthenticationProvider implements AuthenticationProvider { + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + return authentication; + } + + @Override + public boolean supports(Class authentication) { + return CustomAuthenticationToken.class.isAssignableFrom(authentication); + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationToken.java b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationToken.java new file mode 100644 index 00000000000..b85fdc4ad99 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationToken.java @@ -0,0 +1,24 @@ +package custom; + +import java.util.Collections; +import org.springframework.security.authentication.AbstractAuthenticationToken; + +public class CustomAuthenticationToken extends AbstractAuthenticationToken { + + private final String user; + + public CustomAuthenticationToken(String user) { + super(Collections.emptyList()); + this.user = user; + } + + @Override + public Object getCredentials() { + return user; + } + + @Override + public Object getPrincipal() { + return user; + } +} diff --git a/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java b/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java index 204c53a3736..c4e84ae317e 100644 --- a/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java +++ b/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java @@ -47,6 +47,8 @@ public abstract void onLoginSuccessEvent( public abstract void onLoginFailureEvent( UserIdCollectionMode mode, String userId, Boolean exists, Map metadata); + public abstract void onUserEvent(UserIdCollectionMode mode, String userId); + public abstract void onCustomEvent( UserIdCollectionMode mode, String eventName, Map metadata); } diff --git a/settings.gradle b/settings.gradle index d332a3df27d..130d0035043 100644 --- a/settings.gradle +++ b/settings.gradle @@ -433,6 +433,7 @@ include ':dd-java-agent:instrumentation:spring-messaging-4' include ':dd-java-agent:instrumentation:spring-rabbit' include ':dd-java-agent:instrumentation:spring-scheduling-3.1' include ':dd-java-agent:instrumentation:spring-security-5' +include ':dd-java-agent:instrumentation:spring-security-6' include ':dd-java-agent:instrumentation:spring-webflux-5' include ':dd-java-agent:instrumentation:spring-webflux-6' include ':dd-java-agent:instrumentation:spring-webmvc-3.1' From efa3824d5d3935a99a112dc3603b691e4bdeef79 Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Mon, 30 Sep 2024 09:56:07 +0200 Subject: [PATCH 18/18] Add akka-http client 10.6+ support (#7680) * Add akka-http client 10.6+ support * slf4j * align akka latest --- .../akka-http-10.0/build.gradle | 2 +- .../akka-http-10.0/gradle.lockfile | 0 .../AkkaHttpClientInstrumentationTest.groovy | 0 .../AkkaHttpServerInstrumentationTest.groovy | 0 .../src/baseTest/resources/application.conf | 0 .../scala/AkkaHttpTestWebServer.scala | 0 .../iast/AkkaIastTestWebServer.groovy | 0 .../akkahttp/iast/IastAkkaTest.groovy | 0 .../foo/bar/WithInstrumentedCallSites.groovy | 0 .../src/lagomTest/groovy/LagomTest.groovy | 0 .../src/lagomTest/java/EchoService.java | 0 .../src/lagomTest/java/EchoServiceImpl.java | 0 .../src/lagomTest/java/ServiceTestModule.java | 0 .../src/lagomTest/resources/application.conf | 0 ...kaHttp102ServerInstrumentationTests.groovy | 0 .../scala/AkkaHttp102TestWebServer.scala | 0 .../AkkaHttp2ServerInstrumentation.java | 0 .../akkahttp/AkkaHttpClientDecorator.java | 0 .../akkahttp/AkkaHttpClientHelpers.java | 0 .../akkahttp/AkkaHttpServerDecorator.java | 0 .../akkahttp/AkkaHttpServerHeaders.java | 0 .../AkkaHttpServerInstrumentation.java | 0 .../AkkaHttpSingleRequestInstrumentation.java | 0 .../AkkaPoolMasterActorInstrumentation.java | 0 .../akkahttp/DatadogAsyncHandlerWrapper.java | 0 ...tadogServerRequestResponseFlowWrapper.java | 0 .../akkahttp/DatadogWrapperHelper.java | 0 ...efaultExceptionHandlerInstrumentation.java | 0 .../akkahttp/MarkSpanAsErroredPF.java | 0 .../RecoverFromBlockedExceptionPF.java | 0 .../instrumentation/akkahttp/UriAdapter.java | 0 .../appsec/AkkaBlockResponseFunction.java | 0 .../appsec/BlockingResponseHelper.java | 0 .../appsec/Bug4304Instrumentation.java | 0 ...ideRemoteAddressHeaderInstrumentation.java | 0 .../FormDataToStrictInstrumentation.java | 0 .../JacksonUnmarshallerInstrumentation.java | 0 ...MultipartUnmarshallersInstrumentation.java | 0 ...romEntityUnmarshallersInstrumentation.java | 0 .../akkahttp/appsec/ScalaListCollector.java | 0 .../ScalaListCollectorMuzzleReferences.java | 0 .../SprayUnmarshallerInstrumentation.java | 0 .../StrictFormCompanionInstrumentation.java | 0 .../akkahttp/appsec/UnmarshallerHelpers.java | 0 .../iast/CookieDirectivesInstrumentation.java | 0 .../iast/CookieHeaderInstrumentation.java | 0 .../ExtractDirectivesInstrumentation.java | 0 .../iast/FormDataInstrumentation.java | 0 .../FormFieldDirectivesInstrumentation.java | 0 .../akkahttp/iast/HeaderNameCallSite.java | 0 .../HttpHeaderSubclassesInstrumentation.java | 0 .../iast/HttpRequestInstrumentation.java | 0 .../iast/MakeTaintableInstrumentation.java | 0 .../MarshallingDirectivesInstrumentation.java | 0 .../ParameterDirectivesInstrumentation.java | 0 .../iast/PathMatcherInstrumentation.java | 0 .../iast/RequestContextInstrumentation.java | 0 .../akkahttp/iast/TraitMethodMatchers.java | 0 .../iast/UnmarshallerInstrumentation.java | 0 .../akkahttp/iast/UriInstrumentation.java | 0 .../akkahttp/iast/helpers/ScalaToJava.java | 0 .../iast/helpers/TaintCookieFunction.java | 0 .../iast/helpers/TaintFutureHelper.java | 0 .../iast/helpers/TaintMapFunction.java | 0 .../iast/helpers/TaintMultiMapFunction.java | 0 .../helpers/TaintOptionalCookieFunction.java | 0 .../helpers/TaintRequestContextFunction.java | 0 .../iast/helpers/TaintRequestFunction.java | 0 .../iast/helpers/TaintSeqFunction.java | 0 .../helpers/TaintSingleParameterFunction.java | 0 .../iast/helpers/TaintUnmarshaller.java | 0 .../iast/helpers/TaintUriFunction.java | 0 .../akka-http-10.2-iast/build.gradle | 0 .../akka-http-10.2-iast/gradle.lockfile | 0 ...ormFieldDirectivesImplInstrumentation.java | 0 ...arameterDirectivesImplInstrumentation.java | 0 .../iast/helpers/TaintParametersFunction.java | 0 .../akka-http/akka-http-10.6/build.gradle | 80 +++ .../AkkaHttpSingleRequestInstrumentation.java | 39 ++ .../akkahttp106/AkkaHttpClientDecorator.java | 52 ++ .../akkahttp106/AkkaHttpClientHelpers.java | 83 +++ .../akkahttp106/SingleRequestAdvice.java | 63 +++ ...kaHttp102ServerInstrumentationTests.groovy | 55 ++ .../AkkaHttpClientInstrumentationTest.groovy | 151 ++++++ .../AkkaHttpServerInstrumentationTest.groovy | 319 +++++++++++ .../src/test/resources/application.conf | 6 + .../test/scala/AkkaHttp102TestWebServer.scala | 67 +++ .../test/scala/AkkaHttpTestWebServer.scala | 503 ++++++++++++++++++ .../instrumentation/akka-http/build.gradle | 1 + .../instrumentation/play-2.4/build.gradle | 2 +- .../instrumentation/play-2.6/build.gradle | 2 +- .../instrumentation/play-ws-1/build.gradle | 2 +- .../instrumentation/play-ws-2.1/build.gradle | 2 +- .../instrumentation/play-ws-2/build.gradle | 2 +- settings.gradle | 6 +- 95 files changed, 1429 insertions(+), 8 deletions(-) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/build.gradle (99%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/gradle.lockfile (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/baseTest/groovy/AkkaHttpClientInstrumentationTest.groovy (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/baseTest/groovy/AkkaHttpServerInstrumentationTest.groovy (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/baseTest/resources/application.conf (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/baseTest/scala/AkkaHttpTestWebServer.scala (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/AkkaIastTestWebServer.groovy (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/IastAkkaTest.groovy (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/iastTest/groovy/foo/bar/WithInstrumentedCallSites.groovy (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/lagomTest/groovy/LagomTest.groovy (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/lagomTest/java/EchoService.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/lagomTest/java/EchoServiceImpl.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/lagomTest/java/ServiceTestModule.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/lagomTest/resources/application.conf (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/latestDepTest/groovy/AkkaHttp102ServerInstrumentationTests.groovy (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/latestDepTest/scala/AkkaHttp102TestWebServer.scala (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttp2ServerInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientDecorator.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientHelpers.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerDecorator.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerHeaders.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpSingleRequestInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaPoolMasterActorInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogAsyncHandlerWrapper.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogServerRequestResponseFlowWrapper.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DefaultExceptionHandlerInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/MarkSpanAsErroredPF.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/RecoverFromBlockedExceptionPF.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/UriAdapter.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/AkkaBlockResponseFunction.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/BlockingResponseHelper.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/Bug4304Instrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ConfigProvideRemoteAddressHeaderInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/FormDataToStrictInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/JacksonUnmarshallerInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/MultipartUnmarshallersInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/PredefinedFromEntityUnmarshallersInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollector.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollectorMuzzleReferences.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/SprayUnmarshallerInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/StrictFormCompanionInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/UnmarshallerHelpers.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieDirectivesInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieHeaderInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ExtractDirectivesInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormDataInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormFieldDirectivesInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HeaderNameCallSite.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpHeaderSubclassesInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpRequestInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MakeTaintableInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MarshallingDirectivesInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ParameterDirectivesInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/PathMatcherInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/RequestContextInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/TraitMethodMatchers.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UnmarshallerInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UriInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/ScalaToJava.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintCookieFunction.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintFutureHelper.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMapFunction.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMultiMapFunction.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintOptionalCookieFunction.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestContextFunction.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestFunction.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSeqFunction.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSingleParameterFunction.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUnmarshaller.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUriFunction.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.2-iast/build.gradle (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.2-iast/gradle.lockfile (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/FormFieldDirectivesImplInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/ParameterDirectivesImplInstrumentation.java (100%) rename dd-java-agent/instrumentation/{ => akka-http}/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/helpers/TaintParametersFunction.java (100%) create mode 100644 dd-java-agent/instrumentation/akka-http/akka-http-10.6/build.gradle create mode 100644 dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java/datadog/trace/instrumentation/akkahttp106/AkkaHttpSingleRequestInstrumentation.java create mode 100644 dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientDecorator.java create mode 100644 dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientHelpers.java create mode 100644 dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/SingleRequestAdvice.java create mode 100644 dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttp102ServerInstrumentationTests.groovy create mode 100644 dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpClientInstrumentationTest.groovy create mode 100644 dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy create mode 100644 dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/resources/application.conf create mode 100644 dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttp102TestWebServer.scala create mode 100644 dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttpTestWebServer.scala create mode 100644 dd-java-agent/instrumentation/akka-http/build.gradle diff --git a/dd-java-agent/instrumentation/akka-http-10.0/build.gradle b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/build.gradle similarity index 99% rename from dd-java-agent/instrumentation/akka-http-10.0/build.gradle rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/build.gradle index a77f0330348..ed0efec6969 100644 --- a/dd-java-agent/instrumentation/akka-http-10.0/build.gradle +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/build.gradle @@ -120,7 +120,7 @@ dependencies { iastTestCompileOnly group: 'de.thetaphi', name: 'forbiddenapis', version: '3.4' iastTestRuntimeOnly project(':dd-java-agent:instrumentation:jackson-core') iastTestRuntimeOnly project(':dd-java-agent:instrumentation:iast-instrumenter') - iastTestRuntimeOnly project(':dd-java-agent:instrumentation:akka-http-10.2-iast') + iastTestRuntimeOnly project(':dd-java-agent:instrumentation:akka-http:akka-http-10.2-iast') // There are some internal API changes in 10.1 that we would like to test separately for version101TestImplementation libs.scala212 diff --git a/dd-java-agent/instrumentation/akka-http-10.0/gradle.lockfile b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/gradle.lockfile similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/gradle.lockfile rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/gradle.lockfile diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/groovy/AkkaHttpClientInstrumentationTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/groovy/AkkaHttpClientInstrumentationTest.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/groovy/AkkaHttpClientInstrumentationTest.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/groovy/AkkaHttpClientInstrumentationTest.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/groovy/AkkaHttpServerInstrumentationTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/groovy/AkkaHttpServerInstrumentationTest.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/groovy/AkkaHttpServerInstrumentationTest.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/groovy/AkkaHttpServerInstrumentationTest.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/resources/application.conf b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/resources/application.conf similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/resources/application.conf rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/resources/application.conf diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/scala/AkkaHttpTestWebServer.scala b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/scala/AkkaHttpTestWebServer.scala similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/scala/AkkaHttpTestWebServer.scala rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/scala/AkkaHttpTestWebServer.scala diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/AkkaIastTestWebServer.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/AkkaIastTestWebServer.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/AkkaIastTestWebServer.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/AkkaIastTestWebServer.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/IastAkkaTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/IastAkkaTest.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/IastAkkaTest.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/IastAkkaTest.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/foo/bar/WithInstrumentedCallSites.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/foo/bar/WithInstrumentedCallSites.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/foo/bar/WithInstrumentedCallSites.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/foo/bar/WithInstrumentedCallSites.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/groovy/LagomTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/groovy/LagomTest.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/groovy/LagomTest.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/groovy/LagomTest.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/EchoService.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/EchoService.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/EchoService.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/EchoService.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/EchoServiceImpl.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/EchoServiceImpl.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/EchoServiceImpl.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/EchoServiceImpl.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/ServiceTestModule.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/ServiceTestModule.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/ServiceTestModule.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/ServiceTestModule.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/resources/application.conf b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/resources/application.conf similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/resources/application.conf rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/resources/application.conf diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/latestDepTest/groovy/AkkaHttp102ServerInstrumentationTests.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/latestDepTest/groovy/AkkaHttp102ServerInstrumentationTests.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/latestDepTest/groovy/AkkaHttp102ServerInstrumentationTests.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/latestDepTest/groovy/AkkaHttp102ServerInstrumentationTests.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/latestDepTest/scala/AkkaHttp102TestWebServer.scala b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/latestDepTest/scala/AkkaHttp102TestWebServer.scala similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/latestDepTest/scala/AkkaHttp102TestWebServer.scala rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/latestDepTest/scala/AkkaHttp102TestWebServer.scala diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttp2ServerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttp2ServerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttp2ServerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttp2ServerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientDecorator.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientDecorator.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientDecorator.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientDecorator.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientHelpers.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientHelpers.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientHelpers.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientHelpers.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerDecorator.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerDecorator.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerDecorator.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerDecorator.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerHeaders.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerHeaders.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerHeaders.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerHeaders.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpSingleRequestInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpSingleRequestInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpSingleRequestInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpSingleRequestInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaPoolMasterActorInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaPoolMasterActorInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaPoolMasterActorInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaPoolMasterActorInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogAsyncHandlerWrapper.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogAsyncHandlerWrapper.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogAsyncHandlerWrapper.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogAsyncHandlerWrapper.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogServerRequestResponseFlowWrapper.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogServerRequestResponseFlowWrapper.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogServerRequestResponseFlowWrapper.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogServerRequestResponseFlowWrapper.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DefaultExceptionHandlerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DefaultExceptionHandlerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DefaultExceptionHandlerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DefaultExceptionHandlerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/MarkSpanAsErroredPF.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/MarkSpanAsErroredPF.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/MarkSpanAsErroredPF.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/MarkSpanAsErroredPF.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/RecoverFromBlockedExceptionPF.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/RecoverFromBlockedExceptionPF.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/RecoverFromBlockedExceptionPF.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/RecoverFromBlockedExceptionPF.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/UriAdapter.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/UriAdapter.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/UriAdapter.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/UriAdapter.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/AkkaBlockResponseFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/AkkaBlockResponseFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/AkkaBlockResponseFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/AkkaBlockResponseFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/BlockingResponseHelper.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/BlockingResponseHelper.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/BlockingResponseHelper.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/BlockingResponseHelper.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/Bug4304Instrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/Bug4304Instrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/Bug4304Instrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/Bug4304Instrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ConfigProvideRemoteAddressHeaderInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ConfigProvideRemoteAddressHeaderInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ConfigProvideRemoteAddressHeaderInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ConfigProvideRemoteAddressHeaderInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/FormDataToStrictInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/FormDataToStrictInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/FormDataToStrictInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/FormDataToStrictInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/JacksonUnmarshallerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/JacksonUnmarshallerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/JacksonUnmarshallerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/JacksonUnmarshallerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/MultipartUnmarshallersInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/MultipartUnmarshallersInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/MultipartUnmarshallersInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/MultipartUnmarshallersInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/PredefinedFromEntityUnmarshallersInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/PredefinedFromEntityUnmarshallersInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/PredefinedFromEntityUnmarshallersInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/PredefinedFromEntityUnmarshallersInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollector.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollector.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollector.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollector.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollectorMuzzleReferences.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollectorMuzzleReferences.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollectorMuzzleReferences.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollectorMuzzleReferences.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/SprayUnmarshallerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/SprayUnmarshallerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/SprayUnmarshallerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/SprayUnmarshallerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/StrictFormCompanionInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/StrictFormCompanionInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/StrictFormCompanionInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/StrictFormCompanionInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/UnmarshallerHelpers.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/UnmarshallerHelpers.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/UnmarshallerHelpers.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/UnmarshallerHelpers.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieDirectivesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieDirectivesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieDirectivesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieDirectivesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieHeaderInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieHeaderInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieHeaderInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieHeaderInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ExtractDirectivesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ExtractDirectivesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ExtractDirectivesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ExtractDirectivesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormDataInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormDataInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormDataInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormDataInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormFieldDirectivesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormFieldDirectivesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormFieldDirectivesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormFieldDirectivesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HeaderNameCallSite.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HeaderNameCallSite.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HeaderNameCallSite.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HeaderNameCallSite.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpHeaderSubclassesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpHeaderSubclassesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpHeaderSubclassesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpHeaderSubclassesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpRequestInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpRequestInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpRequestInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpRequestInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MakeTaintableInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MakeTaintableInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MakeTaintableInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MakeTaintableInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MarshallingDirectivesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MarshallingDirectivesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MarshallingDirectivesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MarshallingDirectivesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ParameterDirectivesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ParameterDirectivesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ParameterDirectivesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ParameterDirectivesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/PathMatcherInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/PathMatcherInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/PathMatcherInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/PathMatcherInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/RequestContextInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/RequestContextInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/RequestContextInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/RequestContextInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/TraitMethodMatchers.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/TraitMethodMatchers.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/TraitMethodMatchers.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/TraitMethodMatchers.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UnmarshallerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UnmarshallerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UnmarshallerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UnmarshallerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UriInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UriInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UriInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UriInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/ScalaToJava.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/ScalaToJava.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/ScalaToJava.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/ScalaToJava.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintCookieFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintCookieFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintCookieFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintCookieFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintFutureHelper.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintFutureHelper.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintFutureHelper.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintFutureHelper.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMapFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMapFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMapFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMapFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMultiMapFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMultiMapFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMultiMapFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMultiMapFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintOptionalCookieFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintOptionalCookieFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintOptionalCookieFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintOptionalCookieFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestContextFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestContextFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestContextFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestContextFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSeqFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSeqFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSeqFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSeqFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSingleParameterFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSingleParameterFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSingleParameterFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSingleParameterFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUnmarshaller.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUnmarshaller.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUnmarshaller.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUnmarshaller.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUriFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUriFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUriFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUriFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.2-iast/build.gradle b/dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/build.gradle similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.2-iast/build.gradle rename to dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/build.gradle diff --git a/dd-java-agent/instrumentation/akka-http-10.2-iast/gradle.lockfile b/dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/gradle.lockfile similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.2-iast/gradle.lockfile rename to dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/gradle.lockfile diff --git a/dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/FormFieldDirectivesImplInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/FormFieldDirectivesImplInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/FormFieldDirectivesImplInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/FormFieldDirectivesImplInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/ParameterDirectivesImplInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/ParameterDirectivesImplInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/ParameterDirectivesImplInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/ParameterDirectivesImplInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/helpers/TaintParametersFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/helpers/TaintParametersFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/helpers/TaintParametersFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/helpers/TaintParametersFunction.java diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/build.gradle b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/build.gradle new file mode 100644 index 00000000000..0c6522331c3 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/build.gradle @@ -0,0 +1,80 @@ +// Set properties before any plugins get loaded +ext { + minJavaVersionForTests = JavaVersion.VERSION_11 +} + +apply from: "$rootDir/gradle/java.gradle" +apply plugin: 'scala' +apply plugin: 'call-site-instrumentation' + + +muzzle { + pass { + group = 'com.typesafe.akka' + module = 'akka-http_2.13' + versions = "[10.6.0,)" + javaVersion = "11" + extraDependency 'com.typesafe.akka:akka-stream_2.13:2.9.0' + extraRepository('akka', 'https://repo.akka.io/maven') + assertInverse = true + } + +} + +repositories { + maven { + url "https://repo.akka.io/maven" + } +} + +addTestSuiteForDir('latestDepTest', 'test') + +[compileMain_java11Java, compileTestScala, compileLatestDepTestScala].each { + it.configure { + setJavaVersion(it, 11) + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} + +compileTestGroovy { + javaLauncher = getJavaLauncherFor(11) + dependsOn compileTestScala + classpath += files(compileTestScala.destinationDirectory) +} + +compileLatestDepTestGroovy { + javaLauncher = getJavaLauncherFor(11) + dependsOn compileLatestDepTestScala + classpath += files(compileLatestDepTestScala.destinationDirectory) +} + +dependencies { + main_java11CompileOnly libs.scala213 + main_java11CompileOnly group: 'com.typesafe.akka', name: 'akka-http_2.13', version: '10.6.0' + main_java11CompileOnly group: 'com.typesafe.akka', name: 'akka-actor_2.13', version: '2.9.0' + + //testImplementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.6.0' + testImplementation group: 'com.typesafe.akka', name: 'akka-http_2.13', version: '10.6.0' + testImplementation group: 'com.typesafe.akka', name: 'akka-stream_2.13', version: '2.9.0' + testImplementation group: 'com.typesafe.akka', name: 'akka-http-jackson_2.13', version: '10.6.0' + testImplementation group: 'com.typesafe.akka', name: 'akka-http-spray-json_2.13', version: '10.6.0' + testImplementation libs.scala213 + testImplementation project(':dd-java-agent:instrumentation:trace-annotation') + testImplementation project(':dd-java-agent:instrumentation:akka-concurrent') + testImplementation project(':dd-java-agent:instrumentation:scala-concurrent') + testImplementation project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') + testImplementation project(':dd-java-agent:instrumentation:scala-promise:scala-promise-2.13') + + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-http_2.13', version: '+' + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-stream_2.13', version: '+' + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-pki_2.13', version: '+' + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-protobuf-v3_2.13', version: '+' + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-http-jackson_2.13', version: '+' + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-http-spray-json_2.13', version: '+' + latestDepTestImplementation group: 'org.scala-lang.modules', name: 'scala-java8-compat_2.13', version: '1.0.+' +} + +configurations.getByName("latestDepTestRuntimeClasspath").resolutionStrategy { + it.force libs.slf4j +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java/datadog/trace/instrumentation/akkahttp106/AkkaHttpSingleRequestInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java/datadog/trace/instrumentation/akkahttp106/AkkaHttpSingleRequestInstrumentation.java new file mode 100644 index 00000000000..688a9f06475 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java/datadog/trace/instrumentation/akkahttp106/AkkaHttpSingleRequestInstrumentation.java @@ -0,0 +1,39 @@ +package datadog.trace.instrumentation.akkahttp106; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import com.google.auto.service.AutoService; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.agent.tooling.InstrumenterModule; + +@AutoService(InstrumenterModule.class) +public final class AkkaHttpSingleRequestInstrumentation extends InstrumenterModule.Tracing + implements Instrumenter.ForSingleType { + public AkkaHttpSingleRequestInstrumentation() { + super("akka-http", "akka-http-client"); + } + + @Override + public String instrumentedType() { + return "akka.http.scaladsl.HttpExt"; + } + + @Override + public String[] helperClassNames() { + return new String[] { + packageName + ".AkkaHttpClientHelpers", + packageName + ".AkkaHttpClientHelpers$OnCompleteHandler", + packageName + ".AkkaHttpClientHelpers$AkkaHttpHeaders", + packageName + ".AkkaHttpClientHelpers$HasSpanHeader", + packageName + ".AkkaHttpClientDecorator", + }; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + named("singleRequest").and(takesArgument(0, named("akka.http.scaladsl.model.HttpRequest"))), + packageName + ".SingleRequestAdvice"); + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientDecorator.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientDecorator.java new file mode 100644 index 00000000000..35f5b54e734 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientDecorator.java @@ -0,0 +1,52 @@ +package datadog.trace.instrumentation.akkahttp106; + +import akka.http.javadsl.model.HttpHeader; +import akka.http.scaladsl.model.HttpRequest; +import akka.http.scaladsl.model.HttpResponse; +import datadog.trace.bootstrap.instrumentation.api.URIUtils; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.bootstrap.instrumentation.decorator.HttpClientDecorator; +import java.net.URI; +import java.net.URISyntaxException; + +public class AkkaHttpClientDecorator extends HttpClientDecorator { + public static final CharSequence AKKA_HTTP_CLIENT = UTF8BytesString.create("akka-http-client"); + public static final AkkaHttpClientDecorator DECORATE = new AkkaHttpClientDecorator(); + public static final CharSequence AKKA_CLIENT_REQUEST = + UTF8BytesString.create(DECORATE.operationName()); + + @Override + protected String[] instrumentationNames() { + return new String[] {"akka-http", "akka-http-client"}; + } + + @Override + protected CharSequence component() { + return AKKA_HTTP_CLIENT; + } + + @Override + protected String method(final HttpRequest httpRequest) { + return httpRequest.method().value(); + } + + @Override + protected URI url(final HttpRequest httpRequest) throws URISyntaxException { + return URIUtils.safeParse(httpRequest.uri().toString()); + } + + @Override + protected int status(final HttpResponse httpResponse) { + return httpResponse.status().intValue(); + } + + @Override + protected String getRequestHeader(HttpRequest request, String headerName) { + return request.getHeader(headerName).map(HttpHeader::value).orElse(null); + } + + @Override + protected String getResponseHeader(HttpResponse response, String headerName) { + return response.getHeader(headerName).map(HttpHeader::value).orElse(null); + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientHelpers.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientHelpers.java new file mode 100644 index 00000000000..b9e0fc65042 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientHelpers.java @@ -0,0 +1,83 @@ +package datadog.trace.instrumentation.akkahttp106; + +import akka.http.javadsl.model.headers.RawHeader; +import akka.http.scaladsl.model.HttpRequest; +import akka.http.scaladsl.model.HttpResponse; +import akka.http.scaladsl.model.headers.CustomHeader; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import scala.runtime.AbstractFunction1; +import scala.util.Try; + +public final class AkkaHttpClientHelpers { + public static class OnCompleteHandler extends AbstractFunction1, Void> { + private final AgentSpan span; + + public OnCompleteHandler(final AgentSpan span) { + this.span = span; + } + + @Override + public Void apply(final Try result) { + if (result.isSuccess()) { + AkkaHttpClientDecorator.DECORATE.onResponse(span, result.get()); + } else { + AkkaHttpClientDecorator.DECORATE.onError(span, result.failed().get()); + } + AkkaHttpClientDecorator.DECORATE.beforeFinish(span); + span.finish(); + return null; + } + } + + public static class AkkaHttpHeaders implements AgentPropagation.Setter { + private HttpRequest request; + // Did this request have a span when the AkkaHttpHeaders object was created? + private boolean hadSpan; + + public AkkaHttpHeaders(final HttpRequest request) { + hadSpan = request != null && request.getHeader("x-datadog-request-has-span").isPresent(); + if (hadSpan || request == null) { + this.request = request; + } else { + this.request = (HttpRequest) request.addHeader(new HasSpanHeader()); + } + } + + public boolean hadSpan() { + return hadSpan; + } + + @Override + public void set(final HttpRequest carrier, final String key, final String value) { + request = (HttpRequest) request.addHeader(RawHeader.create(key, value)); + } + + public HttpRequest getRequest() { + return request; + } + } + + // Custom header to mark that this request has a span associated with it + public static class HasSpanHeader extends CustomHeader { + @Override + public String name() { + return "x-datadog-request-has-span"; + } + + @Override + public String value() { + return "true"; + } + + @Override + public boolean renderInRequests() { + return false; + } + + @Override + public boolean renderInResponses() { + return false; + } + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/SingleRequestAdvice.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/SingleRequestAdvice.java new file mode 100644 index 00000000000..8e987bc8ec8 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/SingleRequestAdvice.java @@ -0,0 +1,63 @@ +package datadog.trace.instrumentation.akkahttp106; + +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.propagate; +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan; + +import akka.http.scaladsl.HttpExt; +import akka.http.scaladsl.model.HttpRequest; +import akka.http.scaladsl.model.HttpResponse; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.decorator.HttpClientDecorator; +import net.bytebuddy.asm.Advice; +import scala.concurrent.Future; + +public class SingleRequestAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static AgentScope methodEnter( + @Advice.Argument(value = 0, readOnly = false) HttpRequest request) { + final AkkaHttpClientHelpers.AkkaHttpHeaders headers = + new AkkaHttpClientHelpers.AkkaHttpHeaders(request); + if (headers.hadSpan()) { + return null; + } + + final AgentSpan span = startSpan(AkkaHttpClientDecorator.AKKA_CLIENT_REQUEST); + AkkaHttpClientDecorator.DECORATE.afterStart(span); + AkkaHttpClientDecorator.DECORATE.onRequest(span, request); + + if (request != null) { + propagate().inject(span, request, headers); + propagate() + .injectPathwayContext( + span, request, headers, HttpClientDecorator.CLIENT_PATHWAY_EDGE_TAGS); + // Request is immutable, so we have to assign new value once we update headers + request = headers.getRequest(); + } + return activateSpan(span); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void methodExit( + @Advice.This final HttpExt thiz, + @Advice.Return final Future responseFuture, + @Advice.Enter final AgentScope scope, + @Advice.Thrown final Throwable throwable) { + if (scope == null) { + return; + } + + final AgentSpan span = scope.span(); + + if (throwable == null) { + responseFuture.onComplete( + new AkkaHttpClientHelpers.OnCompleteHandler(span), thiz.system().dispatcher()); + } else { + AkkaHttpClientDecorator.DECORATE.onError(span, throwable); + AkkaHttpClientDecorator.DECORATE.beforeFinish(span); + span.finish(); + } + scope.close(); + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttp102ServerInstrumentationTests.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttp102ServerInstrumentationTests.groovy new file mode 100644 index 00000000000..a8c4134f9f5 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttp102ServerInstrumentationTests.groovy @@ -0,0 +1,55 @@ +import datadog.trace.agent.test.base.HttpServer + +class AkkaHttp102ServerInstrumentationBindFlowTest extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttp102TestWebServer.ServerBuilderBindFlow()) + } + + @Override + boolean redirectHasBody() { + return true + } +} + +class AkkaHttp102ServerInstrumentationBindTest extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttp102TestWebServer.ServerBuilderBind()) + } +} + +class AkkaHttp102ServerInstrumentationBindSyncTest extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttp102TestWebServer.ServerBuilderBindSync()) + } + + // we test body endpoints only on the async tests + @Override + boolean testRequestBody() { + false + } + + @Override + boolean testBodyMultipart() { + false + } + + @Override + boolean testBodyJson() { + false + } + + @Override + boolean testBodyUrlencoded() { + false + } +} + +class AkkaHttp102ServerInstrumentationBindAsyncHttp2Test extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttp102TestWebServer.ServerBuilderBindHttp2()) + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpClientInstrumentationTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpClientInstrumentationTest.groovy new file mode 100644 index 00000000000..7d4513b5570 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpClientInstrumentationTest.groovy @@ -0,0 +1,151 @@ +import akka.actor.ActorSystem +import akka.http.javadsl.Http +import akka.http.javadsl.model.HttpMethods +import akka.http.javadsl.model.HttpRequest +import akka.http.javadsl.model.HttpResponse +import akka.http.javadsl.model.headers.RawHeader +import akka.http.scaladsl.settings.ConnectionPoolSettings +import datadog.trace.agent.test.base.HttpClientTest +import datadog.trace.agent.test.naming.TestingGenericHttpNamingConventions +import datadog.trace.api.DDSpanTypes +import datadog.trace.bootstrap.instrumentation.api.Tags +import datadog.trace.instrumentation.akkahttp106.AkkaHttpClientDecorator +import scala.compat.java8.FutureConverters +import scala.concurrent.Future +import spock.lang.Shared +import spock.lang.Timeout + +import java.util.concurrent.CompletionStage + +@Timeout(5) +abstract class AkkaHttpClientInstrumentationTest extends HttpClientTest { + @Shared + ActorSystem system = ActorSystem.create() + + abstract CompletionStage doRequest(HttpRequest request) + + @Override + int doRequest(String method, URI uri, Map headers, String body, Closure callback) { + def request = HttpRequest.create(uri.toString()) + .withMethod(HttpMethods.lookup(method).get()) + .addHeaders(headers.collect { RawHeader.create(it.key, it.value) }) + + def response + try { + response = doRequest(request) + .whenComplete { result, error -> + callback?.call() + } + .toCompletableFuture() + .get() + } finally { + // Since the spans are completed in an async callback, we need to wait here + blockUntilChildSpansFinished(1) + } + return response.status().intValue() + } + + @Override + CharSequence component() { + return AkkaHttpClientDecorator.DECORATE.component() + } + + @Override + boolean testRedirects() { + false + } + + @Override + boolean testRemoteConnection() { + // Not sure how to properly set timeouts... + return false + } + + def "singleRequest exception trace"() { + when: + Http.get(system).singleRequest(null) + + then: + def exception = thrown NullPointerException + assertTraces(1) { + trace(1) { + span { + parent() + operationName operation() + resourceName operation() // resource name is not set so defaults to operationName + spanType DDSpanTypes.HTTP_CLIENT + errored true + tags { + "$Tags.COMPONENT" "akka-http-client" + "$Tags.SPAN_KIND" Tags.SPAN_KIND_CLIENT + errorTags(exception) + defaultTags(false, false) + } + } + } + } + } +} + + +abstract class AkkaHttpJavaClientInstrumentationTest extends AkkaHttpClientInstrumentationTest { + @Override + CompletionStage doRequest(HttpRequest request) { + return Http.get(system).singleRequest(request) + } +} + + +abstract class AkkaHttpScalaClientInstrumentationTest extends AkkaHttpClientInstrumentationTest { + @Override + CompletionStage doRequest(HttpRequest request) { + def http = akka.http.scaladsl.Http.apply(system) + def sRequest = (akka.http.scaladsl.model.HttpRequest) request + Future f = http.singleRequest(sRequest, http.defaultClientHttpsContext(), + (ConnectionPoolSettings) ConnectionPoolSettings.apply(system), system.log()) + return FutureConverters.toJava(f) + } +} + +class AkkaHttpJavaClientInstrumentationV0Test extends AkkaHttpJavaClientInstrumentationTest { + + @Override + int version() { + return 0 + } + + @Override + String service() { + return null + } + + @Override + String operation() { + return "akka-http.client.request" + } +} + +class AkkaHttpJavaClientInstrumentationV1ForkedTest extends AkkaHttpJavaClientInstrumentationTest implements TestingGenericHttpNamingConventions.ClientV1 { +} + +class AkkaHttpScalaClientInstrumentationV0Test extends AkkaHttpScalaClientInstrumentationTest { + + @Override + int version() { + return 0 + } + + @Override + String service() { + return null + } + + @Override + String operation() { + return "akka-http.client.request" + } +} + +class AkkaHttpScalaClientInstrumentationV1ForkedTest extends AkkaHttpScalaClientInstrumentationTest implements TestingGenericHttpNamingConventions.ClientV1{ + +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy new file mode 100644 index 00000000000..397de4f2613 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy @@ -0,0 +1,319 @@ +import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_JSON +import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_MULTIPART +import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.SUCCESS +import static org.junit.Assume.assumeTrue + +import datadog.trace.agent.test.base.HttpServer +import datadog.trace.agent.test.base.HttpServerTest +import datadog.trace.agent.test.naming.TestingGenericHttpNamingConventions +import datadog.trace.agent.test.utils.ThreadUtils +import datadog.trace.instrumentation.akkahttp.AkkaHttpServerDecorator +import okhttp3.HttpUrl +import okhttp3.MultipartBody +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.Response +import spock.lang.Shared + +import java.util.concurrent.atomic.AtomicInteger + +abstract class AkkaHttpServerInstrumentationTest extends HttpServerTest { + + @Override + String component() { + return AkkaHttpServerDecorator.DECORATE.component() + } + + @Override + String expectedOperationName() { + return "akka-http.request" + } + + @Override + boolean testExceptionBody() { + false + } + + @Override + boolean hasExtraErrorInformation() { + return true + } + + @Override + protected boolean enabledFinishTimingChecks() { + true + } + + @Override + boolean changesAll404s() { + true + } + + @Override + boolean testBlocking() { + true + } + + @Override + boolean testBlockingOnResponse() { + true + } + + @Override + boolean testRequestBody() { + true + } + + @Override + boolean testBodyUrlencoded() { + true + } + + @Override + boolean testBodyMultipart() { + true + } + + @Override + boolean testBodyJson() { + true + } + + @Override + boolean isRequestBodyNoStreaming() { + true + } + + @Override + boolean testBadUrl() { + false + } + + @Shared + def totalInvocations = 200 + + @Shared + AtomicInteger counter = new AtomicInteger(0) + + void doAndValidateRequest(int id) { + def type = id & 1 ? "p" : "f" + String url = address.resolve("/injected-id/${type}ing/$id") + def traceId = totalInvocations + id + def request = new Request.Builder().url(url).get().header("x-datadog-trace-id", traceId.toString()).build() + def response = client.newCall(request).execute() + def responseBodyStr = response.body().string() + assert responseBodyStr == "${type}ong $id -> $traceId" + assert response.code() == 200 + } + + def "propagate trace id when we ping akka-http concurrently"() { + expect: + ThreadUtils.runConcurrently(10, totalInvocations, { + def id = counter.incrementAndGet() + doAndValidateRequest(id) + }) + + and: + TEST_WRITER.waitForTraces(totalInvocations) + } + + def 'test instrumentation gateway multipart request body — strict variant'() { + setup: + assumeTrue(testBodyMultipart()) + def body = new MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart('a', 'x') + .build() + + def url = HttpUrl.get(BODY_MULTIPART.resolve(address)).newBuilder() + .encodedQuery('variant=strictUnmarshaller') + .build() + def request = new Request.Builder() + .url(url) + .method('POST', body) + .build() + def response = client.newCall(request).execute() + if (isDataStreamsEnabled()) { + TEST_DATA_STREAMS_WRITER.waitForGroups(1) + } + + expect: + response.body().charStream().text == '[a:[x]]' + + when: + TEST_WRITER.waitForTraces(1) + + then: + TEST_WRITER.get(0).any { + it.getTag('request.body.converted') == '[a:[x]]' + } + } + + def 'test instrumentation gateway json request body — spray variant'() { + assumeTrue(testBodyJson()) + + setup: + def url = HttpUrl.get(BODY_JSON.resolve(address)).newBuilder() + .encodedQuery('variant=spray') + .build() + def request = new Request.Builder() + .url(url) + .method('POST', RequestBody.create(okhttp3.MediaType.get('application/json'), '{"a":"x"}\n')) + .build() + def response = client.newCall(request).execute() + if (isDataStreamsEnabled()) { + TEST_DATA_STREAMS_WRITER.waitForGroups(1) + } + + expect: + response.body().charStream().text == '{"a":"x"}' + + when: + TEST_WRITER.waitForTraces(1) + + then: + TEST_WRITER.get(0).any { + it.getTag('request.body.converted') == '[a:[x]]' + } + } + + void 'content length and type are provided to IG on strict responses'() { + setup: + Request request = request(SUCCESS, 'GET', null) + .header(IG_EXTRA_SPAN_NAME_HEADER, 'ig-span') + .header(IG_ASK_FOR_RESPONSE_HEADER_TAGS_HEADER, 'true') + .build() + Response response = client.newCall(request).execute() + if (isDataStreamsEnabled()) { + TEST_DATA_STREAMS_WRITER.waitForGroups(1) + } + + expect: + response.body().charStream().text == SUCCESS.body + + when: + TEST_WRITER.waitForTraces(1) + def tags = TEST_WRITER.get(0).find { it.spanName == 'ig-span' }.tags + + then: + tags['response.header.content-type'] != null + tags['response.header.content-length'] == SUCCESS.body.length() as String + } +} + +abstract class AkkaHttpServerInstrumentationSyncTest extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttpTestWebServer.BindAndHandleSync()) + } + + @Override + String expectedOperationName() { + return operation() + } + + // we test body endpoints only on the async tests + @Override + boolean testRequestBody() { + false + } + + @Override + boolean testBodyMultipart() { + false + } + + @Override + boolean testBodyJson() { + false + } + + @Override + boolean testBodyUrlencoded() { + false + } +} + +class AkkaHttpServerInstrumentationSyncV0Test extends AkkaHttpServerInstrumentationSyncTest { + @Override + int version() { + return 0 + } + + @Override + String service() { + return null + } + + @Override + String operation() { + return "akka-http.request" + } +} + +class AkkaHttpServerInstrumentationSyncV1ForkedTest extends AkkaHttpServerInstrumentationSyncTest implements TestingGenericHttpNamingConventions.ServerV1 { +} + +class AkkaHttpServerInstrumentationAsyncTest extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttpTestWebServer.BindAndHandleAsync()) + } +} + +class AkkaHttpServerInstrumentationBindAndHandleTest extends AkkaHttpServerInstrumentationTest { + + @Override + HttpServer server() { + AkkaHttpTestWebServer server = new AkkaHttpTestWebServer(AkkaHttpTestWebServer.BindAndHandle()) + server + } + + @Override + boolean redirectHasBody() { + return true + } + + @Override + boolean testBodyMultipart() { + true + } + + @Override + boolean testBodyUrlencoded() { + true + } +} + +class AkkaHttpServerInstrumentationBindAndHandleAsyncWithRouteAsyncHandlerTest extends AkkaHttpServerInstrumentationTest { + String akkaHttpVersion + + @Override + HttpServer server() { + AkkaHttpTestWebServer server = new AkkaHttpTestWebServer(AkkaHttpTestWebServer.BindAndHandleAsyncWithRouteAsyncHandler()) + akkaHttpVersion = server.system().settings().config().getString('akka.http.version') + server + } + + @Override + boolean redirectHasBody() { + return true + } + + @Override + boolean testBodyMultipart() { + true + } + + @Override + boolean testBodyUrlencoded() { + true + } +} + +class AkkaHttpServerInstrumentationAsyncHttp2Test extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttpTestWebServer.BindAndHandleAsyncHttp2()) + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/resources/application.conf b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/resources/application.conf new file mode 100644 index 00000000000..7e7db624120 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/resources/application.conf @@ -0,0 +1,6 @@ +akka.http { + host-connection-pool { + // Limit maximum http backoff for tests + max-connection-backoff = 100ms + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttp102TestWebServer.scala b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttp102TestWebServer.scala new file mode 100644 index 00000000000..da4f15e839d --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttp102TestWebServer.scala @@ -0,0 +1,67 @@ +import AkkaHttpTestWebServer.Binder +import akka.actor.ActorSystem +import akka.http.scaladsl.Http +import akka.http.scaladsl.Http.ServerBinding +import akka.http.scaladsl.server.Route +import akka.stream.Materializer + +import scala.concurrent.Future + +object AkkaHttp102TestWebServer { + val ServerBuilderBindFlow: Binder = new Binder { + override def name: String = "server-builder-bind-flow" + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http() + .newServerAt("localhost", port) + .withMaterializer(materializer) + .bindFlow(AkkaHttpTestWebServer.route) + } + } + + val ServerBuilderBind: Binder = new Binder { + override def name: String = "server-builder-bind" + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http() + .newServerAt("localhost", port) + .withMaterializer(materializer) + .bind(AkkaHttpTestWebServer.asyncHandler) + } + } + + val ServerBuilderBindSync: Binder = new Binder { + override def name: String = "server-builder-bind-sync" + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http() + .newServerAt("localhost", port) + .withMaterializer(materializer) + .bindSync(AkkaHttpTestWebServer.syncHandler) + } + } + + val ServerBuilderBindHttp2: Binder = new Binder { + override def name: String = "server-builder-bind-http2" + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http() + .newServerAt("localhost", port) + .withMaterializer(materializer) + .adaptSettings(AkkaHttpTestWebServer.enableHttp2) + .bind(AkkaHttpTestWebServer.asyncHandler) + } + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttpTestWebServer.scala b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttpTestWebServer.scala new file mode 100644 index 00000000000..af0bc91b428 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttpTestWebServer.scala @@ -0,0 +1,503 @@ +import AkkaHttpTestWebServer.Binder +import akka.actor.ActorSystem +import akka.http.javadsl.marshallers.jackson.Jackson +import akka.http.scaladsl.Http.ServerBinding +import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport +import akka.http.scaladsl.model.HttpEntity.apply +import akka.http.scaladsl.model.HttpMethods.{GET, POST} +import akka.http.scaladsl.model.Multipart.FormData +import akka.http.scaladsl.model.Multipart.FormData.BodyPart +import akka.http.scaladsl.model._ +import akka.http.scaladsl.model.headers.RawHeader +import akka.http.scaladsl.server.Directives._ +import akka.http.scaladsl.server._ +import akka.http.scaladsl.settings.ServerSettings +import akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers.defaultUrlEncodedFormDataUnmarshaller +import akka.http.scaladsl.unmarshalling.Unmarshaller.messageUnmarshallerFromEntityUnmarshaller +import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, MultipartUnmarshallers, Unmarshal, Unmarshaller} +import akka.http.scaladsl.util.FastFuture.EnhancedFuture +import akka.http.scaladsl.{Http, model} +import akka.stream.{ActorMaterializer, Materializer} +import com.typesafe.config.{Config, ConfigFactory, ConfigValueFactory} +import datadog.appsec.api.blocking.{Blocking, BlockingException} +import datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint._ +import datadog.trace.agent.test.base.{HttpServer, HttpServerTest} +import datadog.trace.agent.test.utils.TraceUtils +import datadog.trace.bootstrap.instrumentation.api.AgentTracer +import datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan +import groovy.lang.Closure +import spray.json.{JsObject, JsString, JsValue, RootJsonFormat, deserializationError} + +import java.net.URI +import scala.concurrent.duration._ +import scala.concurrent.{Await, ExecutionContext, Future} +import scala.language.postfixOps +import scala.util.control.NonFatal + +class AkkaHttpTestWebServer(binder: Binder) extends HttpServer { + implicit val system: ActorSystem = { + val name = s"${binder.name}" + binder.config match { + case None => ActorSystem(name) + case Some(config) => ActorSystem(name, config) + } + } + implicit val materializer: ActorMaterializer = ActorMaterializer() + private var port: Int = 0 + private var portBinding: Future[ServerBinding] = _ + + override def start(): Unit = { + portBinding = Await.ready(binder.bind(0), 10 seconds) + port = portBinding.value.get.get.localAddress.getPort + } + + override def stop(): Unit = { + import materializer.executionContext + portBinding + .flatMap(_.unbind()) + .onComplete(_ => system.terminate()) + } + + override def address(): URI = { + new URI("http://localhost:" + port + "/") + } +} + +object AkkaHttpTestWebServer { + + trait Binder { + def name: String + + def config: Option[Config] = None + + def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] + } + + val BindAndHandle: Binder = new Binder { + override def name: String = "bind-and-handle" + + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http().bindAndHandle(route, "localhost", port) + } + } + + val BindAndHandleAsyncWithRouteAsyncHandler: Binder = new Binder { + override def name: String = "bind-and-handle-async-with-route-async-handler" + + override def config: Option[Config] = Some( + ConfigFactory.load() + .withValue("akka.http.server.request-timeout", ConfigValueFactory.fromAnyRef("300 s")) + .withValue("akka.http.server.idle-timeout", ConfigValueFactory.fromAnyRef("300 s")) + ) + + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http().bindAndHandleAsync(Route.asyncHandler(route), "localhost", port) + } + } + + val BindAndHandleSync: Binder = new Binder { + override def name: String = "bind-and-handle-sync" + + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + Http().bindAndHandleSync(syncHandler, "localhost", port) + } + } + + val BindAndHandleAsync: Binder = new Binder { + override def name: String = "bind-and-handle-async" + + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http().bindAndHandleAsync(asyncHandler, "localhost", port) + } + } + + val BindAndHandleAsyncHttp2: Binder = new Binder { + override def name: String = "bind-and-handle-async-http2" + + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + val serverSettings = enableHttp2(ServerSettings(system)) + Http().bindAndHandleAsync( + asyncHandler, + "localhost", + port, + settings = serverSettings + ) + } + } + + // This part defines the routes using the Scala routing DSL + // ---------------------------------------------------------------------- // + private val exceptionHandler = ExceptionHandler { + case e : Exception if !e.isInstanceOf[BlockingException] => + val span = activeSpan() + TraceUtils.handleException(span, e) + complete( + HttpResponse(status = EXCEPTION.getStatus, entity = e.getMessage) + ) + } + + // Since the akka-http route DSL produces a Route that is evaluated for every + // incoming request, we need to wrap the HttpServerTest.controller call and exception + // handling in a custom Directive + private def withController: Directive0 = Directive[Unit] { inner => ctx => + def handleException: PartialFunction[Throwable, Future[RouteResult]] = + exceptionHandler andThen (_(ctx.withAcceptAll)) + + val uri = ctx.request.uri + val endpoint = HttpServerTest.ServerEndpoint.forPath(uri.path.toString()) + HttpServerTest.controller( + endpoint, + new Closure[Future[RouteResult]](()) { + def doCall(): Future[RouteResult] = { + try inner(())(ctx).fast + .recoverWith(handleException)(ctx.executionContext) + catch { + case NonFatal(e) => + handleException + .applyOrElse[Throwable, Future[RouteResult]](e, throw _) + } + } + } + ) + } + + private val defaultHeader = + RawHeader(HttpServerTest.getIG_RESPONSE_HEADER, HttpServerTest.getIG_RESPONSE_HEADER_VALUE) + + // force a rejection due to BlockingException to throw so that the error + // can be recorded in the span + private val blockingRejectionHandler: RejectionHandler = RejectionHandler.newBuilder() + .handle({ + case MalformedRequestContentRejection(_, cause: BlockingException) => + throw cause + }).result() + + def route(implicit ec: ExecutionContext): Route = withController { + handleRejections(blockingRejectionHandler) { + respondWithDefaultHeader(defaultHeader) { + get { + path(SUCCESS.relativePath) { + complete( + HttpResponse(status = SUCCESS.getStatus, entity = SUCCESS.getBody) + ) + } ~ path(FORWARDED.relativePath) { + headerValueByName("x-forwarded-for") { address => + complete( + HttpResponse(status = FORWARDED.getStatus, entity = address) + ) + } + } ~ path( + QUERY_PARAM.relativePath | QUERY_ENCODED_BOTH.relativePath | QUERY_ENCODED_QUERY.relativePath + ) { + parameter("some") { query => + complete( + HttpResponse( + status = QUERY_PARAM.getStatus, + entity = s"some=$query" + ) + ) + } + } ~ path(REDIRECT.relativePath) { + redirect(Uri(REDIRECT.getBody), StatusCodes.Found) + } ~ path(USER_BLOCK.relativePath) { + Blocking.forUser("user-to-block").blockIfMatch() + complete( + HttpResponse(status = SUCCESS.getStatus, entity = "Should not be reached") + ) + } ~ path(ERROR.relativePath) { + complete(HttpResponse(status = ERROR.getStatus, entity = ERROR.getBody)) + } ~ path(EXCEPTION.relativePath) { + throw new Exception(EXCEPTION.getBody) + } ~ pathPrefix("injected-id") { + path("ping" / IntNumber) { id => + val traceId = AgentTracer.activeSpan().getTraceId + complete(s"pong $id -> $traceId") + } ~ path("fing" / IntNumber) { id => + // force the response to happen on another thread or in another context + onSuccess(Future { + Thread.sleep(10) + id + }) { fid => + val traceId = AgentTracer.activeSpan().getTraceId + complete(s"fong $fid -> $traceId") + } + } + } ~ path(USER_BLOCK.relativePath()) { + Blocking.forUser("user-to-block").blockIfMatch() + complete(HttpResponse(status = 200, entity = "should never be reached")) + } + } ~ post { + path(CREATED.relativePath()) { + entity(as[String]) { s => + complete( + HttpResponse( + status = CREATED.getStatus, + entity = s"created: $s" + ) + ) + } + } ~ + path(BODY_URLENCODED.relativePath()) { + formFieldMultiMap { m => + complete( + HttpResponse( + status = BODY_URLENCODED.getStatus, + entity = m.toStringAsGroovy + ) + ) + } + } ~ + path(BODY_JSON.relativePath()) { + parameter(Symbol("variant") ?) { + case Some("spray") => + entity(Unmarshaller.messageUnmarshallerFromEntityUnmarshaller(sprayMapUnmarshaller)) { m => + complete( + HttpResponse( + status = BODY_JSON.getStatus, + entity = SprayMapFormat.write(m).compactPrint + ) + ) + } + case _ => // jackson + entity(Unmarshaller.messageUnmarshallerFromEntityUnmarshaller(jacksonMapUnmarshaller)) { m => + complete( + HttpResponse( + status = BODY_JSON.getStatus, + entity = SprayMapFormat.write(m).compactPrint + ) + ) + } + } + } ~ + path(BODY_MULTIPART.relativePath()) { + parameter(Symbol("variant") ?) { + case Some("strictUnmarshaller") => + entity(as[Multipart.FormData.Strict]) { formData => + val m = formData.strictParts + .groupBy(_.name) + .mapValues( + _.map((bp: BodyPart.Strict) => + bp.entity.data.utf8String + ).toList + ) + complete( + HttpResponse( + status = BODY_MULTIPART.getStatus, + entity = m.toStringAsGroovy + ) + ) + } + case _ => + formFieldMultiMap { m => + complete( + HttpResponse( + status = BODY_MULTIPART.getStatus, + entity = m.toStringAsGroovy + ) + ) + } + } + } + } + } + } + } + + // This part defines the sync and async handler functions + // ---------------------------------------------------------------------- // + + val syncHandler: HttpRequest => HttpResponse = { + case HttpRequest(GET, uri: Uri, _, _, _) => + val path = uri.path.toString() + val endpoint = HttpServerTest.ServerEndpoint.forPath(path) + HttpServerTest + .controller( + endpoint, + new Closure[HttpResponse](()) { + def doCall(): HttpResponse = { + val resp = HttpResponse(status = endpoint.getStatus) + endpoint match { + case SUCCESS => resp.withEntity(endpoint.getBody) + case FORWARDED => resp.withEntity(endpoint.getBody) // cheating + case QUERY_PARAM | QUERY_ENCODED_BOTH | QUERY_ENCODED_QUERY => + resp.withEntity(uri.queryString().orNull) + case REDIRECT => + resp.withHeaders(headers.Location(endpoint.getBody)) + case ERROR => resp.withEntity(endpoint.getBody) + case EXCEPTION => throw new Exception(endpoint.getBody) + case USER_BLOCK => { + Blocking.forUser("user-to-block").blockIfMatch() + // should never be output: + resp.withEntity("should never be reached") + } + case _ => + if (path.startsWith("/injected-id/")) { + val groups = path.split('/') + if (groups.length == 4) { // The path starts with a / and has 3 segments + val traceId = AgentTracer.activeSpan().getTraceId + val id = groups(3).toInt + groups(2) match { + case "ping" => + return HttpResponse(entity = s"pong $id -> $traceId") + case "fing" => + return HttpResponse(entity = s"fong $id -> $traceId") + case _ => + } + } + } + HttpResponse(status = NOT_FOUND.getStatus) + .withEntity(NOT_FOUND.getBody) + } + } + } + ) + .withDefaultHeaders(defaultHeader) + } + + def asyncHandler( + implicit ec: ExecutionContext, + mat: Materializer + ): HttpRequest => Future[HttpResponse] = { + case request@HttpRequest(POST, uri, _, entity, _) => + val path = request.uri.path.toString + val endpoint = HttpServerTest.ServerEndpoint.forPath(path) + + endpoint match { + case CREATED => + Unmarshal(entity).to[String].map { bodyStr => + HttpResponse(status = CREATED.getStatus) + .withEntity(s"${CREATED.getBody}: $bodyStr") + } + case BODY_MULTIPART => + uri.query().get("variant") match { + case Some("strictUnmarshaller") => + val eventualStrict = Unmarshal(entity).to[FormData.Strict] + eventualStrict.map { s => + HttpResponse(status = BODY_MULTIPART.getStatus) + .withEntity(s.toStringAsGroovy) + } + case _ => + val fd = Unmarshal(entity).to[Multipart.FormData] + val eventualStrict = fd.flatMap(_.toStrict(500 millis)) + eventualStrict.map { s => + HttpResponse(status = BODY_MULTIPART.getStatus) + .withEntity(s.toStringAsGroovy) + } + } + case BODY_URLENCODED => + val eventualData = Unmarshal(entity).to[model.FormData] + eventualData.map { d => + HttpResponse(status = BODY_URLENCODED.getStatus) + .withEntity(d.toStringAsGroovy) + } + case BODY_JSON => + val unmarshaller = uri.query().get("variant") match { + case Some("spray") => sprayMapUnmarshaller + case _ => jacksonMapUnmarshaller + } + val eventualData = Unmarshal(entity).to[Map[String, String]](unmarshaller, ec, mat) + eventualData.map { d => + HttpResponse(status = BODY_URLENCODED.getStatus) + .withEntity(SprayMapFormat.write(d).compactPrint) + } + case _ => Future.successful(HttpResponse(404)) + } + case request => Future { + syncHandler(request) + } + } + + def enableHttp2(serverSettings: ServerSettings): ServerSettings = { + val previewServerSettings = + serverSettings.previewServerSettings.withEnableHttp2(true) + serverSettings.withPreviewServerSettings(previewServerSettings) + } + + implicit class MapExtensions[A](m: Iterable[(String, A)]) { + def toStringAsGroovy: String = { + def valueToString(value: Object) : String = value match { + case seq: Seq[_] => seq.map(x => valueToString(x.asInstanceOf[Object])).mkString("[", ",", "]") + case other => other.toString + } + + m.map { case (key, value) => s"$key:${valueToString(value.asInstanceOf[Object])}" } + .mkString("[", ",", "]") + } + } + + implicit class MultipartFormDataStrictExtensions(strict: Multipart.FormData.Strict) { + def toStringAsGroovy: String = + strict.strictParts + .groupBy(_.name) + .mapValues( + _.map((bp: BodyPart.Strict) => + bp.entity.data.utf8String + ).toList + ).toStringAsGroovy + } + + implicit class FormDataExtensions(formData: model.FormData) { + def toStringAsGroovy: String = formData.fields.toMultiMap.toStringAsGroovy + } + + implicit def strictMultipartFormDataUnmarshaller: FromEntityUnmarshaller[Multipart.FormData.Strict] = { + val toStrictUnmarshaller = Unmarshaller.withMaterializer[HttpEntity, HttpEntity.Strict] { + implicit ec => + implicit mat => + entity => + entity.toStrict(1000.millis) + } + val toFormDataUnmarshaller = MultipartUnmarshallers.multipartFormDataUnmarshaller + val downcastUnmarshaller = Unmarshaller.strict[Multipart.FormData, Multipart.FormData.Strict] { + case strict: Multipart.FormData.Strict => strict + case _ => throw new RuntimeException("Expected Strict form data at this point") + } + + toStrictUnmarshaller.andThen(toFormDataUnmarshaller).andThen(downcastUnmarshaller) + } + + val jacksonMapUnmarshaller: FromEntityUnmarshaller[Map[String,String]] = { + Jackson.unmarshaller(classOf[java.util.Map[String, String]]).asScala.map( + javaMap => { + import scala.collection.JavaConverters._ + javaMap.asScala.toMap + } + ) + } + + object SprayMapFormat extends RootJsonFormat[Map[String, String]] { + def write(map: Map[String, String]): JsObject = JsObject(map.mapValues(JsString(_)).toMap) + + def read(value: JsValue): Map[String, String] = value match { + case JsObject(fields) => fields.collect { + case (k, JsString(v)) => k -> v + } + case _ => deserializationError("Expected a JSON object") + } + } + + val sprayMapUnmarshaller: FromEntityUnmarshaller[Map[String, String]] = + SprayJsonSupport.sprayJsonUnmarshaller[Map[String, String]](SprayMapFormat) +} diff --git a/dd-java-agent/instrumentation/akka-http/build.gradle b/dd-java-agent/instrumentation/akka-http/build.gradle new file mode 100644 index 00000000000..5e69c67bd78 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/build.gradle @@ -0,0 +1 @@ +apply from: "$rootDir/gradle/java.gradle" diff --git a/dd-java-agent/instrumentation/play-2.4/build.gradle b/dd-java-agent/instrumentation/play-2.4/build.gradle index 3abd49b8e70..b2ab0d7cd28 100644 --- a/dd-java-agent/instrumentation/play-2.4/build.gradle +++ b/dd-java-agent/instrumentation/play-2.4/build.gradle @@ -77,7 +77,7 @@ dependencies { testRuntimeOnly project(':dd-java-agent:instrumentation:netty-4.0') testRuntimeOnly project(':dd-java-agent:instrumentation:netty-4.1') - testRuntimeOnly project(':dd-java-agent:instrumentation:akka-http-10.0') + testRuntimeOnly project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') testRuntimeOnly project(':dd-java-agent:instrumentation:akka-concurrent') testRuntimeOnly project(':dd-java-agent:instrumentation:akka-init') testRuntimeOnly project(':dd-java-agent:instrumentation:scala-concurrent') diff --git a/dd-java-agent/instrumentation/play-2.6/build.gradle b/dd-java-agent/instrumentation/play-2.6/build.gradle index 09d8571e64f..a13487d0063 100644 --- a/dd-java-agent/instrumentation/play-2.6/build.gradle +++ b/dd-java-agent/instrumentation/play-2.6/build.gradle @@ -104,7 +104,7 @@ dependencies { testRuntimeOnly project(':dd-java-agent:instrumentation:netty-4.0') testRuntimeOnly project(':dd-java-agent:instrumentation:netty-4.1') - testRuntimeOnly project(':dd-java-agent:instrumentation:akka-http-10.0') + testRuntimeOnly project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') testRuntimeOnly project(':dd-java-agent:instrumentation:akka-concurrent') testRuntimeOnly project(':dd-java-agent:instrumentation:akka-init') testRuntimeOnly project(':dd-java-agent:instrumentation:scala-concurrent') diff --git a/dd-java-agent/instrumentation/play-ws-1/build.gradle b/dd-java-agent/instrumentation/play-ws-1/build.gradle index da201cc0f5b..e1dc92d0a5d 100644 --- a/dd-java-agent/instrumentation/play-ws-1/build.gradle +++ b/dd-java-agent/instrumentation/play-ws-1/build.gradle @@ -33,7 +33,7 @@ dependencies { // These are to ensure cross compatibility testImplementation project(':dd-java-agent:instrumentation:netty-4.0') testImplementation project(':dd-java-agent:instrumentation:netty-4.1') - testImplementation project(':dd-java-agent:instrumentation:akka-http-10.0') + testImplementation project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') testImplementation project(':dd-java-agent:instrumentation:akka-concurrent') testImplementation project(':dd-java-agent:instrumentation:akka-init') testImplementation project(':dd-java-agent:instrumentation:scala-concurrent') diff --git a/dd-java-agent/instrumentation/play-ws-2.1/build.gradle b/dd-java-agent/instrumentation/play-ws-2.1/build.gradle index 2efa8ec9bbc..9181efa9426 100644 --- a/dd-java-agent/instrumentation/play-ws-2.1/build.gradle +++ b/dd-java-agent/instrumentation/play-ws-2.1/build.gradle @@ -39,7 +39,7 @@ dependencies { // These are to ensure cross compatibility testImplementation project(':dd-java-agent:instrumentation:netty-4.0') testImplementation project(':dd-java-agent:instrumentation:netty-4.1') - testImplementation project(':dd-java-agent:instrumentation:akka-http-10.0') + testImplementation project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') testImplementation project(':dd-java-agent:instrumentation:akka-concurrent') testImplementation project(':dd-java-agent:instrumentation:akka-init') testImplementation project(':dd-java-agent:instrumentation:scala-concurrent') diff --git a/dd-java-agent/instrumentation/play-ws-2/build.gradle b/dd-java-agent/instrumentation/play-ws-2/build.gradle index 3d7a3db1f1a..3591769e47c 100644 --- a/dd-java-agent/instrumentation/play-ws-2/build.gradle +++ b/dd-java-agent/instrumentation/play-ws-2/build.gradle @@ -38,7 +38,7 @@ dependencies { // These are to ensure cross compatibility testImplementation project(':dd-java-agent:instrumentation:netty-4.0') testImplementation project(':dd-java-agent:instrumentation:netty-4.1') - testImplementation project(':dd-java-agent:instrumentation:akka-http-10.0') + testImplementation project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') testImplementation project(':dd-java-agent:instrumentation:akka-concurrent') testImplementation project(':dd-java-agent:instrumentation:akka-init') testImplementation project(':dd-java-agent:instrumentation:scala-concurrent') diff --git a/settings.gradle b/settings.gradle index 130d0035043..a48738f63c6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -168,8 +168,10 @@ include ':dd-smoke-tests:iast-util' // instrumentation: include ':dd-java-agent:instrumentation:aerospike-4' include ':dd-java-agent:instrumentation:akka-concurrent' -include ':dd-java-agent:instrumentation:akka-http-10.0' -include ':dd-java-agent:instrumentation:akka-http-10.2-iast' +include ':dd-java-agent:instrumentation:akka-http' +include ':dd-java-agent:instrumentation:akka-http:akka-http-10.0' +include ':dd-java-agent:instrumentation:akka-http:akka-http-10.2-iast' +include ':dd-java-agent:instrumentation:akka-http:akka-http-10.6' include ':dd-java-agent:instrumentation:akka-init' include ':dd-java-agent:instrumentation:apache-httpasyncclient-4' include ':dd-java-agent:instrumentation:apache-httpclient-4'