Skip to content

Commit 79ca6e4

Browse files
authored
Common temporary location manager for profiling product (#7971)
1 parent 9078a8c commit 79ca6e4

File tree

7 files changed

+720
-110
lines changed

7 files changed

+720
-110
lines changed

dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java

+22-87
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
import static com.datadog.profiling.controller.ProfilingSupport.*;
1919
import static com.datadog.profiling.controller.ProfilingSupport.isObjectCountParallelized;
2020
import static datadog.trace.api.Platform.isJavaVersionAtLeast;
21-
import static datadog.trace.api.config.ProfilingConfig.PROFILING_DEBUG_CLEANUP_REPO;
22-
import static datadog.trace.api.config.ProfilingConfig.PROFILING_DEBUG_CLEANUP_REPO_DEFAULT;
2321
import static datadog.trace.api.config.ProfilingConfig.PROFILING_HEAP_HISTOGRAM_ENABLED;
2422
import static datadog.trace.api.config.ProfilingConfig.PROFILING_HEAP_HISTOGRAM_ENABLED_DEFAULT;
2523
import static datadog.trace.api.config.ProfilingConfig.PROFILING_HEAP_HISTOGRAM_MODE;
@@ -33,6 +31,7 @@
3331
import com.datadog.profiling.controller.ConfigurationException;
3432
import com.datadog.profiling.controller.Controller;
3533
import com.datadog.profiling.controller.ControllerContext;
34+
import com.datadog.profiling.controller.TempLocationManager;
3635
import com.datadog.profiling.controller.jfr.JFRAccess;
3736
import com.datadog.profiling.controller.jfr.JfpUtils;
3837
import com.datadog.profiling.controller.openjdk.events.AvailableProcessorCoresEvent;
@@ -42,19 +41,13 @@
4241
import datadog.trace.bootstrap.config.provider.ConfigProvider;
4342
import datadog.trace.bootstrap.instrumentation.jfr.backpressure.BackpressureProfiling;
4443
import datadog.trace.bootstrap.instrumentation.jfr.exceptions.ExceptionProfiling;
45-
import datadog.trace.util.PidHelper;
4644
import de.thetaphi.forbiddenapis.SuppressForbidden;
4745
import java.io.IOException;
48-
import java.nio.file.FileVisitResult;
49-
import java.nio.file.FileVisitor;
5046
import java.nio.file.Files;
5147
import java.nio.file.Path;
52-
import java.nio.file.Paths;
53-
import java.nio.file.attribute.BasicFileAttributes;
5448
import java.time.Duration;
5549
import java.util.Collections;
5650
import java.util.Map;
57-
import java.util.Set;
5851
import org.slf4j.Logger;
5952
import org.slf4j.LoggerFactory;
6053

@@ -92,14 +85,8 @@ public OpenJdkController(final ConfigProvider configProvider)
9285
// configure the JFR stackdepth before we try to load any JFR classes
9386
int requestedStackDepth = getConfiguredStackDepth(configProvider);
9487
this.jfrStackDepthApplied = JFRAccess.instance().setStackDepth(requestedStackDepth);
95-
boolean shouldCleanupJfrRepository =
96-
configProvider.getBoolean(
97-
PROFILING_DEBUG_CLEANUP_REPO, PROFILING_DEBUG_CLEANUP_REPO_DEFAULT);
98-
String jfrRepositoryBase = null;
99-
if (shouldCleanupJfrRepository) {
100-
jfrRepositoryBase = getJfrRepositoryBase(configProvider);
101-
JFRAccess.instance().setBaseLocation(jfrRepositoryBase + "/pid_" + PidHelper.getPid());
102-
}
88+
String jfrRepositoryBase = getJfrRepositoryBase(configProvider);
89+
JFRAccess.instance().setBaseLocation(jfrRepositoryBase);
10390
// Make sure we can load JFR classes before declaring that we have successfully created
10491
// factory and can use it.
10592
Class.forName("jdk.jfr.Recording");
@@ -112,10 +99,6 @@ public OpenJdkController(final ConfigProvider configProvider)
11299
Map<String, String> recordingSettings;
113100

114101
try {
115-
if (shouldCleanupJfrRepository) {
116-
cleanupJfrRepositories(Paths.get(jfrRepositoryBase));
117-
}
118-
119102
recordingSettings =
120103
JfpUtils.readNamedJfpResource(
121104
ultraMinimal ? JfpUtils.SAFEPOINTS_JFP : JfpUtils.DEFAULT_JFP);
@@ -270,21 +253,27 @@ && isEventEnabled(recordingSettings, "jdk.NativeMethodSample")) {
270253
}
271254

272255
private static String getJfrRepositoryBase(ConfigProvider configProvider) {
273-
return configProvider.getString(
274-
ProfilingConfig.PROFILING_JFR_REPOSITORY_BASE,
275-
ProfilingConfig.PROFILING_JFR_REPOSITORY_BASE_DEFAULT);
276-
}
277-
278-
private static void cleanupJfrRepositories(Path repositoryBase) {
279-
try {
280-
Files.walkFileTree(repositoryBase, new JfrCleanupVisitor(repositoryBase));
281-
} catch (IOException e) {
282-
if (log.isDebugEnabled()) {
283-
log.warn("Unable to cleanup old JFR repositories", e);
284-
} else {
285-
log.warn("Unable to cleanup old JFR repositories");
256+
String legacy =
257+
configProvider.getString(
258+
ProfilingConfig.PROFILING_JFR_REPOSITORY_BASE,
259+
ProfilingConfig.PROFILING_JFR_REPOSITORY_BASE_DEFAULT);
260+
if (!legacy.equals(ProfilingConfig.PROFILING_JFR_REPOSITORY_BASE_DEFAULT)) {
261+
log.warn(
262+
"The configuration key {} is deprecated. Please use {} instead.",
263+
ProfilingConfig.PROFILING_JFR_REPOSITORY_BASE,
264+
ProfilingConfig.PROFILING_TEMP_DIR);
265+
}
266+
Path repositoryPath = TempLocationManager.getInstance().getTempDir().resolve("jfr");
267+
if (!Files.exists(repositoryPath)) {
268+
try {
269+
Files.createDirectories(repositoryPath);
270+
} catch (IOException e) {
271+
log.error("Failed to create JFR repository directory: {}", repositoryPath, e);
272+
throw new IllegalStateException(
273+
"Failed to create JFR repository directory: " + repositoryPath, e);
286274
}
287275
}
276+
return repositoryPath.toString();
288277
}
289278

290279
int getMaxSize() {
@@ -331,58 +320,4 @@ private int getConfiguredStackDepth(ConfigProvider configProvider) {
331320
return configProvider.getInteger(
332321
ProfilingConfig.PROFILING_STACKDEPTH, ProfilingConfig.PROFILING_STACKDEPTH_DEFAULT);
333322
}
334-
335-
private static class JfrCleanupVisitor implements FileVisitor<Path> {
336-
private boolean shouldClean = false;
337-
338-
private final Path root;
339-
private final Set<String> pidSet = PidHelper.getJavaPids();
340-
341-
JfrCleanupVisitor(Path root) {
342-
this.root = root;
343-
}
344-
345-
@Override
346-
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
347-
throws IOException {
348-
if (dir.equals(root)) {
349-
return FileVisitResult.CONTINUE;
350-
}
351-
String fileName = dir.getFileName().toString();
352-
// the JFR repository directories are under <basedir>/pid_<pid>
353-
String pid = fileName.startsWith("pid_") ? fileName.substring(4) : null;
354-
shouldClean |= pid != null && !pidSet.contains(pid);
355-
if (shouldClean) {
356-
log.debug("Cleaning JFR repository under {}", dir);
357-
}
358-
return shouldClean ? FileVisitResult.CONTINUE : FileVisitResult.SKIP_SUBTREE;
359-
}
360-
361-
@Override
362-
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
363-
if (file.toString().toLowerCase().endsWith(".jfr")) {
364-
Files.delete(file);
365-
}
366-
return FileVisitResult.CONTINUE;
367-
}
368-
369-
@Override
370-
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
371-
if (log.isDebugEnabled() && file.toString().toLowerCase().endsWith(".jfr")) {
372-
log.debug("Failed to delete file {}", file, exc);
373-
}
374-
return FileVisitResult.CONTINUE;
375-
}
376-
377-
@Override
378-
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
379-
if (shouldClean) {
380-
Files.delete(dir);
381-
String fileName = dir.getFileName().toString();
382-
// reset the flag only if we are done cleaning the top-level directory
383-
shouldClean = !fileName.startsWith("pid_");
384-
}
385-
return FileVisitResult.CONTINUE;
386-
}
387-
}
388323
}

0 commit comments

Comments
 (0)