Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/environment/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ val excludedClassesCoverage by extra {
"datadog.environment.JavaVirtualMachine", // depends on OS and JVM vendor
"datadog.environment.JavaVirtualMachine.JvmOptionsHolder", // depends on OS and JVM vendor
"datadog.environment.JvmOptions", // depends on OS and JVM vendor
"datadog.environment.OperatingSystem", // depends on OS
"datadog.environment.OperatingSystem**", // depends on OS
)
}
val excludedClassesBranchCoverage by extra {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package datadog.environment;

import static datadog.environment.OperatingSystem.Type.LINUX;
import static datadog.environment.OperatingSystem.Type.MACOS;
import static datadog.environment.OperatingSystem.Type.WINDOWS;
import static java.util.Locale.ROOT;

import java.io.BufferedReader;
Expand All @@ -10,11 +13,15 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/** Detects operating systems and libc library. */
public final class OperatingSystem {
private static final String OS_NAME_PROPERTY = "os.name";
private static final String OS_ARCH_PROPERTY = "os.arch";
private static final Type TYPE = Type.current();
private static final Architecture ARCHITECTURE = Architecture.current();
Comment on lines 20 to +24
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: Thinking about this, what about renaming OperatingSystem to Platform, and Type to OS (or OperatingSystem) ?

The reason for this naeing change is that architecture is not really a property of the operating system. I believe that using the notion of platform is much more close to the native world.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially design the arch outside the OperatingSystem. But I rely on os.arch property, I moved is in OperatingSystem.


private OperatingSystem() {}

Expand All @@ -24,7 +31,7 @@ private OperatingSystem() {}
* @return @{@code true} if operating system is Linux based, {@code false} otherwise.
*/
public static boolean isLinux() {
return propertyContains(OS_NAME_PROPERTY, "linux");
return TYPE == LINUX;
}

/**
Expand All @@ -33,8 +40,7 @@ public static boolean isLinux() {
* @return @{@code true} if operating system is Windows, {@code false} otherwise.
*/
public static boolean isWindows() {
// https://mkyong.com/java/how-to-detect-os-in-java-systemgetpropertyosname/
return propertyContains(OS_NAME_PROPERTY, "win");
return TYPE == WINDOWS;
}

/**
Expand All @@ -43,20 +49,21 @@ public static boolean isWindows() {
* @return @{@code true} if operating system is macOS, {@code false} otherwise.
*/
public static boolean isMacOs() {
return propertyContains(OS_NAME_PROPERTY, "mac");
return TYPE == MACOS;
}

/**
* Checks whether the architecture is AArch64.
* Gets the operating system type.
*
* @return {@code true} if the architecture is AArch64, {@code false} otherwise.
* @return The operating system type, {@link Type#UNKNOWN} if not properly detected or supported.
*/
public static boolean isAarch64() {
return propertyContains(OS_ARCH_PROPERTY, "aarch64");
public static Type type() {
return TYPE;
}

private static boolean propertyContains(String property, String content) {
return SystemProperties.getOrDefault(property, "").toLowerCase(ROOT).contains(content);
/** Gets the operating system architecture . */
public static Architecture architecture() {
return ARCHITECTURE;
}

/**
Expand Down Expand Up @@ -146,4 +153,65 @@ private static boolean containsArray(byte[] container, int offset, byte[] contai
}
return true;
}

public enum Type {
WINDOWS("Windows"),
MACOS("MacOS"),
LINUX("Linux"),
UNKNOWN("unknown");

private final String name;

Type(String name) {
this.name = name;
}

static Type current() {
String property = SystemProperties.getOrDefault(OS_NAME_PROPERTY, "").toLowerCase(ROOT);
// https://mkyong.com/java/how-to-detect-os-in-java-systemgetpropertyosname/
if (property.contains("linux")) {
return LINUX;
} else if (property.contains("win")) {
return WINDOWS;
} else if (property.contains("mac")) {
return MACOS;
} else {
return UNKNOWN;
}
}

@Override
public String toString() {
return this.name;
}
}

/** Detects the operating system architecture. */
public enum Architecture {
X64("x86_64", "amd64", "k8"),
X86("x86", "i386", "i486", "i586", "i686"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Out of curiosity as I didn't followed what Intel did these last years, is there later architectures, if that matter for us ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should ask to profiling about it. This PR is only code relocation.

ARM("arm", "aarch32"),
ARM64("arm64", "aarch64"),
UNKNOWN();

private final Set<String> identifiers;

Architecture(String... identifiers) {
this.identifiers = new HashSet<>(Arrays.asList(identifiers));
}

static Architecture of(String identifier) {
for (Architecture architecture : Architecture.values()) {
if (architecture.identifiers.contains(identifier)) {
return architecture;
}
}
return UNKNOWN;
}

static Architecture current() {
String property = SystemProperties.getOrDefault(OS_ARCH_PROPERTY, "").toLowerCase(ROOT);
return Architecture.of(property);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package datadog.environment;

import static datadog.environment.OperatingSystem.Architecture.ARM;
import static datadog.environment.OperatingSystem.Architecture.ARM64;
import static datadog.environment.OperatingSystem.Architecture.X64;
import static datadog.environment.OperatingSystem.Architecture.X86;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.condition.OS.LINUX;
import static org.junit.jupiter.api.condition.OS.MAC;
import static org.junit.jupiter.api.condition.OS.WINDOWS;

import datadog.environment.OperatingSystem.Type;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;

Expand All @@ -16,6 +22,7 @@ void onLinuxOnly() {
assertTrue(OperatingSystem.isLinux());
assertFalse(OperatingSystem.isMacOs());
assertFalse(OperatingSystem.isWindows());
assertEquals(Type.LINUX, OperatingSystem.type());
}

@Test
Expand All @@ -24,6 +31,7 @@ void onMacOsOnly() {
assertFalse(OperatingSystem.isLinux());
assertTrue(OperatingSystem.isMacOs());
assertFalse(OperatingSystem.isWindows());
assertEquals(Type.MACOS, OperatingSystem.type());
}

@Test
Expand All @@ -32,5 +40,30 @@ void onWindowsOnly() {
assertFalse(OperatingSystem.isLinux());
assertFalse(OperatingSystem.isMacOs());
assertTrue(OperatingSystem.isWindows());
assertEquals(Type.WINDOWS, OperatingSystem.type());
}

@Test
@EnabledOnOs(architectures = {"x86_64", "amd64", "k8"})
void onX64() {
assertEquals(X64, OperatingSystem.architecture());
}

@Test
@EnabledOnOs(architectures = {"x86", "i386", "i486", "i586", "i686"})
void onX86() {
assertEquals(X86, OperatingSystem.architecture());
}

@Test
@EnabledOnOs(architectures = {"arm", "aarch32"})
void onArm() {
assertEquals(ARM, OperatingSystem.architecture());
}

@Test
@EnabledOnOs(architectures = {"arm64", "aarch64"})
void onArm64() {
assertEquals(ARM64, OperatingSystem.architecture());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.datadog.profiling.controller;

import static datadog.environment.OperatingSystem.Architecture.ARM64;

import datadog.environment.JavaVirtualMachine;
import datadog.environment.OperatingSystem;
import datadog.environment.SystemProperties;
Expand Down Expand Up @@ -242,7 +244,10 @@ private static boolean extractSoFromJar(Path target, StringBuilder sb) throws Ex
.filter(
e ->
e.getName()
.contains(OperatingSystem.isAarch64() ? "/linux-arm64/" : "/linux-x64/")
.contains(
OperatingSystem.architecture() == ARM64
? "/linux-arm64/"
: "/linux-x64/")
&& (!OperatingSystem.isMusl() || e.getName().contains("-musl")))
.findFirst()
.map(
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
import com.datadog.profiling.controller.ddprof.DatadogProfilerController;
import com.datadog.profiling.controller.openjdk.OpenJdkController;
import com.datadog.profiling.controller.oracle.OracleJdkController;
import com.datadog.profiling.ddprof.Arch;
import com.datadog.profiling.ddprof.OperatingSystem;
import datadog.environment.JavaVirtualMachine;
import datadog.environment.OperatingSystem;
import datadog.environment.SystemProperties;
import datadog.trace.api.Config;
import datadog.trace.api.Platform;
Expand Down Expand Up @@ -168,8 +167,8 @@ public static Controller build(ConfigProvider provider, ControllerContext contex
ProfilerFlareLogger.getInstance()
.log(
"JFR is not available on this platform: {}, {}",
OperatingSystem.current(),
Arch.current());
OperatingSystem.type(),
OperatingSystem.architecture());
}
} catch (Throwable t) {
ProfilerFlareLogger.getInstance().log("Failed to load openjdk profiler", t);
Expand All @@ -186,14 +185,16 @@ public static Controller build(ConfigProvider provider, ControllerContext contex
} catch (Throwable error) {
Throwable rootCause = error.getCause() == null ? error : error.getCause();
context.setDatadogProfilerUnavailableReason(rootCause.getMessage());
OperatingSystem os = OperatingSystem.current();
if (os != OperatingSystem.linux) {
if (!isLinux()) {
ProfilerFlareLogger.getInstance()
.log("Datadog profiler only supported on Linux", rootCause);
} else {
ProfilerFlareLogger.getInstance()
.log(
"Failed to instantiate Datadog profiler on {} {}", os, Arch.current(), rootCause);
"Failed to instantiate Datadog profiler on {} {}",
OperatingSystem.type(),
OperatingSystem.architecture(),
rootCause);
}
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public static void onEnter(@Advice.Argument(value = 0, readOnly = false) String[
+ "com.datadog.profiling.controller.openjdk.events.SmapEntryFactory$SmapParseErrorEvent:build_time,"
+ "com.datadog.profiling.ddprof.JavaProfilerLoader:run_time,"
+ "datadog.environment.JavaVirtualMachine:rerun,"
+ "datadog.environment.OperatingSystem:rerun,"
+ "datadog.environment.OperatingSystem$Architecture:rerun,"
+ "datadog.trace.agent.tooling.WeakMaps$Adapter:build_time,"
+ "datadog.trace.api.Config:rerun,"
+ "datadog.trace.api.Platform:rerun,"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,14 @@ public TraceStructureWriter(String outputFile, boolean debugLog) {
}

private static String[] parseArgs(String outputFile) {
return parseArgs(outputFile, OperatingSystem.isWindows());
}

// package visibility for testing
static String[] parseArgs(String outputFile, boolean windows) {
String[] args = ARGS_DELIMITER.split(outputFile);
// Check Windows absolute paths (<drive>:<path>) as column is used as arg delimiter
if (OperatingSystem.isWindows()
if (windows
&& args.length > 1
&& args[0].length() == 1
&& (args[1].startsWith("\\") || args[1].startsWith("/"))) {
Expand Down
Loading