diff --git a/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManager.java b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManager.java new file mode 100644 index 0000000..638c8f9 --- /dev/null +++ b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManager.java @@ -0,0 +1,58 @@ +/* (C) 2024 */ +package rocks.inspectit.gepard.agent.internal.identity; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Objects; +import rocks.inspectit.gepard.agent.internal.identity.model.IdentityInfo; + +/** Responsible for generating the agentId. */ +public class IdentityManager { + + private static IdentityManager instance; + + private final IdentityInfo identityInfo; + + private IdentityManager() { + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + String vmId = runtime.getName(); + this.identityInfo = new IdentityInfo(vmId, hash(vmId)); + } + + public static IdentityManager getInstance() { + if (Objects.isNull(instance)) instance = new IdentityManager(); + return instance; + } + + public IdentityInfo getIdentityInfo() { + return this.identityInfo; + } + + /** + * Hashes the given input with SHA3-256. + * + * @param input the String to be hashed. + * @return the SHA3-256 hashed String + */ + private static String hash(String input) { + MessageDigest messageDigest; + try { + messageDigest = MessageDigest.getInstance("SHA3-256"); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException("SHA3-256 not supported", e); + } + byte[] bytes = messageDigest.digest(input.getBytes(StandardCharsets.UTF_8)); + StringBuilder hexString = new StringBuilder(2 * bytes.length); + for (byte b : bytes) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } +} diff --git a/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/notification/model/AgentInfo.java b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/model/AgentInfo.java similarity index 84% rename from inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/notification/model/AgentInfo.java rename to inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/model/AgentInfo.java index 986639e..6b6092e 100644 --- a/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/notification/model/AgentInfo.java +++ b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/model/AgentInfo.java @@ -1,5 +1,5 @@ /* (C) 2024 */ -package rocks.inspectit.gepard.agent.notification.model; +package rocks.inspectit.gepard.agent.internal.identity.model; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.PropertyAccessor; @@ -11,6 +11,7 @@ import java.lang.management.RuntimeMXBean; import java.util.Map; import java.util.Objects; +import rocks.inspectit.gepard.agent.internal.identity.IdentityManager; import rocks.inspectit.gepard.agent.internal.properties.PropertiesResolver; /** Meta-information about the current agent */ @@ -31,18 +32,24 @@ public class AgentInfo { private final long startTime; - private final long pid; + private final String vmId; + + private final String agentId; private final Map attributes; private AgentInfo() { + IdentityManager identityManager = IdentityManager.getInstance(); + IdentityInfo identityInfo = identityManager.getIdentityInfo(); + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + this.serviceName = getServiceNameFromSdk(); this.gepardVersion = "0.0.1"; this.otelVersion = AgentVersion.VERSION; this.javaVersion = System.getProperty("java.version"); - RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); this.startTime = runtime.getStartTime(); - this.pid = runtime.getPid(); + this.vmId = identityInfo.vmId(); + this.agentId = identityInfo.agentId(); this.attributes = PropertiesResolver.getAttributes(); } @@ -67,15 +74,4 @@ private String getServiceNameFromSdk() { ? "inspectit-gepard-agent" : configuredServiceName; } - - /** - * @return the service name of the agent. - */ - public String getServiceName() { - return serviceName; - } - - public long getPid() { - return pid; - } } diff --git a/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/model/IdentityInfo.java b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/model/IdentityInfo.java new file mode 100644 index 0000000..f6c17f6 --- /dev/null +++ b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/model/IdentityInfo.java @@ -0,0 +1,21 @@ +/* (C) 2024 */ +package rocks.inspectit.gepard.agent.internal.identity.model; + +public final class IdentityInfo { + + private final String vmId; + private final String agentId; + + public IdentityInfo(String vmId, String agentId) { + this.vmId = vmId; + this.agentId = agentId; + } + + public String vmId() { + return vmId; + } + + public String agentId() { + return agentId; + } +} diff --git a/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/notification/http/NotificationFactory.java b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/notification/http/NotificationFactory.java index 917087b..797ab3e 100644 --- a/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/notification/http/NotificationFactory.java +++ b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/notification/http/NotificationFactory.java @@ -7,7 +7,7 @@ import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; import org.apache.hc.core5.http.ContentType; -import rocks.inspectit.gepard.agent.notification.model.AgentInfo; +import rocks.inspectit.gepard.agent.internal.identity.model.AgentInfo; /** This factory should create different HTTP requests for the configuration server */ public class NotificationFactory { diff --git a/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManagerTest.java b/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManagerTest.java new file mode 100644 index 0000000..b7333cd --- /dev/null +++ b/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManagerTest.java @@ -0,0 +1,41 @@ +/* (C) 2024 */ +package rocks.inspectit.gepard.agent.internal.identity; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import rocks.inspectit.gepard.agent.internal.identity.model.IdentityInfo; + +@ExtendWith(MockitoExtension.class) +class IdentityManagerTest { + + @Test + void testCreateIdentityManagerSuccessfully() { + RuntimeMXBean mockRuntimeMXBean = mock(RuntimeMXBean.class); + when(mockRuntimeMXBean.getName()).thenReturn("12345@mockedHostName"); + + try (MockedStatic managementFactoryMockedStatic = + Mockito.mockStatic(ManagementFactory.class)) { + managementFactoryMockedStatic + .when(ManagementFactory::getRuntimeMXBean) + .thenReturn(mockRuntimeMXBean); + + IdentityManager identityManager = IdentityManager.getInstance(); + IdentityInfo identityInfo = identityManager.getIdentityInfo(); + + assertNotNull(identityInfo); + assertEquals("12345@mockedHostName", identityInfo.vmId()); + assertEquals( + "d29aca592fc2071bcef6577d649071d4d54a8ae6cd5c0be0e51f28af2867f207", + identityInfo.agentId()); + } + } +} diff --git a/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/notification/model/AgentInfoTest.java b/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/internal/identity/model/AgentInfoTest.java similarity index 84% rename from inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/notification/model/AgentInfoTest.java rename to inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/internal/identity/model/AgentInfoTest.java index cadcb4a..1ed424c 100644 --- a/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/notification/model/AgentInfoTest.java +++ b/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/internal/identity/model/AgentInfoTest.java @@ -1,5 +1,5 @@ /* (C) 2024 */ -package rocks.inspectit.gepard.agent.notification.model; +package rocks.inspectit.gepard.agent.internal.identity.model; import static org.junit.jupiter.api.Assertions.*; @@ -23,7 +23,8 @@ void agentInformationContainsProperties() throws JsonProcessingException { assertTrue(info.contains("otelVersion")); assertTrue(info.contains("javaVersion")); assertTrue(info.contains("startTime")); - assertTrue(info.contains("pid")); + assertTrue(info.contains("vmId")); + assertTrue(info.contains("agentId")); assertTrue(info.contains("attributes")); } } diff --git a/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/notification/http/NotificationFactoryTest.java b/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/notification/http/NotificationFactoryTest.java index 408e858..3b34123 100644 --- a/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/notification/http/NotificationFactoryTest.java +++ b/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/notification/http/NotificationFactoryTest.java @@ -6,7 +6,7 @@ import java.net.URISyntaxException; import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; import org.junit.jupiter.api.Test; -import rocks.inspectit.gepard.agent.notification.model.AgentInfo; +import rocks.inspectit.gepard.agent.internal.identity.model.AgentInfo; class NotificationFactoryTest {