Skip to content

Commit

Permalink
Merge pull request #434 from sentrysoftware/feature/issue-433-breakin…
Browse files Browse the repository at this point in the history
…g_change-disable-automatic-hostname-resolution-to-fqdn-in-metricshub

Issue #433: [BREAKING_CHANGE] Disable automatic Hostname to FQDN resolution
  • Loading branch information
NassimBtk authored Oct 2, 2024
2 parents de0fa0e + c75559e commit 2affb96
Show file tree
Hide file tree
Showing 17 changed files with 237 additions and 234 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ public class AgentConfig {

private boolean sequential;

@Default
private boolean resolveHostnameToFqdn = true;
private boolean resolveHostnameToFqdn;

@Default
@JsonSetter(nulls = SKIP)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,7 @@ static HostConfiguration buildHostConfiguration(
.sequential(Boolean.TRUE.equals(resourceConfig.getSequential()))
.configuredConnectorId(configuredConnectorId)
.connectorVariables(resourceConfig.getVariables())
.resolveHostnameToFqdn(resourceConfig.getResolveHostnameToFqdn())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
* ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
*/

import static org.sentrysoftware.metricshub.engine.common.helpers.MetricsHubConstants.HOST_NAME;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
Expand All @@ -40,11 +38,6 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class OtelHelper {

/**
* Fully Qualified Domain Name (FQDN) attribute key
*/
public static final String FQDN_ATTRIBUTE_KEY = "fqdn";

/**
* Create an OTEL Resource
*
Expand Down Expand Up @@ -106,75 +99,36 @@ public static AutoConfiguredOpenTelemetrySdk initOpenTelemetrySdk(
}

/**
* Create the host resource based on the given attributes
* Create the host resource based on the given attributes.
*
* @param hostAttributes Host attributes: host.id, host.name, os.type, host.type, etc
* collected by the engine
* @param userAttributes User configured attributes
* @param resolveHostnameToFqdn Whether we must resolve the hostname of the host to a
* Fully Qualified Domain Name (FQDN)
* @return OTEL {@link Resource} instance
* @param computedHostResourceAttributes Host Resource attributes: host.id, host.name, os.type, host.type, etc
* collected by the engine.
* @param userAttributes User configured attributes.
* @return OTEL {@link Resource} instance representing the host.
*/
public static Resource createHostResource(
@NonNull final Map<String, String> hostAttributes,
@NonNull final Map<String, String> userAttributes,
final boolean resolveHostnameToFqdn
@NonNull final Map<String, String> computedHostResourceAttributes,
@NonNull final Map<String, String> userAttributes
) {
// Get the resource host.name attribute value
final String hostname = resolveResourceHostname(
hostAttributes.get(HOST_NAME),
userAttributes.get(HOST_NAME),
resolveHostnameToFqdn,
userAttributes.get(FQDN_ATTRIBUTE_KEY)
);

// Prepare the resource attributes
final Map<String, String> attributes = new HashMap<>();
attributes.putAll(hostAttributes);
attributes.put(HOST_NAME, hostname);
final Map<String, String> attributes = new HashMap<>(computedHostResourceAttributes);

// Add user attributes
userAttributes.entrySet().stream().forEach(entry -> attributes.putIfAbsent(entry.getKey(), entry.getValue()));
// Add user attributes to the resource attributes
// host.name is managed by the engine based on the resolveHostnameToFqdn flag, so we shouldn't override it here.
// host.type is managed by the engine using a set of rules to determine the host.type in OTEL format so we shouldn't override it here.
// The other attributes are user-defined so we can override them.
userAttributes
.entrySet()
.stream()
.filter(keyValue -> {
final String key = keyValue.getKey();
return !key.equals("host.name") && !key.equals("host.type");
})
.forEach(entry -> attributes.put(entry.getKey(), entry.getValue()));

return createOpenTelemetryResource(attributes);
}

/**
* Resolve the resource hostname.
*
* Priority
* <ol>
* <li>User's attribute <code>fqdn</code> with <code>resolveHostnameToFqdn=true</code></li>
* <li>Collected <code>fqdn</code> when the <code>resolveHostnameToFqdn=true</code></li>
* <li>Configured host name attribute <code>host.name</code></li>
* </ol>
*
* @param collectedFqdn Collected fqdn
* @param configuredHostname Configured host's host.name
* @param resolveHostnameToFqdn Whether we must resolve host.name value to a fully qualified domain name.
* @param userFqdn FQDN attribute value
* @return String value
*/
public static String resolveResourceHostname(
final String collectedFqdn,
final String configuredHostname,
final boolean resolveHostnameToFqdn,
final String userFqdn
) {
if (resolveHostnameToFqdn) {
// User's Fqdn?
if (userFqdn != null) {
return userFqdn;
} else {
// Collected Fqdn
return collectedFqdn;
}
}

// Finally we keep the configured host.name
return configuredHostname;
}

/**
* Merge the given OTEL SDK attributes
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,11 +386,7 @@ void initOtelSdk(final TelemetryManager telemetryManager, final ResourceConfig r
hostMonitorResourceAttributes = Map.of();
}

final Resource resource = OtelHelper.createHostResource(
hostMonitorResourceAttributes,
userAttributes,
resourceConfig.getResolveHostnameToFqdn()
);
final Resource resource = OtelHelper.createHostResource(hostMonitorResourceAttributes, userAttributes);

// Store the host monitor attributes for future use
mainResourceAttributes =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,6 @@ public class MetricsHubCliService implements Callable<Integer> {
)
char[] password;

@Option(names = { "-pd", "--patch-directory" }, order = 5, description = "Patch path to the connectors directory")
String patchDirectory;

@Option(
names = { "-c", "--connectors" },
order = 4,
Expand All @@ -197,6 +194,9 @@ public class MetricsHubCliService implements Callable<Integer> {
)
Set<String> connectors;

@Option(names = { "-pd", "--patch-directory" }, order = 5, description = "Patch path to the connectors directory")
String patchDirectory;

@Option(
names = { "-s", "--sequential" },
order = 6,
Expand All @@ -212,15 +212,15 @@ public class MetricsHubCliService implements Callable<Integer> {
@Option(
names = { "-l", "--list" },
help = true,
order = 7,
order = 8,
description = "Lists all connectors bundled in the engine that can be selected or excluded"
)
boolean listConnectors;

@Option(
names = { "-i", "--iterations" },
help = true,
order = 8,
order = 9,
defaultValue = "1",
description = "Executes the collect strategies N times, where N is the number of iterations"
)
Expand All @@ -229,21 +229,30 @@ public class MetricsHubCliService implements Callable<Integer> {
@Option(
names = { "-si", "--sleep-iteration" },
help = true,
order = 9,
order = 10,
defaultValue = "5",
description = "Adds a sleep period in seconds between collect iterations"
)
long sleepIteration;

@Option(
names = { "-m", "--monitors" },
order = 10,
order = 11,
paramLabel = "MONITOR",
split = ",",
description = "Comma-separated list of monitor types to filter. %nExamples: +disk,+file_system,!memory"
)
Set<String> monitorTypes;

@Option(
names = { "-r", "--resolve-fqdn" },
order = 12,
defaultValue = "false",
description = "Resolves the provided HOSTNAME to its Fully Qualified Domain Name (FQDN)",
help = true
)
boolean resolveHostnameToFqdn;

@Override
public Integer call() throws Exception {
// Check whether iterations is greater than 0. If it's not the case, throw a ParameterException
Expand All @@ -269,6 +278,7 @@ public Integer call() throws Exception {
.hostname(hostname)
.hostType(deviceType)
.sequential(sequential)
.resolveHostnameToFqdn(resolveHostnameToFqdn)
.build();

// Connectors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.sentrysoftware.metricshub.engine.connector.model.metric.MetricDefinition;
import org.sentrysoftware.metricshub.engine.telemetry.MetricFactory;
import org.sentrysoftware.metricshub.engine.telemetry.Monitor;
import org.sentrysoftware.metricshub.engine.telemetry.Resource;
import org.sentrysoftware.metricshub.engine.telemetry.TelemetryManager;
import org.sentrysoftware.metricshub.engine.telemetry.metric.AbstractMetric;
import org.sentrysoftware.metricshub.engine.telemetry.metric.NumberMetric;
Expand All @@ -69,6 +70,15 @@
@Data
public class PrettyPrinterService {

/**
* The header for the resource section
*/
static final String RESOURCE_HEADER = "Resource:";
/**
* The header for the attributes section
*/
static final String ATTRIBUTES_HEADER = "Attributes:";

// @formatter:off
/**
* Defines the priority order for different monitor types
Expand Down Expand Up @@ -162,7 +172,13 @@ private void print(final MonitorChildren monitorChildren, final int indentation)
printWriter.println(Ansi.ansi().fgCyan().a(getMonitorDisplayName(monitor)).reset().toString());

// Attributes
printAttributes(monitor, indentation + 2);
printAttributes(monitor.getAttributes(), indentation + 2, ATTRIBUTES_HEADER);

final Resource resource = monitor.getResource();
if (resource != null) {
// Resource
printAttributes(resource.getAttributes(), indentation + 2, RESOURCE_HEADER);
}

// Metrics
printMetrics(monitor, indentation + 2);
Expand Down Expand Up @@ -199,10 +215,10 @@ private void print(final MonitorChildren monitorChildren, final int indentation)
}

/**
* Print the metrics associated to the given monitor
* Print the metrics associated to the given monitor.
*
* @param monitor Monitor instance whose metrics must be printed
* @param indentation How much indentation to use
* @param monitor Monitor instance whose metrics must be printed.
* @param indentation How much indentation to use.
*/
void printMetrics(final Monitor monitor, final int indentation) {
// Get the metrics
Expand Down Expand Up @@ -351,24 +367,24 @@ private String getMonitorDisplayName(final Monitor monitor) {
}

/**
* Print the attributes associated to the given monitor
* Print the given attributes.
*
* @param monitor The monitor whose attributes must be printed
* @param indentation How much indentation to use
* @param attributes The attributes to be printed.
* @param indentation How much indentation to use.
* @param header The header to be printed.
*/
void printAttributes(final Monitor monitor, final int indentation) {
void printAttributes(final Map<String, String> attributes, final int indentation, final String header) {
// Print a new line
printWriter.println();

// Add the margin
addMargin(indentation);

// Add the header
printWriter.println("Attributes:");
printWriter.println(header);

// Iterate through the attributes, printing each attribute name along with its corresponding value
monitor
.getAttributes()
attributes
.entrySet()
.stream()
.filter(entry -> shouldDisplayKey(entry.getKey()))
Expand Down
Loading

0 comments on commit 2affb96

Please sign in to comment.