8000 feat(environment): Add environment component · DataDog/dd-trace-java@b485504 · GitHub
[go: up one dir, main page]

Skip to content

Commit b485504

Browse files
committed
feat(environment): Add environment component
1 parent 7d0a7e8 commit b485504
< 10000 button data-component="IconButton" type="button" data-testid="expand-file-tree-button" aria-expanded="false" aria-controls="diff_file_tree" class="prc-Button-ButtonBase-c50BI d-md-none position-relative fgColor-muted prc-Button-IconButton-szpyj" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="invisible" aria-describedby=":R6iplab:-loading-announcement" aria-labelledby=":Riplab:">

18 files changed

+1518
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
plugins {
2+
`java-library`
3+
}
4+
5+
apply(from = "$rootDir/gradle/java.gradle")
6+
7+
extra.set("minimumInstructionCoverage", 0.7)
8+
val excludedClassesCoverage by extra {
9+
listOf(
10+
"datadog.environment.JavaVirtualMachine", // depends on OS and JVM vendor
11+
"datadog.environment.JavaVirtualMachine.JvmOptionsHolder", // depends on OS and JVM vendor
12+
"datadog.environment.JvmOptions", // depends on OS and JVM vendor
13+
"datadog.environment.OperatingSystem", // depends on OS
14+
)
15+
}
16+
val excludedClassesBranchCoverage by extra {
17+
listOf("datadog.environment.CommandLine") // tested using forked process
18+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package datadog.environment;
2+
3+
import static java.util.Collections.emptyList;
4+
5+
import de.thetaphi.forbiddenapis.SuppressForbidden;
6+
import java.util.Arrays;
7+
import java.util.List;
8+
9+
/**
10+
* Fetches and captures the command line, both command and its arguments. It relies on a
11+
* non-standard {@code sun.java.command} system property and was tested on:
12+
*
13+
* <ul>
14+
* <li>OracleJDK,
15+
* <li>OpenJDK,
16+
* <li>Temurin based JDK,
17+
* <li>IMB JDK,
18+
* <li>Azul Zulu,
19+
* <li>Amazon Coretto,
20+
* </ul>
21+
*/
22+
class CommandLine {
23+
private static final String SUN_JAVA_COMMAND_PROPERTY = "sun.java.command";
24+
final List<String> fullCommand = findFullCommand();
25+
final String command = getCommand();
26+
final List<String> arguments = getCommandArguments();
27+
28+
@SuppressForbidden // split on single-character uses fast path
29+
private List<String> findFullCommand() {
30+
String command = SystemProperties.getOrDefault(SUN_JAVA_COMMAND_PROPERTY, "").trim();
31+
return command.isEmpty() ? emptyList() : Arrays.asList(command.split(" "));
32+
}
33+
34+
private String getCommand() {
35+
return fullCommand.isEmpty() ? null : fullCommand.get(0);
36+
}
37+
38+
private List<String> getCommandArguments() {
39+
if (fullCommand.isEmpty()) {
40+
return fullCommand;
41+
} else {
42+
return fullCommand.subList(1, fullCommand.size());
43+
}
44+
}
45+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package datadog.environment;
2+
3+
import javax.annotation.Nonnull;
4+
import javax.annotation.Nullable;
5+
6+
/**
7+
* Safely queries environment variables against security manager.
8+
*
9+
* @see <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/SecurityManager.html">Security
10+
* Manager</a>
11+
*/
12+
public final class EnvironmentVariables {
13+
private EnvironmentVariables() {}
14+
15+
/**
16+
* Gets an environment variable value.
17+
*
18+
* @param name The environment variable name.
19+
* @return The environment variable value, {@code null} if missing or can't be retrieved.
20+
*/
21+
public static @Nullable String get(String name) {
22+
return getOrDefault(name, null);
23+
}
24+
25+
/**
26+
* Gets an environment variable value, or default value if missing or can't be retrieved.
27+
*
28+
* @param name The environment variable name.
29+
* @param defaultValue The default value to return if the environment variable is missing or can't
30+
* be retrieved.
31+
* @return The environment variable value, {@code defaultValue} if missing or can't be retrieved.
32+
*/
33+
public static String getOrDefault(@Nonnull String name, String defaultValue) {
34+
try {
35+
String value = System.getenv(name);
36+
return value == null ? defaultValue : value;
37+
} catch (SecurityException e) {
38+
return defaultValue;
39+
}
40+
}
41+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package datadog.environment;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
* This class represents a Java version according the String Naming Convention.
8+
*
9+
* @see <a href="https://www.oracle.com/java/technologies/javase/versioning-naming.html">String
10+
* Naming Convention</a>
11+
*/
12+
final class JavaVersion {
13+
final int major;
14+
final int minor;
15+
final int update;
16+
17+
JavaVersion(int major, int minor, int update) {
18+
this.major = major;
19+
this.minor = minor;
20+
this.update = update;
21+
}
22+
23+
static JavaVersion getRuntimeVersion() {
24+
return parseJavaVersion(SystemProperties.getOrDefault("java.version", ""));
25+
}
26+
27+
static JavaVersion parseJavaVersion(String javaVersion) {
28+
// Remove pre-release part, usually -ea
29+
final int indexOfDash = javaVersion.indexOf('-');
30+
if (indexOfDash >= 0) {
31+
javaVersion = javaVersion.substring(0, indexOfDash);
32+
}
33+
34+
int major = 0;
35+
int minor = 0;
36+
int update = 0;
37+
38+
try {
39+
List<Integer> nums = splitDigits(javaVersion);
40+
major = nums.get(0);
41+
42+
// for java 1.6/1.7/1.8
43+
if (major == 1) {
44+
major = nums.get(1);
45+
minor = nums.get(2);
46+
update = nums.get(3);
47+
} else {
48+
minor = nums.get(1);
49+
update = nums.get(2);
50+
}
51+
} catch (NumberFormatException | IndexOutOfBoundsException e) {
52+
// unable to parse version string - do nothing
53+
}
54+
return new JavaVersion(major, minor, update);
55+
}
56+
57+
/* The method splits java version string by digits. Delimiters are: dot, underscore and plus */
58+
private static List<Integer> splitDigits(String str) {
59+
List<Integer> results = new ArrayList<>();
60+
61+
int len = str.length();
62+
int value = 0;
63+
for (int i = 0; i < len; i++) {
64+
char ch = str.charAt(i);
65+
if (ch >= '0' && ch <= '9') {
66+
value = value * 10 + (ch - '0');
67+
} else if (ch == '.' || ch == '_' || ch == '+') {
68+
results.add(value);
69+
value = 0;
70+
} else {
71+
throw new NumberFormatException();
72+
}
73+
}
74+
results.add(value);
75+
return results;
76+
}
77+
78+
public boolean is(int major) {
79+
return this.major == major;
80+
}
81+
82+
public boolean is(int major, int minor) {
83+
return this.major == major && this.minor == minor;
84+
}
85+
86+
public boolean is(int major, int minor, int update) {
87+
return this.major == major && this.minor == minor && this.update == update;
88+
}
89+
90+
public boolean isAtLeast(int major, int minor, int update) {
91+
return isAtLeast(this.major, this.minor, this.update, major, minor, update);
92+
}
93+
94+
public boolean isBetween(
95+
int fromMajor, int fromMinor, int fromUpdate, int toMajor, int toMinor, int toUpdate) {
96+
return isAtLeast(toMajor, toMinor, toUpdate, fromMajor, fromMinor, fromUpdate)
97+
&& isAtLeast(fromMajor, fromMinor, fromUpdate)
98+
&& !isAtLeast(toMajor, toMinor, toUpdate);
99+
}
100+
101+
private static boolean isAtLeast(
102+
int major, int minor, int update, int atLeastMajor, int atLeastMinor, int atLeastUpdate) {
103+
return (major > atLeastMajor)
104+
|| (major == atLeastMajor && minor > atLeastMinor)
105+
|| (major == atLeastMajor && minor == atLeastMinor && update >= atLeastUpdate);
106+
}
107+
}

0 commit comments

Comments
 (0)
0