diff --git a/pom.xml b/pom.xml
index 13986c6..ab8acc4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,11 @@
spring-retry
[2.0.0,3.0.0)
+
+ com.github.oshi
+ oshi-core
+ 6.9.2
+
com.github.spotbugs
spotbugs-annotations
diff --git a/src/main/java/io/apitally/common/ApitallyClient.java b/src/main/java/io/apitally/common/ApitallyClient.java
index a647811..b664a78 100644
--- a/src/main/java/io/apitally/common/ApitallyClient.java
+++ b/src/main/java/io/apitally/common/ApitallyClient.java
@@ -72,6 +72,7 @@ public enum HubRequestStatus {
public final ValidationErrorCounter validationErrorCounter;
public final ServerErrorCounter serverErrorCounter;
public final ConsumerRegistry consumerRegistry;
+ public final ResourceMonitor resourceMonitor;
private final Queue syncDataQueue = new ConcurrentLinkedQueue();
private final Random random = new Random();
@@ -87,6 +88,7 @@ public ApitallyClient(String clientId, String env, RequestLoggingConfig requestL
this.validationErrorCounter = new ValidationErrorCounter();
this.serverErrorCounter = new ServerErrorCounter();
this.consumerRegistry = new ConsumerRegistry();
+ this.resourceMonitor = new ResourceMonitor();
}
public boolean isEnabled() {
@@ -149,7 +151,8 @@ private void sendSyncData() {
requestCounter.getAndResetRequests(),
validationErrorCounter.getAndResetValidationErrors(),
serverErrorCounter.getAndResetServerErrors(),
- consumerRegistry.getAndResetConsumers());
+ consumerRegistry.getAndResetConsumers(),
+ resourceMonitor.getCpuMemoryUsage());
syncDataQueue.offer(data);
int i = 0;
diff --git a/src/main/java/io/apitally/common/ResourceMonitor.java b/src/main/java/io/apitally/common/ResourceMonitor.java
new file mode 100644
index 0000000..0cec7a0
--- /dev/null
+++ b/src/main/java/io/apitally/common/ResourceMonitor.java
@@ -0,0 +1,34 @@
+package io.apitally.common;
+
+import io.apitally.common.dto.ResourceUsage;
+import oshi.SystemInfo;
+import oshi.software.os.OSProcess;
+
+public class ResourceMonitor {
+ private final SystemInfo systemInfo = new SystemInfo();
+ private OSProcess previousSnapshot;
+
+ public ResourceUsage getCpuMemoryUsage() {
+ try {
+ int pid = (int) ProcessHandle.current().pid();
+ OSProcess currentProcess = systemInfo.getOperatingSystem().getProcess(pid);
+ if (currentProcess == null) {
+ return null;
+ }
+
+ if (previousSnapshot == null) {
+ previousSnapshot = currentProcess;
+ return null;
+ }
+
+ double cpuPercent =
+ 100.0 * currentProcess.getProcessCpuLoadBetweenTicks(previousSnapshot);
+ long memoryRss = currentProcess.getResidentSetSize();
+ previousSnapshot = currentProcess;
+
+ return new ResourceUsage(cpuPercent, memoryRss);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/io/apitally/common/dto/ResourceUsage.java b/src/main/java/io/apitally/common/dto/ResourceUsage.java
new file mode 100644
index 0000000..4efff2a
--- /dev/null
+++ b/src/main/java/io/apitally/common/dto/ResourceUsage.java
@@ -0,0 +1,23 @@
+package io.apitally.common.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ResourceUsage {
+ private final double cpuPercent;
+ private final long memoryRss;
+
+ public ResourceUsage(double cpuPercent, long memoryRss) {
+ this.cpuPercent = cpuPercent;
+ this.memoryRss = memoryRss;
+ }
+
+ @JsonProperty("cpu_percent")
+ public double getCpuPercent() {
+ return cpuPercent;
+ }
+
+ @JsonProperty("memory_rss")
+ public long getMemoryRss() {
+ return memoryRss;
+ }
+}
diff --git a/src/main/java/io/apitally/common/dto/SyncData.java b/src/main/java/io/apitally/common/dto/SyncData.java
index bc043a7..6234b12 100644
--- a/src/main/java/io/apitally/common/dto/SyncData.java
+++ b/src/main/java/io/apitally/common/dto/SyncData.java
@@ -1,6 +1,7 @@
package io.apitally.common.dto;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import java.util.UUID;
@@ -13,13 +14,15 @@ public class SyncData extends BaseDto {
private final List validationErrors;
private final List serverErrors;
private final List consumers;
+ private final ResourceUsage resources;
public SyncData(
UUID instanceUuid,
List requests,
List validationErrors,
List serverErrors,
- List consumers) {
+ List consumers,
+ ResourceUsage resources) {
this.timestamp = System.currentTimeMillis() / 1000.0;
this.instanceUuid = instanceUuid;
this.messageUuid = UUID.randomUUID();
@@ -27,6 +30,7 @@ public SyncData(
this.validationErrors = validationErrors;
this.serverErrors = serverErrors;
this.consumers = consumers;
+ this.resources = resources;
}
@JsonProperty("timestamp")
@@ -64,6 +68,12 @@ public List getConsumers() {
return consumers;
}
+ @JsonProperty("resources")
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public ResourceUsage getResources() {
+ return resources;
+ }
+
@JsonIgnore
public double getAgeInSeconds() {
return System.currentTimeMillis() / 1000.0 - timestamp;
diff --git a/src/test/java/io/apitally/common/ResourceMonitorTest.java b/src/test/java/io/apitally/common/ResourceMonitorTest.java
new file mode 100644
index 0000000..1ace0a5
--- /dev/null
+++ b/src/test/java/io/apitally/common/ResourceMonitorTest.java
@@ -0,0 +1,26 @@
+package io.apitally.common;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import io.apitally.common.dto.ResourceUsage;
+import org.junit.jupiter.api.Test;
+
+class ResourceMonitorTest {
+
+ @Test
+ void testGetCpuMemoryUsage() throws InterruptedException {
+ ResourceMonitor resourceMonitor = new ResourceMonitor();
+
+ ResourceUsage firstResult = resourceMonitor.getCpuMemoryUsage();
+ assertNull(firstResult);
+
+ Thread.sleep(100);
+
+ ResourceUsage secondResult = resourceMonitor.getCpuMemoryUsage();
+ assertNotNull(secondResult);
+ assertTrue(secondResult.getCpuPercent() >= 0);
+ assertTrue(secondResult.getMemoryRss() > 0);
+ }
+}