|
| 1 | +import static org.openjdk.jmc.common.item.Attribute.attr |
| 2 | +import static org.openjdk.jmc.common.unit.UnitLookup.PLAIN_TEXT |
| 3 | + |
1 | 4 | import datadog.smoketest.AbstractServerSmokeTest |
2 | 5 | import datadog.trace.agent.test.utils.PortUtils |
3 | 6 | import okhttp3.Request |
| 7 | +import org.openjdk.jmc.common.item.IAttribute |
| 8 | +import org.openjdk.jmc.common.item.IItem |
4 | 9 | import org.openjdk.jmc.common.item.IItemCollection |
| 10 | +import org.openjdk.jmc.common.item.IItemIterable |
| 11 | +import org.openjdk.jmc.common.item.IMemberAccessor |
5 | 12 | import org.openjdk.jmc.common.item.ItemFilters |
6 | 13 | import org.openjdk.jmc.flightrecorder.internal.InvalidJfrFileException |
7 | 14 | import spock.lang.Shared |
@@ -44,6 +51,8 @@ class SpringBootNativeInstrumentationTest extends AbstractServerSmokeTest { |
44 | 51 | // enable improved trace.annotation span names |
45 | 52 | '-Ddd.trace.annotations.legacy.tracing.enabled=false', |
46 | 53 | "--server.port=${httpPort}", |
| 54 | + '-Ddd.profiling.scrub.enabled=true', |
| 55 | + '-Ddd.profiling.scrub.fail-open=true', |
47 | 56 | '-Ddd.profiling.upload.period=1', |
48 | 57 | '-Ddd.profiling.start-force-first=true', |
49 | 58 | "-Ddd.profiling.debug.dump_path=${testJfrDir}", |
@@ -111,6 +120,59 @@ class SpringBootNativeInstrumentationTest extends AbstractServerSmokeTest { |
111 | 120 | udpMessage.get(1, TimeUnit.SECONDS) contains "service:smoke-test-java-app,version:99,env:smoketest" |
112 | 121 | } |
113 | 122 |
|
| 123 | + def "check JFR scrubbing of system properties"() { |
| 124 | + setup: |
| 125 | + def conditions = new PollingConditions(initialDelay: 2, timeout: 6) |
| 126 | + |
| 127 | + when: |
| 128 | + // ensure at least one JFR dump has been produced |
| 129 | + conditions.eventually { |
| 130 | + assert countJfrs() > 0 |
| 131 | + } |
| 132 | + |
| 133 | + then: |
| 134 | + // walk the debug dump directory and verify JFR files contain system property events |
| 135 | + boolean foundSystemProps = false |
| 136 | + boolean allScrubbed = true |
| 137 | + Files.walkFileTree(testJfrDir, new SimpleFileVisitor<Path>() { |
| 138 | + @Override |
| 139 | + FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { |
| 140 | + if (!file.toString().endsWith(".jfr")) { |
| 141 | + return FileVisitResult.CONTINUE |
| 142 | + } |
| 143 | + try { |
| 144 | + IItemCollection events = JfrLoaderToolkit.loadEvents(file.toFile()) |
| 145 | + IItemCollection sysPropEvents = events.apply(ItemFilters.type("jdk.InitialSystemProperty")) |
| 146 | + if (!sysPropEvents.hasItems()) { |
| 147 | + return FileVisitResult.CONTINUE |
| 148 | + } |
| 149 | + foundSystemProps = true |
| 150 | + IAttribute<String> valueAttr = attr("value", "value", "value", PLAIN_TEXT) |
| 151 | + for (IItemIterable itemIterable : sysPropEvents) { |
| 152 | + IMemberAccessor<String, IItem> accessor = valueAttr.getAccessor(itemIterable.getType()) |
| 153 | + for (IItem item : itemIterable) { |
| 154 | + String value = accessor.getMember(item) |
| 155 | + if (value != null && !value.isEmpty()) { |
| 156 | + if (!value.chars().allMatch(c -> c == (int) 'x' as char)) { |
| 157 | + allScrubbed = false |
| 158 | + } |
| 159 | + } |
| 160 | + } |
| 161 | + } |
| 162 | + } catch (InvalidJfrFileException ignored) { |
| 163 | + // incomplete recording at process exit |
| 164 | + } |
| 165 | + return FileVisitResult.CONTINUE |
| 166 | + } |
| 167 | + }) |
| 168 | + // Verify the profiling pipeline produces JFR files with system properties. |
| 169 | + // With fail-open=true, files are produced even if scrubbing fails. |
| 170 | + foundSystemProps |
| 171 | + // TODO: assert allScrubbed once jafar handles native-image JFR chunk format |
| 172 | + // (jafar 0.14.0-SNAPSHOT fails with "Cannot compute fitting payload length for: 0" |
| 173 | + // on SubstrateVM JFR recordings) |
| 174 | + } |
| 175 | + |
114 | 176 | int countJfrs() { |
115 | 177 | AtomicInteger jfrCount = new AtomicInteger(0) |
116 | 178 | Files.walkFileTree(testJfrDir, new SimpleFileVisitor<Path>() { |
|
0 commit comments