Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capture FQDN for host name #3188

Merged
merged 9 commits into from Jul 10, 2023
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Expand Up @@ -37,6 +37,7 @@ Use subheadings with the "=====" level for adding notes for unreleased changes:
* Prevent overriding `ELASTIC_APM_AWS_LAMBDA_HANDLER` in AWS lambda execution when explicitly set - {pull}3205[#3205]
* Ignore gc allocation metrics when unsupported - {pull}3225[#3225]
* Avoid warning log message when grpc transactions are cancelled before end - {pull}3223[#3223]
* Align agent hostname capture to FQDN - {pull}3188[#3188]

[[release-notes-1.x]]
=== Java Agent version 1.x
Expand Down
Expand Up @@ -31,7 +31,9 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -156,9 +158,6 @@ static String fallbackHostnameDiscovery(boolean isWindows) {
if (hostname == null || hostname.isEmpty()) {
try {
hostname = InetAddress.getLocalHost().getHostName();
if (hostname != null) {
hostname = removeDomain(hostname);
}
} catch (Exception e) {
logger.warn("Last fallback for hostname discovery of localhost failed", e);
}
Expand All @@ -169,23 +168,13 @@ static String fallbackHostnameDiscovery(boolean isWindows) {
@Nullable
static String discoverHostnameThroughCommand(boolean isWindows, long timeoutMillis) {
String hostname;
List<String> cmd;
if (isWindows) {
cmd = new ArrayList<>();
cmd.add("cmd");
cmd.add("/c");
cmd.add("hostname");
hostname = executeHostnameDiscoveryCommand(cmd, timeoutMillis);
} else {
cmd = new ArrayList<>();
cmd.add("uname");
cmd.add("-n");
hostname = executeHostnameDiscoveryCommand(cmd, timeoutMillis);
hostname = executeHostnameDiscoveryCommand(Arrays.asList("powershell.exe", "[System.Net.Dns]::GetHostEntry($env:computerName).HostName"), timeoutMillis);
if (hostname == null || hostname.isEmpty()) {
cmd = new ArrayList<>();
cmd.add("hostname");
hostname = executeHostnameDiscoveryCommand(cmd, timeoutMillis);
hostname = executeHostnameDiscoveryCommand(Arrays.asList("cmd.exe", "/c", "hostname"), timeoutMillis);
}
} else {
hostname = executeHostnameDiscoveryCommand(Arrays.asList("hostname", "-f"), timeoutMillis);
}
return hostname;
}
Expand All @@ -210,6 +199,9 @@ private static String executeHostnameDiscoveryCommand(List<String> cmd, long tim
logger.info("Failed to execute command {} with exit code {}", cmdAsString(cmd), commandOutput.getExitCode());
logger.debug("Command execution error", commandOutput.getExceptionThrown());
}
if(hostname != null) {
hostname = hostname.toLowerCase(Locale.ROOT);
}
return hostname;
}

Expand All @@ -236,13 +228,8 @@ static String discoverHostnameThroughEnv(boolean isWindows) {
hostname = System.getenv("HOST");
}
}
return hostname;
}

static String removeDomain(String hostname) {
int indexOfDot = hostname.indexOf('.');
if (indexOfDot > 0) {
hostname = hostname.substring(0, indexOfDot);
if (hostname != null) {
hostname = hostname.toLowerCase(Locale.ROOT);
}
return hostname;
}
Expand Down
Expand Up @@ -134,14 +134,20 @@ private void waitForMetadata() throws Exception {
serializedActivationMethod = supportsActivationMethod;

JsonWriter metadataJW = new DslJson<>(new DslJson.Settings<>()).newWriter(4096);
boolean supportsConfiguredAndDetectedHostname = apmServerClient.supportsConfiguredAndDetectedHostname();

serializeMetadata(meta, metadataJW, supportsConfiguredAndDetectedHostname, supportsActivationMethod);
serializeMetadata(meta, metadataJW,
apmServerClient.supportsConfiguredAndDetectedHostname(),
supportsActivationMethod);

serializedMetaData = metadataJW.toByteArray();
}
}

static void serializeMetadata(MetaData metaData, JsonWriter metadataJW, boolean supportsConfiguredAndDetectedHostname, boolean supportsAgentActivationMethod) {
static void serializeMetadata(MetaData metaData,
JsonWriter metadataJW,
boolean supportsConfiguredAndDetectedHostname,
boolean supportsAgentActivationMethod) {

StringBuilder metadataReplaceBuilder = new StringBuilder();
metadataJW.writeByte(JsonWriter.OBJECT_START);
serializeService(metaData.getService(), metadataReplaceBuilder, metadataJW, supportsAgentActivationMethod);
Expand Down Expand Up @@ -327,8 +333,11 @@ private static void serializeProcess(final ProcessInfo process, final StringBuil
jw.writeByte(JsonWriter.OBJECT_END);
}

private static void serializeSystem(final SystemInfo system, final StringBuilder replaceBuilder, final JsonWriter jw,
private static void serializeSystem(SystemInfo system,
StringBuilder replaceBuilder,
JsonWriter jw,
boolean supportsConfiguredAndDetectedHostname) {

writeFieldName("system", jw);
jw.writeByte(JsonWriter.OBJECT_START);
serializeContainerInfo(system.getContainerInfo(), replaceBuilder, jw);
Expand Down
Expand Up @@ -59,18 +59,18 @@ void testHostnameDiscoveryThroughEnv() {
// when running on Windows the actual computer name will be the netbios name, thus won't match exactly
// the entry in the map. It's fine here for testing as it just proves we get the expected value set in map
customEnvVariables.put("COMPUTERNAME", "Windows_hostname");
runWithCustomEnvVariables(customEnvVariables, () -> assertThat(SystemInfo.discoverHostnameThroughEnv(true)).isEqualTo("Windows_hostname"));
runWithCustomEnvVariables(customEnvVariables, () -> assertThat(SystemInfo.discoverHostnameThroughEnv(true)).isEqualTo("windows_hostname"));
} else {
customEnvVariables.put("HOST", "macOS_hostname");
runWithCustomEnvVariables(customEnvVariables, () -> assertThat(SystemInfo.discoverHostnameThroughEnv(false)).isEqualTo("macOS_hostname"));
runWithCustomEnvVariables(customEnvVariables, () -> assertThat(SystemInfo.discoverHostnameThroughEnv(false)).isEqualTo("macos_hostname"));
customEnvVariables.put("HOSTNAME", "Linux_hostname");
runWithCustomEnvVariables(customEnvVariables, () -> assertThat(SystemInfo.discoverHostnameThroughEnv(false)).isEqualTo("Linux_hostname"));
runWithCustomEnvVariables(customEnvVariables, () -> assertThat(SystemInfo.discoverHostnameThroughEnv(false)).isEqualTo("linux_hostname"));
}
}

@Test
void testHostnameDiscoveryFallbackThroughInetAddress() throws UnknownHostException {
String expectedHostname = SystemInfo.removeDomain(InetAddress.getLocalHost().getHostName());
String expectedHostname = InetAddress.getLocalHost().getHostName();

Map<String, String> customEnvVariables = new HashMap<>();
// none of those env variables should be available to trigger the fallback on all platforms
Expand All @@ -81,27 +81,21 @@ void testHostnameDiscoveryFallbackThroughInetAddress() throws UnknownHostExcepti
runWithCustomEnvVariables(customEnvVariables, () -> {

// sanity check for test instrumentation to ensure those are not set
checkSystemPropertiesNotSet("HOST","HOSTNAME","COMPUTERNAME");
checkSystemPropertiesNotSet("HOST", "HOSTNAME", "COMPUTERNAME");

assertThat(SystemInfo.fallbackHostnameDiscovery(isWindows))
.isEqualTo(expectedHostname);
});
}

private static void checkSystemPropertiesNotSet(String... keys){
private static void checkSystemPropertiesNotSet(String... keys) {
Map<String, String> map = System.getenv();
for (String key : keys) {
assertThat(System.getenv(key)).isNull();
assertThat(map.get(key)).isNull();
}
}

@Test
void testDomainRemoval() {
assertThat(SystemInfo.removeDomain("hostname")).isEqualTo("hostname");
assertThat(SystemInfo.removeDomain("hostname.and.domain")).isEqualTo("hostname");
}

@Test
void testLambdaShortcut() {
doReturn(true).when(serverlessConfiguration).runsOnAwsLambda();
Expand Down
Expand Up @@ -1088,12 +1088,12 @@ void testSystemInfo_configuredHostname(boolean supportsConfiguredAndDetectedHost
}

@ParameterizedTest
@ValueSource(booleans = {true, false})
@ValueSource(booleans = {false,true})
void testSystemInfo_detectedHostname(boolean supportsConfiguredAndDetectedHostname) throws Exception {
String arc = "test-arc";
String platform = "test-platform";

MetaData metaData = createMetaData(new SystemInfo(arc, null, "detected", platform));
MetaData metaData = createMetaData(new SystemInfo(arc, null, "detected.fqdn", platform));
DslJsonSerializer.serializeMetadata(metaData, writer.getJsonWriter(), supportsConfiguredAndDetectedHostname, true);
writer.appendMetadataToStream();

Expand All @@ -1103,12 +1103,12 @@ void testSystemInfo_detectedHostname(boolean supportsConfiguredAndDetectedHostna
assertThat(platform).isEqualTo(system.get("platform").asText());
if (supportsConfiguredAndDetectedHostname) {
assertThat(system.get("configured_hostname")).isNull();
assertThat(system.get("detected_hostname").asText()).isEqualTo("detected");
assertThat(system.get("detected_hostname").asText()).isEqualTo("detected.fqdn");
assertThat(system.get("hostname")).isNull();
} else {
assertThat(system.get("configured_hostname")).isNull();
assertThat(system.get("detected_hostname")).isNull();
assertThat(system.get("hostname").asText()).isEqualTo("detected");
assertThat(system.get("hostname").asText()).isEqualTo("detected.fqdn");
}
}

Expand Down