Skip to content

Commit 3dbf4bf

Browse files
committed
Add cgroupv2 support.
Add support for modifying where cgroups is mounted to. Fix bug with reading of the body of profile upload responses, early closing of the response prevented the body from being read
1 parent c58db7c commit 3dbf4bf

23 files changed

Lines changed: 488 additions & 103 deletions

File tree

agent/agent-profiler/agent-diagnostics-api/src/main/java/com/microsoft/applicationinsights/diagnostics/DiagnosticEngineFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
package com.microsoft.applicationinsights.diagnostics;
55

66
import java.util.concurrent.ScheduledExecutorService;
7+
import javax.annotation.Nullable;
78

89
/**
910
* Factory to be invoked to create a DiagnosticEngine. This factory will be service loaded by the
1011
* agent and invoked. It is up to the provider of a DiagnosticEngine to provide a service loader for
1112
* this interface.
1213
*/
1314
public interface DiagnosticEngineFactory {
14-
DiagnosticEngine create(ScheduledExecutorService executorService);
15+
DiagnosticEngine create(
16+
ScheduledExecutorService executorService, @Nullable String cgroupBasePath);
1517
}

agent/agent-profiler/agent-diagnostics/src/main/java/com/microsoft/applicationinsights/diagnostics/appinsights/CodeOptimizerApplicationInsightFactoryJfr.java

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,58 @@
66
import com.google.auto.service.AutoService;
77
import com.microsoft.applicationinsights.diagnostics.DiagnosticEngine;
88
import com.microsoft.applicationinsights.diagnostics.DiagnosticEngineFactory;
9+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
10+
import java.nio.file.Files;
11+
import java.nio.file.Path;
12+
import java.nio.file.Paths;
913
import java.util.concurrent.ScheduledExecutorService;
14+
import javax.annotation.Nullable;
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
1017

