From 7a792e2790ff0e6b082358f0f4668e804eeb41fe Mon Sep 17 00:00:00 2001 From: Nikita Salnikov-Tarnovski Date: Thu, 10 Dec 2020 14:41:09 +0200 Subject: [PATCH 1/4] Support for WildFly version detection --- instrumentation/wildfly/build.gradle | 7 ++ ...ildFlyAttributesInstrumentationModule.java | 80 +++++++++++++++++++ settings.gradle.kts | 1 + .../opentelemetry/GlassFishSmokeTest.java | 2 +- .../opentelemetry/WildFlySmokeTest.java | 74 +++++++++++++++++ 5 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 instrumentation/wildfly/build.gradle create mode 100644 instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java create mode 100644 smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java diff --git a/instrumentation/wildfly/build.gradle b/instrumentation/wildfly/build.gradle new file mode 100644 index 000000000..bff7f4c40 --- /dev/null +++ b/instrumentation/wildfly/build.gradle @@ -0,0 +1,7 @@ +plugins { + id "java" +} + +dependencies { + compileOnly('org.wildfly.core:wildfly-version:13.0.0.Final') +} \ No newline at end of file diff --git a/instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java b/instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java new file mode 100644 index 000000000..8dfac636c --- /dev/null +++ b/instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java @@ -0,0 +1,80 @@ +/* + * Copyright Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.splunk.opentelemetry.middleware; + +import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.isStatic; +import static net.bytebuddy.matcher.ElementMatchers.named; + +import com.google.auto.service.AutoService; +import com.splunk.opentelemetry.javaagent.bootstrap.MiddlewareHolder; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.jboss.as.version.ProductConfig; + +@AutoService(InstrumentationModule.class) +public class WildFlyAttributesInstrumentationModule extends InstrumentationModule { + + public WildFlyAttributesInstrumentationModule() { + super("wildfly"); + } + + @Override + public ElementMatcher.Junction classLoaderMatcher() { + return hasClassesNamed("org.jboss.as.version.ProductConfig"); + } + + @Override + public List typeInstrumentations() { + return Collections.singletonList(new Instrumentation()); + } + + public static class Instrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("org.jboss.as.version.ProductConfig"); + } + + @Override + public Map, String> transformers() { + return Collections.singletonMap( + isMethod().and(isStatic()).and(named("fromFilesystemSlot")), + WildFlyAttributesInstrumentationModule.class.getName() + + "$MiddlewareInitializedAdvice"); + } + } + + @SuppressWarnings("unused") + public static class MiddlewareInitializedAdvice { + @Advice.OnMethodExit(suppress = Throwable.class) + public static void onExit(@Advice.Return ProductConfig productConfig) { + if (productConfig != null) { + MiddlewareHolder.trySetName(productConfig.resolveName()); + MiddlewareHolder.trySetVersion(productConfig.resolveVersion()); + } + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 29fc602f6..6ddb66f40 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,5 +16,6 @@ include("agent", "instrumentation:jetty", "instrumentation:glassfish", "instrumentation:tomcat", + "instrumentation:wildfly", "smoke-tests", "matrix") \ No newline at end of file diff --git a/smoke-tests/src/test/java/com/splunk/opentelemetry/GlassFishSmokeTest.java b/smoke-tests/src/test/java/com/splunk/opentelemetry/GlassFishSmokeTest.java index dd6a71ddb..08402a479 100644 --- a/smoke-tests/src/test/java/com/splunk/opentelemetry/GlassFishSmokeTest.java +++ b/smoke-tests/src/test/java/com/splunk/opentelemetry/GlassFishSmokeTest.java @@ -54,7 +54,7 @@ protected Map getExtraEnv() { @Override protected WaitStrategy getWaitStrategy() { return Wait.forLogMessage(".*app was successfully deployed.*", 1) - .withStartupTimeout(Duration.ofMinutes(15)); + .withStartupTimeout(Duration.ofMinutes(5)); } @ParameterizedTest diff --git a/smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java b/smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java new file mode 100644 index 000000000..e9efee579 --- /dev/null +++ b/smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java @@ -0,0 +1,74 @@ +/* + * Copyright Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.splunk.opentelemetry; + +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import java.io.IOException; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +public class WildFlySmokeTest extends AppServerTest { + + public static final ExpectedServerAttributes WILDFLY_13_SERVER_ATTRIBUTES = + new ExpectedServerAttributes( + "/this-is-definitely-not-there-but-there-should-be-a-trace-nevertheless", + "WildFly Full", + "13.0.0.Final"); + public static final ExpectedServerAttributes WILDFLY_17_SERVER_ATTRIBUTES = + new ExpectedServerAttributes( + "/this-is-definitely-not-there-but-there-should-be-a-trace-nevertheless", + "WildFly Full", + "17.0.1.Final"); + public static final ExpectedServerAttributes WILDFLY_21_SERVER_ATTRIBUTES = + new ExpectedServerAttributes( + "/this-is-definitely-not-there-but-there-should-be-a-trace-nevertheless", + "WildFly Full", + "21.0.0.Final"); + + private static Stream supportedConfigurations() { + return Stream.of( + arguments( + "ghcr.io/open-telemetry/java-test-containers:wildfly-13.0.0.Final-jdk8-20201207.405832649", + WILDFLY_13_SERVER_ATTRIBUTES), + arguments( + "ghcr.io/open-telemetry/java-test-containers:wildfly-17.0.1.Final-jdk8-20201207.405832649", + WILDFLY_17_SERVER_ATTRIBUTES), + arguments( + "ghcr.io/open-telemetry/java-test-containers:wildfly-17.0.1.Final-jdk11-20201207.405832649", + WILDFLY_17_SERVER_ATTRIBUTES), + arguments( + "ghcr.io/open-telemetry/java-test-containers:wildfly-21.0.0.Final-jdk8-20201207.405832649", + WILDFLY_21_SERVER_ATTRIBUTES), + arguments( + "ghcr.io/open-telemetry/java-test-containers:wildfly-21.0.0.Final-jdk11-20201207.405832649", + WILDFLY_21_SERVER_ATTRIBUTES)); + } + + @ParameterizedTest + @MethodSource("supportedConfigurations") + void wildflySmokeTest(String imageName, ExpectedServerAttributes expectedServerAttributes) + throws IOException, InterruptedException { + startTarget(imageName); + + //TODO support 404 +// assertServerHandler(expectedServerAttributes); + assertWebAppTrace(expectedServerAttributes); + } +} From 85af904d76d54f11c4ec01f9cda83821190132b4 Mon Sep 17 00:00:00 2001 From: Nikita Salnikov-Tarnovski Date: Thu, 10 Dec 2020 15:09:37 +0200 Subject: [PATCH 2/4] Format --- .../middleware/WildFlyAttributesInstrumentationModule.java | 3 +-- .../test/java/com/splunk/opentelemetry/WildFlySmokeTest.java | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java b/instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java index 8dfac636c..d5f18278a 100644 --- a/instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java +++ b/instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java @@ -62,8 +62,7 @@ public ElementMatcher typeMatcher() { public Map, String> transformers() { return Collections.singletonMap( isMethod().and(isStatic()).and(named("fromFilesystemSlot")), - WildFlyAttributesInstrumentationModule.class.getName() - + "$MiddlewareInitializedAdvice"); + WildFlyAttributesInstrumentationModule.class.getName() + "$MiddlewareInitializedAdvice"); } } diff --git a/smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java b/smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java index e9efee579..e95358bce 100644 --- a/smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java +++ b/smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java @@ -67,8 +67,8 @@ void wildflySmokeTest(String imageName, ExpectedServerAttributes expectedServerA throws IOException, InterruptedException { startTarget(imageName); - //TODO support 404 -// assertServerHandler(expectedServerAttributes); + // TODO support 404 + // assertServerHandler(expectedServerAttributes); assertWebAppTrace(expectedServerAttributes); } } From 815618fccf58f94cc258ca5111bf62bb5df17260 Mon Sep 17 00:00:00 2001 From: Nikita Salnikov-Tarnovski Date: Thu, 10 Dec 2020 16:09:46 +0200 Subject: [PATCH 3/4] Better test name --- .../test/java/com/splunk/opentelemetry/WildFlySmokeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java b/smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java index e95358bce..b440aada5 100644 --- a/smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java +++ b/smoke-tests/src/test/java/com/splunk/opentelemetry/WildFlySmokeTest.java @@ -61,7 +61,7 @@ private static Stream supportedConfigurations() { WILDFLY_21_SERVER_ATTRIBUTES)); } - @ParameterizedTest + @ParameterizedTest(name = "[{index}] {0}") @MethodSource("supportedConfigurations") void wildflySmokeTest(String imageName, ExpectedServerAttributes expectedServerAttributes) throws IOException, InterruptedException { From 4009e0007ee6eaa608c0e6fa7ebdd3412405becd Mon Sep 17 00:00:00 2001 From: Nikita Salnikov-Tarnovski Date: Thu, 10 Dec 2020 17:12:07 +0200 Subject: [PATCH 4/4] Instrument ServerEnvironment --- instrumentation/build.gradle | 1 + ...WildFlyAttributesInstrumentationModule.java | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/instrumentation/build.gradle b/instrumentation/build.gradle index 0e322d0c5..c44b528f6 100644 --- a/instrumentation/build.gradle +++ b/instrumentation/build.gradle @@ -12,6 +12,7 @@ subprojects { dependencies { compileOnly("io.opentelemetry:opentelemetry-sdk:${versions.opentelemetry}") compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-tooling:${versions.opentelemetryJavaagent}") + compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-api:${versions.opentelemetryJavaagent}") compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-spi:${versions.opentelemetryJavaagent}") compileOnly("net.bytebuddy:byte-buddy:1.10.10") annotationProcessor("com.google.auto.service:auto-service:1.0-rc3") diff --git a/instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java b/instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java index d5f18278a..4b7530797 100644 --- a/instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java +++ b/instrumentation/wildfly/src/main/java/com/splunk/opentelemetry/middleware/WildFlyAttributesInstrumentationModule.java @@ -17,12 +17,12 @@ package com.splunk.opentelemetry.middleware; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isStatic; +import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.named; import com.google.auto.service.AutoService; import com.splunk.opentelemetry.javaagent.bootstrap.MiddlewareHolder; +import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Collections; @@ -55,22 +55,28 @@ public static class Instrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { - return named("org.jboss.as.version.ProductConfig"); + return named("org.jboss.as.server.ServerEnvironment"); } @Override public Map, String> transformers() { return Collections.singletonMap( - isMethod().and(isStatic()).and(named("fromFilesystemSlot")), + isConstructor(), WildFlyAttributesInstrumentationModule.class.getName() + "$MiddlewareInitializedAdvice"); } } @SuppressWarnings("unused") public static class MiddlewareInitializedAdvice { + @Advice.OnMethodEnter + public static void onEnter() { + CallDepthThreadLocalMap.incrementCallDepth(ProductConfig.class); + } + @Advice.OnMethodExit(suppress = Throwable.class) - public static void onExit(@Advice.Return ProductConfig productConfig) { - if (productConfig != null) { + public static void onExit(@Advice.FieldValue("productConfig") ProductConfig productConfig) { + if (CallDepthThreadLocalMap.decrementCallDepth(ProductConfig.class) == 0 + && productConfig != null) { MiddlewareHolder.trySetName(productConfig.resolveName()); MiddlewareHolder.trySetVersion(productConfig.resolveVersion()); }