Skip to content

Commit d7e67d1

Browse files
authored
Merge branch 'master' into sarahchen6/fix-latest-dep-tests
2 parents 297ae9b + cd456d2 commit d7e67d1

File tree

17 files changed

+335
-82
lines changed

17 files changed

+335
-82
lines changed

buildSrc/src/main/kotlin/datadog/gradle/plugin/config/ConfigInversionLinter.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ private fun registerLogEnvVarUsages(target: Project, extension: SupportedTracerC
8282
val javaFiles = target.fileTree(target.projectDir) {
8383
include("**/src/main/java/**/*.java")
8484
exclude("**/build/**", "**/dd-smoke-tests/**")
85+
// Undertow uses DD_UNDERTOW_CONTINUATION as a legacy key to store an AgentScope. It is not related to an environment variable
86+
exclude("dd-java-agent/instrumentation/undertow/src/main/java/datadog/trace/instrumentation/undertow/UndertowDecorator.java")
8587
}
8688
inputs.files(javaFiles)
8789
outputs.upToDateWhen { true }
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
package datadog.gradle.plugin.config
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.kotlin.dsl.property
5+
import org.gradle.api.model.ObjectFactory
6+
import org.gradle.api.tasks.Input
7+
import org.gradle.api.tasks.InputFile
8+
import org.gradle.api.tasks.OutputDirectory
9+
import org.gradle.api.tasks.TaskAction
10+
import com.fasterxml.jackson.core.type.TypeReference
11+
import com.fasterxml.jackson.databind.ObjectMapper
12+
import org.gradle.api.tasks.CacheableTask
13+
import org.gradle.api.tasks.PathSensitive
14+
import org.gradle.api.tasks.PathSensitivity
15+
import java.io.File
16+
import java.io.FileInputStream
17+
import java.io.PrintWriter
18+
import javax.inject.Inject
19+
20+
@CacheableTask
21+
abstract class ParseV2SupportedConfigurationsTask @Inject constructor(
22+
private val objects: ObjectFactory
23+
) : DefaultTask() {
24+
@InputFile
25+
@PathSensitive(PathSensitivity.NONE)
26+
val jsonFile = objects.fileProperty()
27+
28+
@get:OutputDirectory
29+
val destinationDirectory = objects.directoryProperty()
30+
31+
@Input
32+
val className = objects.property<String>()
33+
34+
@TaskAction
35+
fun generate() {
36+
val input = jsonFile.get().asFile
37+
val outputDir = destinationDirectory.get().asFile
38+
val finalClassName = className.get()
39+
outputDir.mkdirs()
40+
41+
// Read JSON (directly from the file, not classpath)
42+
val mapper = ObjectMapper()
43+
val fileData: Map<String, Any?> = FileInputStream(input).use { inStream ->
44+
mapper.readValue(inStream, object : TypeReference<Map<String, Any?>>() {})
45+
}
46+
47+
// Fetch top-level keys of JSON file
48+
@Suppress("UNCHECKED_CAST")
49+
val supportedRaw = fileData["supportedConfigurations"] as Map<String, List<Map<String, Any?>>>
50+
@Suppress("UNCHECKED_CAST")
51+
val deprecated = (fileData["deprecations"] as? Map<String, String>) ?: emptyMap()
52+
53+
// Parse supportedConfigurations key to into a V2 format
54+
val supported: Map<String, List<SupportedConfigurationItem>> = supportedRaw.mapValues { (_, configList) ->
55+
configList.map { configMap ->
56+
SupportedConfigurationItem(
57+
configMap["version"] as? String,
58+
configMap["type"] as? String,
59+
configMap["default"] as? String,
60+
(configMap["aliases"] as? List<String>) ?: emptyList(),
61+
(configMap["propertyKeys"] as? List<String>) ?: emptyList()
62+
)
63+
}
64+
}
65+
66+
// Generate top-level mapping from config -> list of aliases and reverse alias mapping from alias -> top-level config
67+
// Note: This top-level alias mapping will be deprecated once Config Registry is mature enough to understand which version of a config a customer is using
68+
val aliases: Map<String, List<String>> = supported.mapValues { (_, configList) ->
69+
configList.flatMap { it.aliases }.distinct()
70+
}
71+
72+
val aliasMapping = mutableMapOf<String, String>()
73+
for ((canonical, alist) in aliases) {
74+
for (alias in alist) aliasMapping[alias] = canonical
75+
}
76+
77+
val reversePropertyKeysMap: Map<String, String> = supported.flatMap { (canonical, configList) ->
78+
configList.flatMap { config ->
79+
config.propertyKeys.map { propertyKey -> propertyKey to canonical }
80+
}
81+
}.toMap()
82+
83+
// Build the output .java path from the fully-qualified class name
84+
val pkgName = finalClassName.substringBeforeLast('.', "")
85+
val pkgPath = pkgName.replace('.', File.separatorChar)
86+
val simpleName = finalClassName.substringAfterLast('.')
87+
val pkgDir = if (pkgPath.isEmpty()) outputDir else File(outputDir, pkgPath).also { it.mkdirs() }
88+
val generatedFile = File(pkgDir, "$simpleName.java").absolutePath
89+
90+
// Call your existing generator (same signature as in your Java code)
91+
generateJavaFile(
92+
generatedFile,
93+
simpleName,
94+
pkgName,
95+
supported,
96+
aliases,
97+
aliasMapping,
98+
deprecated,
99+
reversePropertyKeysMap
100+
)
101+
}
102+
103+
private fun generateJavaFile(
104+
outputPath: String,
105+
className: String,
106+
packageName: String,
107+
supported: Map<String, List<SupportedConfigurationItem>>,
108+
aliases: Map<String, List<String>>,
109+
aliasMapping: Map<String, String>,
110+
deprecated: Map<String, String>,
111+
reversePropertyKeysMap: Map<String, String>
112+
) {
113+
val outFile = File(outputPath)
114+
outFile.parentFile?.mkdirs()
115+
116+
PrintWriter(outFile).use { out ->
117+
out.println("package $packageName;")
118+
out.println()
119+
out.println("import java.util.*;")
120+
out.println()
121+
out.println("public final class $className {")
122+
out.println()
123+
out.println(" public static final Map<String, List<SupportedConfiguration>> SUPPORTED;")
124+
out.println()
125+
out.println(" public static final Map<String, List<String>> ALIASES;")
126+
out.println()
127+
out.println(" public static final Map<String, String> ALIAS_MAPPING;")
128+
out.println()
129+
out.println(" public static final Map<String, String> DEPRECATED;")
130+
out.println()
131+
out.println(" public static final Map<String, String> REVERSE_PROPERTY_KEYS_MAP;")
132+
out.println()
133+
out.println(" static {")
134+
out.println()
135+
136+
// SUPPORTED
137+
out.println(" Map<String, List<SupportedConfiguration>> supportedMap = new HashMap<>();")
138+
for ((key, configList) in supported.toSortedMap()) {
139+
out.print(" supportedMap.put(\"${esc(key)}\", Collections.unmodifiableList(Arrays.asList(")
140+
val configIter = configList.iterator()
141+
while (configIter.hasNext()) {
142+
val config = configIter.next()
143+
out.print("new SupportedConfiguration(")
144+
out.print("${escNullableString(config.version)}, ")
145+
out.print("${escNullableString(config.type)}, ")
146+
out.print("${escNullableString(config.default)}, ")
147+
out.print("Arrays.asList(${quoteList(config.aliases)}), ")
148+
out.print("Arrays.asList(${quoteList(config.propertyKeys)})")
149+
out.print(")")
150+
if (configIter.hasNext()) out.print(", ")
151+
}
152+
out.println(")));")
153+
}
154+
out.println(" SUPPORTED = Collections.unmodifiableMap(supportedMap);")
155+
out.println()
156+
157+
// ALIASES
158+
out.println(" // Note: This top-level alias mapping will be deprecated once Config Registry is mature enough to understand which version of a config a customer is using")
159+
out.println(" Map<String, List<String>> aliasesMap = new HashMap<>();")
160+
for ((canonical, list) in aliases.toSortedMap()) {
161+
out.printf(
162+
" aliasesMap.put(\"%s\", Collections.unmodifiableList(Arrays.asList(%s)));\n",
163+
esc(canonical),
164+
quoteList(list)
165+
)
166+
}
167+
out.println(" ALIASES = Collections.unmodifiableMap(aliasesMap);")
168+
out.println()
169+
170+
// ALIAS_MAPPING
171+
out.println(" Map<String, String> aliasMappingMap = new HashMap<>();")
172+
for ((alias, target) in aliasMapping.toSortedMap()) {
173+
out.printf(" aliasMappingMap.put(\"%s\", \"%s\");\n", esc(alias), esc(target))
174+
}
175+
out.println(" ALIAS_MAPPING = Collections.unmodifiableMap(aliasMappingMap);")
176+
out.println()
177+
178+
// DEPRECATED
179+
out.println(" Map<String, String> deprecatedMap = new HashMap<>();")
180+
for ((oldKey, note) in deprecated.toSortedMap()) {
181+
out.printf(" deprecatedMap.put(\"%s\", \"%s\");\n", esc(oldKey), esc(note))
182+
}
183+
out.println(" DEPRECATED = Collections.unmodifiableMap(deprecatedMap);")
184+
out.println()
185+
186+
// REVERSE_PROPERTY_KEYS_MAP
187+
out.println(" Map<String, String> reversePropertyKeysMapping = new HashMap<>();")
188+
for ((propertyKey, config) in reversePropertyKeysMap.toSortedMap()) {
189+
out.printf(" reversePropertyKeysMapping.put(\"%s\", \"%s\");\n", esc(propertyKey), esc(config))
190+
}
191+
out.println(" REVERSE_PROPERTY_KEYS_MAP = Collections.unmodifiableMap(reversePropertyKeysMapping);")
192+
out.println()
193+
194+
out.println(" }")
195+
out.println("}")
196+
}
197+
}
198+
199+
private fun quoteList(list: List<String>): String =
200+
list.joinToString(", ") { "\"${esc(it)}\"" }
201+
202+
private fun esc(s: String): String =
203+
s.replace("\\", "\\\\").replace("\"", "\\\"")
204+
205+
private fun escNullableString(s: String?): String =
206+
if (s == null) "null" else "\"${esc(s)}\""
207+
}
208+
209+
private data class SupportedConfigurationItem(
210+
val version: String?,
211+
val type: String?,
212+
val default: String?,
213+
val aliases: List<String>,
214+
val propertyKeys: List<String>
215+
)

buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ abstract class MuzzleTask @Inject constructor(
9898
// See https://github.com/gradle/gradle/issues/33987
9999
workerExecutor.processIsolation {
100100
forkOptions {
101+
// datadog.trace.agent.tooling.muzzle.MuzzleVersionScanPlugin needs reflective access to ClassLoader.findLoadedClass
102+
if(javaLauncher.metadata.languageVersion > JavaLanguageVersion.of(9)) {
103+
jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED")
104+
}
101105
executable(javaLauncher.executablePath)
102106
}
103107
}

dd-java-agent/instrumentation/undertow/src/main/java/datadog/trace/instrumentation/undertow/UndertowBlockingHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package datadog.trace.instrumentation.undertow;
22

3-
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DD_UNDERTOW_CONTINUATION;
3+
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DATADOG_UNDERTOW_CONTINUATION;
44

55
import datadog.appsec.api.blocking.BlockingContentType;
66
import datadog.trace.api.gateway.Flow;
@@ -117,7 +117,7 @@ private static void commitBlockingResponse(
117117
}
118118

119119
private static void markAsEffectivelyBlocked(HttpServerExchange xchg) {
120-
AgentScope.Continuation continuation = xchg.getAttachment(DD_UNDERTOW_CONTINUATION);
120+
AgentScope.Continuation continuation = xchg.getAttachment(DATADOG_UNDERTOW_CONTINUATION);
121121
if (continuation != null) {
122122
continuation.span().getRequestContext().getTraceSegment().effectivelyBlocked();
123123
}

dd-java-agent/instrumentation/undertow/src/main/java/datadog/trace/instrumentation/undertow/UndertowDecorator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class UndertowDecorator
2626
InstanceStore.of(AttachmentKey.class);
2727

2828
@SuppressWarnings("unchecked")
29-
public static final AttachmentKey<AgentScope.Continuation> DD_UNDERTOW_CONTINUATION =
29+
public static final AttachmentKey<AgentScope.Continuation> DATADOG_UNDERTOW_CONTINUATION =
3030
attachmentStore.putIfAbsent(
3131
"DD_UNDERTOW_CONTINUATION", () -> AttachmentKey.create(AgentScope.Continuation.class));
3232

dd-java-agent/instrumentation/undertow/undertow-2.0/src/main/java/datadog/trace/instrumentation/undertow/ExchangeEndSpanListener.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package datadog.trace.instrumentation.undertow;
22

33
import static datadog.trace.bootstrap.instrumentation.api.AgentSpan.fromContext;
4-
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DD_UNDERTOW_CONTINUATION;
4+
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DATADOG_UNDERTOW_CONTINUATION;
55
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DECORATE;
66

77
import datadog.context.Context;
@@ -18,7 +18,7 @@ private ExchangeEndSpanListener() {}
1818

1919
@Override
2020
public void exchangeEvent(HttpServerExchange exchange, NextListener nextListener) {
21-
AgentScope.Continuation continuation = exchange.getAttachment(DD_UNDERTOW_CONTINUATION);
21+
AgentScope.Continuation continuation = exchange.getAttachment(DATADOG_UNDERTOW_CONTINUATION);
2222
if (continuation == null) {
2323
return;
2424
}

dd-java-agent/instrumentation/undertow/undertow-2.0/src/main/java/datadog/trace/instrumentation/undertow/HandlerInstrumentation.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import static datadog.trace.bootstrap.instrumentation.api.Java8BytecodeBridge.spanFromContext;
66
import static datadog.trace.instrumentation.undertow.UndertowBlockingHandler.REQUEST_BLOCKING_DATA;
77
import static datadog.trace.instrumentation.undertow.UndertowBlockingHandler.TRACE_SEGMENT;
8-
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DD_UNDERTOW_CONTINUATION;
8+
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DATADOG_UNDERTOW_CONTINUATION;
99
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DECORATE;
1010
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
1111
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
@@ -87,7 +87,7 @@ public static void onEnter(
8787
}
8888
}
8989

90-
AgentScope.Continuation continuation = exchange.getAttachment(DD_UNDERTOW_CONTINUATION);
90+
AgentScope.Continuation continuation = exchange.getAttachment(DATADOG_UNDERTOW_CONTINUATION);
9191
if (continuation != null) {
9292
// not yet complete, not ready to do final activation of continuation
9393
scope = continuation.span().attach();
@@ -101,7 +101,7 @@ public static void onEnter(
101101
DECORATE.afterStart(span);
102102
DECORATE.onRequest(span, exchange, exchange, parentContext);
103103

104-
exchange.putAttachment(DD_UNDERTOW_CONTINUATION, captureSpan(span));
104+
exchange.putAttachment(DATADOG_UNDERTOW_CONTINUATION, captureSpan(span));
105105

106106
exchange.addExchangeCompleteListener(ExchangeEndSpanListener.INSTANCE);
107107

dd-java-agent/instrumentation/undertow/undertow-2.0/src/main/java/datadog/trace/instrumentation/undertow/HttpServerExchangeSenderInstrumentation.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package datadog.trace.instrumentation.undertow;
22

33
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
4-
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DD_UNDERTOW_CONTINUATION;
4+
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DATADOG_UNDERTOW_CONTINUATION;
55
import static net.bytebuddy.matcher.ElementMatchers.isPrivate;
66
import static net.bytebuddy.matcher.ElementMatchers.not;
77
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
@@ -62,7 +62,7 @@ static class GetResponseChannelAdvice {
6262
return false;
6363
}
6464

65-
AgentScope.Continuation continuation = xchg.getAttachment(DD_UNDERTOW_CONTINUATION);
65+
AgentScope.Continuation continuation = xchg.getAttachment(DATADOG_UNDERTOW_CONTINUATION);
6666
if (continuation == null) {
6767
return false;
6868
}

dd-java-agent/instrumentation/undertow/undertow-2.0/src/main/java/datadog/trace/instrumentation/undertow/ServletInstrumentation.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import static datadog.trace.bootstrap.instrumentation.api.InstrumentationTags.SERVLET_PATH;
66
import static datadog.trace.bootstrap.instrumentation.decorator.HttpServerDecorator.DD_CONTEXT_ATTRIBUTE;
77
import static datadog.trace.bootstrap.instrumentation.decorator.http.HttpResourceDecorator.HTTP_RESOURCE_DECORATOR;
8-
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DD_UNDERTOW_CONTINUATION;
8+
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DATADOG_UNDERTOW_CONTINUATION;
99
import static datadog.trace.instrumentation.undertow.UndertowDecorator.SERVLET_REQUEST;
1010
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
1111

@@ -64,7 +64,7 @@ public static class DispatchAdvice {
6464
public static void enter(
6565
@Advice.Argument(0) final HttpServerExchange exchange,
6666
@Advice.Argument(1) final ServletRequestContext servletRequestContext) {
67-
AgentScope.Continuation continuation = exchange.getAttachment(DD_UNDERTOW_CONTINUATION);
67+
AgentScope.Continuation continuation = exchange.getAttachment(DATADOG_UNDERTOW_CONTINUATION);
6868
if (continuation != null) {
6969
AgentSpan undertowSpan = continuation.span();
7070
ServletRequest request = servletRequestContext.getServletRequest();

dd-java-agent/instrumentation/undertow/undertow-2.2/src/main/java/datadog/trace/instrumentation/undertow/JakartaServletInstrumentation.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import static datadog.trace.bootstrap.instrumentation.api.InstrumentationTags.SERVLET_CONTEXT;
55
import static datadog.trace.bootstrap.instrumentation.api.InstrumentationTags.SERVLET_PATH;
66
import static datadog.trace.bootstrap.instrumentation.decorator.HttpServerDecorator.DD_CONTEXT_ATTRIBUTE;
7-
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DD_UNDERTOW_CONTINUATION;
7+
import static datadog.trace.instrumentation.undertow.UndertowDecorator.DATADOG_UNDERTOW_CONTINUATION;
88
import static datadog.trace.instrumentation.undertow.UndertowDecorator.SERVLET_REQUEST;
99
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
1010

@@ -56,7 +56,7 @@ public static class DispatchAdvice {
5656
public static void enter(
5757
@Advice.Argument(0) final HttpServerExchange exchange,
5858
@Advice.Argument(1) final ServletRequestContext servletRequestContext) {
59-
AgentScope.Continuation continuation = exchange.getAttachment(DD_UNDERTOW_CONTINUATION);
59+
AgentScope.Continuation continuation = exchange.getAttachment(DATADOG_UNDERTOW_CONTINUATION);
6060
if (continuation != null) {
6161
AgentSpan undertowSpan = continuation.span();
6262
ServletRequest request = servletRequestContext.getServletRequest();

0 commit comments

Comments
 (0)