1118
/** Factory for Code Optimizer diagnostics to be service loaded */
1219
@AutoService(DiagnosticEngineFactory.class)
1320
public class CodeOptimizerApplicationInsightFactoryJfr implements DiagnosticEngineFactory {
21+
22+
private static final Path FILE_SYSTEM_ROOT =
23+
Paths.get(System.getProperty("applicationinsights.profiler.filesystemRoot", "/"));
24+
private static final Path CGROUP_DIR = Paths.get("./sys/fs/cgroup");
25+
26+
private static final Logger logger =
27+
LoggerFactory.getLogger(CodeOptimizerApplicationInsightFactoryJfr.class);
28+
1429
@Override
15-
public DiagnosticEngine create(ScheduledExecutorService executorService) {
16-
return new CodeOptimizerDiagnosticEngineJfr(executorService);
30+
public DiagnosticEngine create(
31+
ScheduledExecutorService executorService, @Nullable String cgroupBasePath) {
32+
Path cgroupPath = getCgroupPath(cgroupBasePath);
33+
return new CodeOptimizerDiagnosticEngineJfr(executorService, cgroupPath);
34+
}
35+
36+
@SuppressFBWarnings(
37+
value = "SECPTI", // Potential Path Traversal
38+
justification =
39+
"The constructed file path cannot be controlled by an end user of the instrumented application")
40+
@Nullable
41+
private static Path getCgroupPath(@Nullable String cgroupBasePath) {
42+
Path cgroupPath = null;
43+
if (cgroupBasePath != null) {
44+
cgroupPath = Paths.get(cgroupBasePath);
45+
46+
if (!Files.exists(cgroupPath)) {
47+
logger.warn("Configured Cgroup path {} does not exist, setting to default", cgroupBasePath);
48+
cgroupPath = null;
49+
}
50+
}
51+
52+
if (cgroupPath == null) {
53+
cgroupPath = FILE_SYSTEM_ROOT.resolve(CGROUP_DIR);
54+
55+
if (!Files.exists(cgroupPath)) {
56+
logger.warn("Expected default Cgroup path {} does not exist", cgroupBasePath);
57+
cgroupPath = null;
58+
}
59+
}
60+
61+
return cgroupPath;
1762
}
1863
}

agent/agent-profiler/agent-diagnostics/src/main/java/com/microsoft/applicationinsights/diagnostics/appinsights/CodeOptimizerDiagnosticEngineJfr.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.microsoft.applicationinsights.diagnostics.jfr.SystemStatsProvider;
1515
import java.io.IOException;
1616
import java.io.StringWriter;
17+
import java.nio.file.Path;
1718
import java.util.concurrent.CompletableFuture;
1819
import java.util.concurrent.Future;
1920
import java.util.concurrent.ScheduledExecutorService;
@@ -33,10 +34,13 @@ public class CodeOptimizerDiagnosticEngineJfr implements DiagnosticEngine {
3334
public static final long TIME_BEFORE_END_OF_PROFILE_TO_EMIT_EVENT = 10L;
3435
private final ScheduledExecutorService executorService;
3536
private final Semaphore semaphore = new Semaphore(1, false);
37+
private final Path cgroupBasePath;
3638
private int thisPid;
3739

38-
public CodeOptimizerDiagnosticEngineJfr(ScheduledExecutorService executorService) {
40+
public CodeOptimizerDiagnosticEngineJfr(
41+
ScheduledExecutorService executorService, Path cgroupBasePath) {
3942
this.executorService = executorService;
43+
this.cgroupBasePath = cgroupBasePath;
4044
}
4145

4246
@Override
@@ -49,14 +53,14 @@ public void init(int thisPid) {
4953
this.thisPid = thisPid;
5054

5155
logger.debug("Initialising Code Optimizer Diagnostic Engine");
52-
CodeOptimizerDiagnosticsJfrInit.initFeature(thisPid);
56+
CodeOptimizerDiagnosticsJfrInit.initFeature(thisPid, cgroupBasePath);
5357
logger.debug("Code Optimizer Diagnostic Engine Initialised");
5458
}
5559

56-
private static void startDiagnosticCycle(int thisPid) {
60+
private static void startDiagnosticCycle(int thisPid, Path cgroupBasePath) {
5761
logger.debug("Starting Code Optimizer Diagnostic Cycle");
58-
CodeOptimizerDiagnosticsJfrInit.initFeature(thisPid);
59-
CodeOptimizerDiagnosticsJfrInit.start(thisPid);
62+
CodeOptimizerDiagnosticsJfrInit.initFeature(thisPid, cgroupBasePath);
63+
CodeOptimizerDiagnosticsJfrInit.start(thisPid, cgroupBasePath);
6064
}
6165

6266
private static void endDiagnosticCycle() {
@@ -70,13 +74,13 @@ public Future<DiagnosisResult<?>> performDiagnosis(AlertBreach alert) {
7074
new CompletableFuture<>();
7175
try {
7276
if (semaphore.tryAcquire(SEMAPHORE_TIMEOUT_IN_SEC, TimeUnit.SECONDS)) {
73-
emitInfo(alert);
77+
emitInfo(alert, cgroupBasePath);
7478

7579
long profileDurationInSec = alert.getAlertConfiguration().getProfileDurationSeconds();
7680

7781
long end = profileDurationInSec - TIME_BEFORE_END_OF_PROFILE_TO_EMIT_EVENT;
7882

79-
startDiagnosticCycle(thisPid);
83+
startDiagnosticCycle(thisPid, cgroupBasePath);
8084

8185
scheduleEmittingAlertBreachEvent(alert, end);
8286

@@ -101,7 +105,7 @@ private void scheduleShutdown(
101105
executorService.schedule(
102106
() -> {
103107
try {
104-
emitInfo(alert);
108+
emitInfo(alert, cgroupBasePath);
105109

106110
// We do not return a result atm
107111
diagnosisResultCompletableFuture.complete(null);
@@ -123,7 +127,7 @@ private void scheduleEmittingAlertBreachEvent(AlertBreach alert, long end) {
123127
executorService.schedule(
124128
() -> {
125129
try {
126-
emitInfo(alert);
130+
emitInfo(alert, cgroupBasePath);
127131
} catch (RuntimeException e) {
128132
logger.error("Failed to emit breach", e);
129133
}
@@ -132,10 +136,10 @@ private void scheduleEmittingAlertBreachEvent(AlertBreach alert, long end) {
132136
TimeUnit.SECONDS);
133137
}
134138

135-
private static void emitInfo(AlertBreach alert) {
139+
private static void emitInfo(AlertBreach alert, Path cgroupBasePath) {
136140
logger.debug("Emitting Code Optimizer Diagnostic Event");
137141
emitAlertBreachJfrEvent(alert);
138-
CodeOptimizerDiagnosticsJfrInit.emitCGroupData();
142+
CodeOptimizerDiagnosticsJfrInit.emitCGroupData(cgroupBasePath);
139143
emitMachineStats();
140144
}
141145

agent/agent-profiler/agent-diagnostics/src/main/java/com/microsoft/applicationinsights/diagnostics/collection/libos/kernel/CGroupDataReader.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ public interface CGroupDataReader {
1919
long getCpuLimit() throws OperatingSystemInteractionException;
2020

2121
long getCpuPeriod() throws OperatingSystemInteractionException;
22+
23+
boolean isAvailable();
2224
}

agent/agent-profiler/agent-diagnostics/src/main/java/com/microsoft/applicationinsights/diagnostics/collection/libos/kernel/CGroupUsageDataReader.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@
1313
public interface CGroupUsageDataReader extends TwoStepUpdatable, Closeable {
1414
@Nullable
1515
List<Double> getTelemetry();
16+
17+
boolean isAvailable();
1618
}

agent/agent-profiler/agent-diagnostics/src/main/java/com/microsoft/applicationinsights/diagnostics/collection/libos/os/linux/cgroups/CGroupCpuSystemReader.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44
package com.microsoft.applicationinsights.diagnostics.collection.libos.os.linux.cgroups;
55

6-
@SuppressWarnings(
7-
"checkstyle:AbbreviationAsWordInName") // CGroup is the standard abbreviation for Control Group
6+
import java.nio.file.Path;
7+
8+
@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
89
public class CGroupCpuSystemReader extends CGroupValueReader {
910
// total system CPU time (in nanoseconds) consumed by all tasks in this cgroup
10-
public CGroupCpuSystemReader() {
11-
super("/sys/fs/cgroup/cpu,cpuacct/cpuacct.usage_sys");
11+
public CGroupCpuSystemReader(Path cgroupPath) {
12+
super(cgroupPath.resolve("./cpuacct.usage_sys"));
1213
}
1314
}

agent/agent-profiler/agent-diagnostics/src/main/java/com/microsoft/applicationinsights/diagnostics/collection/libos/os/linux/cgroups/CGroupCpuUsageReader.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44
package com.microsoft.applicationinsights.diagnostics.collection.libos.os.linux.cgroups;
55

6-
@SuppressWarnings(
7-
"checkstyle:AbbreviationAsWordInName") // CGroup is the standard abbreviation for Control Group
6+
import java.nio.file.Path;
7+
8+
@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
89
public class CGroupCpuUsageReader extends CGroupValueReader {
910
// total CPU usage (in nanoseconds) consumed by all tasks in this cgroup
10-
public CGroupCpuUsageReader() {
11-
super("/sys/fs/cgroup/cpu,cpuacct/cpuacct.usage");
11+
public CGroupCpuUsageReader(Path cgroupPath) {
12+
super(cgroupPath.resolve("./cpuacct.usage"));
1213
}
1314
}

agent/agent-profiler/agent-diagnostics/src/main/java/com/microsoft/applicationinsights/diagnostics/collection/libos/os/linux/cgroups/CGroupCpuUserReader.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44
package com.microsoft.applicationinsights.diagnostics.collection.libos.os.linux.cgroups;
55

6-
@SuppressWarnings(
7-
"checkstyle:AbbreviationAsWordInName") // CGroup is the standard abbreviation for Control Group
6+
import java.nio.file.Path;
7+
8+
@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
89
public class CGroupCpuUserReader extends CGroupValueReader {
910
// total user CPU time (in nanoseconds) consumed by all tasks in this cgroup
10-
public CGroupCpuUserReader() {
11-
super("/sys/fs/cgroup/cpu,cpuacct/cpuacct.usage_user");
11+
public CGroupCpuUserReader(Path cgroupPath) {
12+
super(cgroupPath.resolve("./cpuacct.usage_user"));
1213
}
1314
}

agent/agent-profiler/agent-diagnostics/src/main/java/com/microsoft/applicationinsights/diagnostics/collection/libos/os/linux/cgroups/CGroupStatReader.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@
55

66
import com.microsoft.applicationinsights.diagnostics.collection.libos.BigIncrementalCounter;
77
import com.microsoft.applicationinsights.diagnostics.collection.libos.os.linux.TwoStepProcReader;
8-
import java.io.File;
8+
import java.nio.file.Path;
99

10-
@SuppressWarnings(
11-
"checkstyle:AbbreviationAsWordInName") // CGroup is the standard abbreviation for Control Group
10+
@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
1211
public class CGroupStatReader extends TwoStepProcReader {
1312
private final BigIncrementalCounter user = new BigIncrementalCounter();
1413
private final BigIncrementalCounter system = new BigIncrementalCounter();
1514

16-
public CGroupStatReader() {
17-
super(new File("/sys/fs/cgroup/cpu,cpuacct/cpuacct.stat"), true);
15+
public CGroupStatReader(Path cgroupPath) {
16+
super(cgroupPath.resolve("./cpuacct.stat").toFile(), true);
1817
}
1918

2019
@Override

agent/agent-profiler/agent-diagnostics/src/main/java/com/microsoft/applicationinsights/diagnostics/collection/libos/os/linux/cgroups/CGroupValueReader.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55

66
import com.microsoft.applicationinsights.diagnostics.collection.libos.BigIncrementalCounter;
77
import com.microsoft.applicationinsights.diagnostics.collection.libos.os.linux.TwoStepProcReader;
8-
import java.io.File;
8+
import java.nio.file.Path;
99

10-
@SuppressWarnings(
11-
"checkstyle:AbbreviationAsWordInName") // CGroup is the standard abbreviation for Control Group
10+
@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
1211
public abstract class CGroupValueReader extends TwoStepProcReader {
1312
private final BigIncrementalCounter usage = new BigIncrementalCounter();
1413

15-
public CGroupValueReader(String fileName) {
16-
super(new File(fileName), true);
14+
public CGroupValueReader(Path file) {
15+
super(file.toFile(), true);
1716
}
1817

1918
@Override

0 commit comments

Comments
 (0)