-
Notifications
You must be signed in to change notification settings - Fork 305
Added special lightweight pre-main class that skips installation on incompatible JVMs. #8855
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
Merged
+385
−162
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
5e9b6ba
Added special lightweight pre-main class to enable SSI inject for Jav…
AlexeyKuznetsov-DD c40db79
Fixed SuppressForbidden test.
AlexeyKuznetsov-DD 125a148
Refactored pre-check logic.
AlexeyKuznetsov-DD 1e7ecd1
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD 99abf99
Refactored build.gradle to reuse existing functions.
AlexeyKuznetsov-DD 2eb2753
Minor cleanup.
AlexeyKuznetsov-DD 0c2e817
Added missing `@SuppressForbidden`.
AlexeyKuznetsov-DD 45fb91f
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD 78dc42b
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD ea5bea7
Added 'java.home' to warning. That would help to identify problematic…
AlexeyKuznetsov-DD 5695279
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD 9238f7d
Added test to ensure Java 6 & 8 compilation.
AlexeyKuznetsov-DD 10d60a0
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD 5f61b62
Fixed test.
AlexeyKuznetsov-DD 5fa1bb6
Drop support for 0.x version.
AlexeyKuznetsov-DD 985412f
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD be58d6b
Fixed small typo.
AlexeyKuznetsov-DD 7c2a597
Fixed test.
AlexeyKuznetsov-DD 8192ac4
Update dd-java-agent/src/main/java6/datadog/trace/bootstrap/AgentPreC…
AlexeyKuznetsov-DD 1037295
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD e1df6fe
Fixed test.
AlexeyKuznetsov-DD File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
194 changes: 194 additions & 0 deletions
194
dd-java-agent/src/main/java6/datadog/trace/bootstrap/AgentPreCheck.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
package datadog.trace.bootstrap; | ||
|
||
import de.thetaphi.forbiddenapis.SuppressForbidden; | ||
import java.io.BufferedReader; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.io.OutputStream; | ||
import java.io.PrintStream; | ||
import java.lang.instrument.Instrumentation; | ||
import java.lang.reflect.Method; | ||
|
||
/** Special lightweight pre-main class that skips installation on incompatible JVMs. */ | ||
public class AgentPreCheck { | ||
public static void premain(final String agentArgs, final Instrumentation inst) { | ||
agentmain(agentArgs, inst); | ||
} | ||
|
||
@SuppressForbidden | ||
public static void agentmain(final String agentArgs, final Instrumentation inst) { | ||
try { | ||
if (compatible()) { | ||
continueBootstrap(agentArgs, inst); | ||
} | ||
} catch (Throwable e) { | ||
// If agent failed we should not fail the application. | ||
// We don't have a log manager here, so just print. | ||
System.err.println("ERROR: " + e.getMessage()); | ||
} | ||
} | ||
|
||
private static void reportIncompatibleJava( | ||
String javaVersion, String javaHome, String agentVersion, PrintStream output) { | ||
output.println( | ||
"Warning: " | ||
+ (agentVersion == null ? "This version" : "Version " + agentVersion) | ||
+ " of dd-java-agent is not compatible with Java " | ||
+ javaVersion | ||
+ " found at '" | ||
+ javaHome | ||
+ "' and is effectively disabled."); | ||
output.println("Please upgrade your Java version to 8+"); | ||
} | ||
|
||
static void sendTelemetry(String forwarderPath, String javaVersion, String agentVersion) { | ||
// Hardcoded payload for unsupported Java version. | ||
String payload = | ||
"{\"metadata\":{" | ||
+ "\"runtime_name\":\"jvm\"," | ||
+ "\"language_name\":\"jvm\"," | ||
+ "\"runtime_version\":\"" | ||
+ javaVersion | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Part of me doesn't like that these aren't escaped properly, but I suppose for this use case it is okay. |
||
+ "\"," | ||
+ "\"language_version\":\"" | ||
+ javaVersion | ||
+ "\"," | ||
+ "\"tracer_version\":\"" | ||
+ agentVersion | ||
+ "\"}," | ||
+ "\"points\":[{" | ||
+ "\"name\":\"library_entrypoint.abort\"," | ||
+ "\"tags\":[\"reason:incompatible_runtime\"]" | ||
+ "}]" | ||
+ "}"; | ||
|
||
ForwarderJsonSenderThread t = new ForwarderJsonSenderThread(forwarderPath, payload); | ||
t.setDaemon(true); | ||
t.start(); | ||
} | ||
|
||
private static String tryGetProperty(String property) { | ||
try { | ||
return System.getProperty(property); | ||
} catch (SecurityException e) { | ||
return null; | ||
} | ||
} | ||
|
||
@SuppressForbidden | ||
private static boolean compatible() { | ||
String javaVersion = tryGetProperty("java.version"); | ||
String javaHome = tryGetProperty("java.home"); | ||
|
||
return compatible(javaVersion, javaHome, System.err); | ||
} | ||
|
||
// Reachable for testing | ||
static boolean compatible(String javaVersion, String javaHome, PrintStream output) { | ||
int majorJavaVersion = parseJavaMajorVersion(javaVersion); | ||
|
||
if (majorJavaVersion >= 8) { | ||
return true; | ||
} | ||
|
||
String agentVersion = getAgentVersion(); | ||
|
||
reportIncompatibleJava(javaVersion, javaHome, agentVersion, output); | ||
|
||
String forwarderPath = System.getenv("DD_TELEMETRY_FORWARDER_PATH"); | ||
if (forwarderPath != null) { | ||
sendTelemetry(forwarderPath, javaVersion, agentVersion); | ||
} | ||
|
||
return false; | ||
} | ||
|
||
// Reachable for testing | ||
static int parseJavaMajorVersion(String javaVersion) { | ||
int major = 0; | ||
if (javaVersion == null || javaVersion.isEmpty()) { | ||
return major; | ||
} | ||
|
||
int start = 0; | ||
if (javaVersion.charAt(0) == '1' | ||
&& javaVersion.length() >= 3 | ||
&& javaVersion.charAt(1) == '.' | ||
&& Character.isDigit(javaVersion.charAt(2))) { | ||
start = 2; | ||
} | ||
|
||
// Parse the major digit and be a bit lenient, allowing digits followed by any non digit | ||
for (int i = start; i < javaVersion.length(); i++) { | ||
char c = javaVersion.charAt(i); | ||
if (Character.isDigit(c)) { | ||
major *= 10; | ||
major += Character.digit(c, 10); | ||
} else { | ||
break; | ||
} | ||
} | ||
return major; | ||
} | ||
|
||
private static String getAgentVersion() { | ||
try { | ||
// Get the resource as an InputStream | ||
InputStream is = AgentPreCheck.class.getResourceAsStream("/dd-java-agent.version"); | ||
if (is == null) { | ||
return null; | ||
} | ||
|
||
BufferedReader reader = new BufferedReader(new InputStreamReader(is)); | ||
final StringBuilder sb = new StringBuilder(); | ||
for (int c = reader.read(); c != -1; c = reader.read()) { | ||
sb.append((char) c); | ||
} | ||
reader.close(); | ||
|
||
return sb.toString().trim(); | ||
} catch (Throwable e) { | ||
return null; | ||
} | ||
} | ||
|
||
@SuppressForbidden | ||
private static void continueBootstrap(final String agentArgs, final Instrumentation inst) | ||
throws Exception { | ||
Class<?> clazz = Class.forName("datadog.trace.bootstrap.AgentBootstrap"); | ||
Method agentMain = clazz.getMethod("agentmain", String.class, Instrumentation.class); | ||
agentMain.invoke(null, agentArgs, inst); | ||
} | ||
|
||
public static final class ForwarderJsonSenderThread extends Thread { | ||
private final String forwarderPath; | ||
private final String payload; | ||
|
||
public ForwarderJsonSenderThread(String forwarderPath, String payload) { | ||
super("dd-forwarder-json-sender"); | ||
setDaemon(true); | ||
this.forwarderPath = forwarderPath; | ||
this.payload = payload; | ||
} | ||
|
||
@SuppressForbidden | ||
@Override | ||
public void run() { | ||
ProcessBuilder builder = new ProcessBuilder(forwarderPath, "library_entrypoint"); | ||
try { | ||
Process process = builder.start(); | ||
OutputStream out = null; | ||
try { | ||
out = process.getOutputStream(); | ||
out.write(payload.getBytes()); | ||
} finally { | ||
if (out != null) { | ||
out.close(); | ||
} | ||
} | ||
} catch (Throwable e) { | ||
System.err.println("Failed to send telemetry: " + e.getMessage()); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.