Skip to content

Commit f7d45ac

Browse files
committed
Update tests with new attrs
1 parent 5c57154 commit f7d45ac

File tree

2 files changed

+71
-4
lines changed

2 files changed

+71
-4
lines changed

dd-java-agent/instrumentation/spark/spark-common/src/main/java/datadog/trace/instrumentation/spark/SparkLauncherAdvice.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ public class SparkLauncherAdvice {
1717

1818
private static final Logger log = LoggerFactory.getLogger(SparkLauncherAdvice.class);
1919

20+
// Same default pattern as spark.redaction.regex in Spark source
21+
private static final Pattern CONF_REDACTION_PATTERN =
22+
Pattern.compile("(?i)secret|password|token|access.key|api.key");
23+
2024
/** The launcher span, accessible from SparkExitAdvice via reflection. */
2125
public static volatile AgentSpan launcherSpan;
2226

@@ -50,13 +54,11 @@ private static void setLauncherConfigTags(AgentSpan span, Object launcher) {
5054
@SuppressWarnings("unchecked")
5155
Map<String, String> conf = (Map<String, String>) confField.get(builder);
5256
if (conf != null) {
53-
Pattern redactionPattern =
54-
Pattern.compile("(?i)secret|password|token|access.key|api.key");
5557
for (Map.Entry<String, String> entry : conf.entrySet()) {
5658
if (SparkConfAllowList.canCaptureJobParameter(entry.getKey())) {
5759
String value = entry.getValue();
58-
if (redactionPattern.matcher(entry.getKey()).find()
59-
|| redactionPattern.matcher(value).find()) {
60+
if (CONF_REDACTION_PATTERN.matcher(entry.getKey()).find()
61+
|| CONF_REDACTION_PATTERN.matcher(value).find()) {
6062
value = "[redacted]";
6163
}
6264
span.setTag("config." + entry.getKey().replace('.', '_'), value);

dd-java-agent/instrumentation/spark/spark-common/src/test/groovy/datadog/trace/instrumentation/spark/SparkLauncherTest.groovy

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,74 @@ import datadog.trace.agent.test.InstrumentationSpecification
44
import datadog.trace.api.sampling.PrioritySampling
55
import datadog.trace.api.sampling.SamplingMechanism
66
import datadog.trace.bootstrap.instrumentation.api.AgentTracer
7+
import org.apache.spark.launcher.SparkLauncher
78

89
class SparkLauncherTest extends InstrumentationSpecification {
910

11+
def "createLauncherSpan extracts config tags from SparkLauncher"() {
12+
setup:
13+
SparkLauncherAdvice.launcherSpan = null
14+
15+
when:
16+
def launcher = new SparkLauncher()
17+
.setMaster("yarn")
18+
.setDeployMode("cluster")
19+
.setAppName("test-app")
20+
.setMainClass("com.example.Main")
21+
.setAppResource("/path/to/app.jar")
22+
.setConf("spark.executor.memory", "4g")
23+
.setConf("spark.executor.instances", "10")
24+
SparkLauncherAdvice.createLauncherSpan("SparkLauncher.startApplication", launcher)
25+
SparkLauncherAdvice.finishLauncherSpan(0)
26+
27+
then:
28+
assertTraces(1) {
29+
trace(1) {
30+
span {
31+
operationName "spark.launcher.launch"
32+
spanType "spark"
33+
resourceName "SparkLauncher.startApplication"
34+
errored false
35+
assert span.tags["master"] == "yarn"
36+
assert span.tags["deploy_mode"] == "cluster"
37+
assert span.tags["application_name"] == "test-app"
38+
assert span.tags["main_class"] == "com.example.Main"
39+
assert span.tags["app_resource"] == "/path/to/app.jar"
40+
assert span.tags["config.spark_executor_memory"] == "4g"
41+
assert span.tags["config.spark_executor_instances"] == "10"
42+
}
43+
}
44+
}
45+
}
46+
47+
def "createLauncherSpan redacts sensitive conf values"() {
48+
setup:
49+
SparkLauncherAdvice.launcherSpan = null
50+
51+
when:
52+
def launcher = new SparkLauncher()
53+
// spark.app.name is allowlisted; its value contains "secret" so should be redacted
54+
.setConf("spark.app.name", "my-secret-app")
55+
// spark.master is allowlisted; its value is harmless so should pass through
56+
.setConf("spark.master", "yarn")
57+
SparkLauncherAdvice.createLauncherSpan("SparkLauncher.startApplication", launcher)
58+
SparkLauncherAdvice.finishLauncherSpan(0)
59+
60+
then:
61+
assertTraces(1) {
62+
trace(1) {
63+
span {
64+
operationName "spark.launcher.launch"
65+
spanType "spark"
66+
resourceName "SparkLauncher.startApplication"
67+
errored false
68+
assert span.tags["config.spark_app_name"] == "[redacted]"
69+
assert span.tags["config.spark_master"] == "yarn"
70+
}
71+
}
72+
}
73+
}
74+
1075
def "generate spark.launcher span from startApplication"() {
1176
setup:
1277
SparkLauncherAdvice.launcherSpan = null

0 commit comments

Comments
 (0)