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

native-image instrumentation #4333

Merged
merged 5 commits into from
Nov 29, 2022
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
5 changes: 3 additions & 2 deletions buildSrc/src/main/groovy/InstrumentPlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ class InstrumentPlugin implements Plugin<Project> {
compileTask.destinationDirectory = rawClassesDir.asFile

byteBuddyTask.classPath.from((project.configurations.findByName('instrumentationMuzzle') ?: []) +
project.configurations.compileClasspath.findAll { it.name != 'previous-compilation-data.bin' } +
compileTask.destinationDirectory)
project.configurations.compileClasspath.findAll {
it.name != 'previous-compilation-data.bin' && !it.name.endsWith(".gz")
} + compileTask.destinationDirectory)

byteBuddyTask.transformation {
it.plugin = InstrumentLoader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ public boolean isEnabledByDefault() {
public static void start(final Instrumentation inst, final URL agentJarURL) {
createAgentClassloader(agentJarURL);

if (Platform.isNativeImageBuilder()) {
startDatadogAgent(inst);
return;
}

// Retro-compatibility for the old way to configure CI Visibility
if ("true".equals(ddGetProperty("dd.integration.junit.enabled"))
|| "true".equals(ddGetProperty("dd.integration.testng.enabled"))) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package datadog.trace.agent.tooling;

import com.blogspot.mydailyjava.weaklockfree.WeakConcurrentMap;
import datadog.trace.api.Platform;
import datadog.trace.bootstrap.WeakMap;
import datadog.trace.util.AgentTaskScheduler;
import datadog.trace.util.AgentTaskScheduler.Task;
Expand All @@ -12,12 +13,14 @@ public class WeakMaps {

public static <K, V> WeakMap<K, V> newWeakMap() {
final WeakConcurrentMap<K, V> map = new WeakConcurrentMap<>(false, true);
AgentTaskScheduler.INSTANCE.weakScheduleAtFixedRate(
MapCleaningTask.INSTANCE,
map,
CLEAN_FREQUENCY_SECONDS,
CLEAN_FREQUENCY_SECONDS,
TimeUnit.SECONDS);
if (!Platform.isNativeImageBuilder()) {
AgentTaskScheduler.INSTANCE.weakScheduleAtFixedRate(
MapCleaningTask.INSTANCE,
map,
CLEAN_FREQUENCY_SECONDS,
CLEAN_FREQUENCY_SECONDS,
TimeUnit.SECONDS);
}
return new Adapter<>(map);
}

Expand Down
1 change: 1 addition & 0 deletions dd-java-agent/instrumentation/graal/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
apply from: "$rootDir/gradle/java.gradle"
41 changes: 41 additions & 0 deletions dd-java-agent/instrumentation/graal/native-image/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
ext {
minJavaVersionForTests = JavaVersion.VERSION_11
}

muzzle {
pass {
group = "org.graalvm.nativeimage"
module = "svm"
versions = "[20,)"
}
}

apply from: "$rootDir/gradle/java.gradle"
apply plugin: "idea"

[compileMain_java11Java, compileTestJava].each {
it.sourceCompatibility = JavaVersion.VERSION_11
it.targetCompatibility = JavaVersion.VERSION_11
setJavaVersion(it, 11)
it.options.compilerArgs.addAll([
'-Xlint:all,-processing,-options,-path',
'--add-modules',
'jdk.internal.vm.ci',
'--add-exports',
'jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED'
])
}

dependencies {
main_java11CompileOnly group: 'org.graalvm.nativeimage', name: 'svm', version: '20.0.0'
}

forbiddenApisMain_java11 {
failOnMissingClasses = false
}

idea {
module {
jdkName = '11'
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package datadog.trace.instrumentation.graal.nativeimage;

import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.api.Platform;
import java.util.Set;

public abstract class AbstractNativeImageInstrumentation extends Instrumenter.Default {
public AbstractNativeImageInstrumentation() {
super("native-image");
}

@Override
public boolean isApplicable(Set<TargetSystem> enabledSystems) {
return Platform.isNativeImageBuilder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package datadog.trace.instrumentation.graal.nativeimage;

import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;

import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;

@AutoService(Instrumenter.class)
public final class AnnotationSubstitutionProcessorInstrumentation
extends AbstractNativeImageInstrumentation implements Instrumenter.ForSingleType {

@Override
public String instrumentedType() {
return "com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor";
}

@Override
public void adviceTransformations(AdviceTransformation transformation) {
transformation.applyAdvice(
isMethod()
.and(named("lookup"))
.and(takesArgument(0, named("jdk.vm.ci.meta.ResolvedJavaField"))),
packageName + ".DeleteFieldAdvice");
}

@Override
public String[] muzzleIgnoredClassNames() {
// ignore JVMCI classes which are part of GraalVM but aren't available in public repositories
return new String[] {"jdk.vm.ci.meta.ResolvedJavaType", "jdk.vm.ci.meta.ResolvedJavaField"};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package datadog.trace.instrumentation.graal.nativeimage;

import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;

import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;

@AutoService(Instrumenter.class)
public final class ClassInitializationFeatureInstrumentation
extends AbstractNativeImageInstrumentation implements Instrumenter.ForSingleType {

@Override
public String instrumentedType() {
return "com.oracle.svm.hosted.classinitialization.ClassInitializationFeature";
}

@Override
public void adviceTransformations(AdviceTransformation transformation) {
transformation.applyAdvice(
isMethod()
.and(named("processClassInitializationOptions"))
.and(
takesArgument(
0,
named("com.oracle.svm.hosted.classinitialization.ClassInitializationSupport"))),
packageName + ".ClassInitializationAdvice");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package datadog.trace.instrumentation.graal.nativeimage;

import net.bytebuddy.asm.Advice;
import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport;

public class ClassInitializationAdvice {
@Advice.OnMethodEnter
public static void onEnter(
@Advice.Argument(0) RuntimeClassInitializationSupport classInitializationSupport) {
classInitializationSupport.initializeAtBuildTime(
"datadog.trace.api.env.CapturedEnvironment", "");
classInitializationSupport.initializeAtBuildTime("datadog.trace.api.ConfigDefaults", "");
classInitializationSupport.initializeAtBuildTime("datadog.trace.api.Functions", "");
classInitializationSupport.initializeAtBuildTime("datadog.trace.api.InstrumenterConfig", "");
classInitializationSupport.initializeAtBuildTime("datadog.trace.api.Platform", "");
classInitializationSupport.initializeAtBuildTime("datadog.trace.api.GlobalTracer", "");
classInitializationSupport.initializeAtBuildTime(
"datadog.trace.bootstrap.config.provider.ConfigConverter", "");
classInitializationSupport.initializeAtBuildTime(
"datadog.trace.bootstrap.config.provider.ConfigProvider", "");
classInitializationSupport.initializeAtBuildTime("datadog.trace.bootstrap.Agent", "");
classInitializationSupport.initializeAtBuildTime("datadog.trace.bootstrap.BootstrapProxy", "");
classInitializationSupport.initializeAtBuildTime(
"datadog.trace.bootstrap.CallDepthThreadLocalMap", "");
classInitializationSupport.initializeAtBuildTime(
"datadog.trace.bootstrap.DatadogClassLoader", "");
classInitializationSupport.initializeAtBuildTime(
"datadog.trace.bootstrap.FieldBackedContextStores", "");
classInitializationSupport.initializeAtBuildTime(
"datadog.trace.bootstrap.instrumentation.java.concurrent.ConcurrentState", "");
classInitializationSupport.initializeAtBuildTime(
"datadog.trace.bootstrap.instrumentation.java.concurrent.ExcludeFilter", "");
classInitializationSupport.initializeAtBuildTime(
"datadog.trace.bootstrap.instrumentation.java.concurrent.TPEHelper", "");
classInitializationSupport.initializeAtBuildTime(
"datadog.trace.logging.LoggingSettingsDescription", "");
classInitializationSupport.initializeAtBuildTime(
"datadog.trace.logging.simplelogger.SLCompatFactory", "");
classInitializationSupport.initializeAtBuildTime("datadog.trace.util.CollectionUtils", "");
classInitializationSupport.initializeAtBuildTime("datadog.slf4j.impl.StaticLoggerBinder", "");
classInitializationSupport.initializeAtBuildTime("datadog.slf4j.LoggerFactory", "");
classInitializationSupport.initializeAtBuildTime(
"com.blogspot.mydailyjava.weaklockfree.WeakConcurrentMap", "");
classInitializationSupport.initializeAtBuildTime("net.bytebuddy.", "");
classInitializationSupport.initializeAtBuildTime("com.sun.proxy.", "");
mcculls marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package datadog.trace.instrumentation.graal.nativeimage;

import com.oracle.svm.core.annotate.Delete;
import com.oracle.svm.hosted.substitute.AnnotatedField;
import jdk.vm.ci.meta.ResolvedJavaField;
import net.bytebuddy.asm.Advice;

public class DeleteFieldAdvice {
@Advice.OnMethodExit
public static void onExit(
@Advice.Argument(0) ResolvedJavaField field,
@Advice.Return(readOnly = false) ResolvedJavaField result,
@Advice.FieldValue("SUBSTITUTION_DELETE") Delete SUBSTITUTION_DELETE) {
if ("datadog.trace.bootstrap.DatadogClassLoader"
.equals(field.getDeclaringClass().toClassName())) {
result = new AnnotatedField(field, SUBSTITUTION_DELETE);
}
}
}
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ include ':dd-java-agent:instrumentation:exception-profiling'
include ':dd-java-agent:instrumentation:finatra-2.9'
include ':dd-java-agent:instrumentation:glassfish'
include ':dd-java-agent:instrumentation:google-http-client'
include ':dd-java-agent:instrumentation:graal:native-image'
include ':dd-java-agent:instrumentation:graphql-java-14.0'
include ':dd-java-agent:instrumentation:grizzly-2'
include ':dd-java-agent:instrumentation:grizzly-client-1.9'
Expand Down