From 28e9369e28e047276f2864551193d3eb89f45cb3 Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Tue, 12 Oct 2021 11:07:57 +0200 Subject: [PATCH 01/12] enable jdk 17 + disable 15,16 --- Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 73955e5aeb..fff526e9e3 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -334,7 +334,8 @@ pipeline { axis { // the list of support java versions can be found in the infra repo (ansible/roles/java/defaults/main.yml) name 'JAVA_VERSION' - values 'openjdk12', 'openjdk13', 'openjdk14', 'openjdk15', 'openjdk16' + values 'openjdk12', 'openjdk13', 'openjdk14', 'openjdk17' + } } stages { From 47656f3a2552de3a82d8e47783b31c57e6464ee9 Mon Sep 17 00:00:00 2001 From: eyalkoren <41850454+eyalkoren@users.noreply.github.com> Date: Thu, 14 Oct 2021 12:55:55 +0300 Subject: [PATCH 02/12] Adding utility to mock environment variables --- apm-agent-core/pom.xml | 7 -- .../apm/agent/impl/context/MessageTest.java | 18 +++++ .../agent/impl/payload/ContainerInfoTest.java | 29 ++++--- .../SystemAllEnvVariablesInstrumentation.java | 52 ++++++++++++ .../SystemEnvVariableInstrumentation.java | 79 +++++++++++++++++++ ...stemSingleEnvVariablesInstrumentation.java | 53 +++++++++++++ .../apm/agent/util/CustomEnvVariables.java | 67 ++++++++++++++++ ...ic.apm.agent.sdk.ElasticApmInstrumentation | 2 + 8 files changed, 287 insertions(+), 20 deletions(-) create mode 100644 apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemAllEnvVariablesInstrumentation.java create mode 100644 apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemEnvVariableInstrumentation.java create mode 100644 apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemSingleEnvVariablesInstrumentation.java create mode 100644 apm-agent-core/src/test/java/co/elastic/apm/agent/util/CustomEnvVariables.java create mode 100644 apm-agent-core/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation diff --git a/apm-agent-core/pom.xml b/apm-agent-core/pom.xml index c2bcd4feb5..ec0e880a51 100644 --- a/apm-agent-core/pom.xml +++ b/apm-agent-core/pom.xml @@ -140,13 +140,6 @@ 1.2 test - - - com.github.stefanbirkner - system-lambda - 1.1.0 - test - org.apache.httpcomponents httpclient diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/context/MessageTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/context/MessageTest.java index e247cd20a0..46200a1894 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/context/MessageTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/context/MessageTest.java @@ -1,3 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 co.elastic.apm.agent.impl.context; import org.junit.jupiter.api.Test; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/payload/ContainerInfoTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/payload/ContainerInfoTest.java index 8281c88357..214580ec0c 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/payload/ContainerInfoTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/payload/ContainerInfoTest.java @@ -18,16 +18,19 @@ */ package co.elastic.apm.agent.impl.payload; +import co.elastic.apm.agent.util.CustomEnvVariables; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnJre; import org.junit.jupiter.api.condition.JRE; import javax.annotation.Nullable; -import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable; +import java.util.HashMap; +import java.util.Map; + import static org.assertj.core.api.Assertions.assertThat; -public class ContainerInfoTest { +public class ContainerInfoTest extends CustomEnvVariables { @Test void testContainerIdParsing() { @@ -142,25 +145,25 @@ void testKubernetesDownwardApi() throws Exception { String podName = "downward-api-pod-name"; String nodeName = "downward-api-node-name"; String namespace = "downward-api-namespace"; - withEnvironmentVariable("KUBERNETES_NODE_NAME", nodeName) - .and("KUBERNETES_POD_NAME", podName) - .and("KUBERNETES_NAMESPACE", namespace) - .and("KUBERNETES_POD_UID", podUid) - .execute(systemInfo::findContainerDetails); + + Map mockedEnv = new HashMap<>(); + mockedEnv.put("KUBERNETES_NODE_NAME", nodeName); + mockedEnv.put("KUBERNETES_POD_NAME", podName); + mockedEnv.put("KUBERNETES_NAMESPACE", namespace); + mockedEnv.put("KUBERNETES_POD_UID", podUid); + runWithCustomEnvVariables(mockedEnv, systemInfo::findContainerDetails); assertKubernetesInfo(systemInfo, podUid, podName, nodeName, namespace); // test partial settings systemInfo = assertContainerId(line, containerId); assertKubernetesInfo(systemInfo, originalPodUid, hostName, null, null); - withEnvironmentVariable("KUBERNETES_NODE_NAME", nodeName) - .and("KUBERNETES_POD_NAME", null) - .and("KUBERNETES_NAMESPACE", namespace) - .and("KUBERNETES_POD_UID", null) - .execute(systemInfo::findContainerDetails); - systemInfo.findContainerDetails(); + mockedEnv.put("KUBERNETES_POD_NAME", null); + mockedEnv.put("KUBERNETES_POD_UID", null); + runWithCustomEnvVariables(mockedEnv, systemInfo::findContainerDetails); assertKubernetesInfo(systemInfo, originalPodUid, hostName, nodeName, namespace); } + private SystemInfo createSystemInfo() { return new SystemInfo("arch", "my-host", "platform"); } diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemAllEnvVariablesInstrumentation.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemAllEnvVariablesInstrumentation.java new file mode 100644 index 0000000000..5c8dec40a7 --- /dev/null +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemAllEnvVariablesInstrumentation.java @@ -0,0 +1,52 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 co.elastic.apm.agent.testinstr; + +import co.elastic.apm.agent.sdk.advice.AssignTo; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import java.util.HashMap; +import java.util.Map; + +import static net.bytebuddy.matcher.ElementMatchers.isStatic; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments; + +public class SystemAllEnvVariablesInstrumentation extends SystemEnvVariableInstrumentation { + + @Override + public ElementMatcher getMethodMatcher() { + return isStatic().and(named("getenv").and(takesNoArguments())); + } + + public static class AdviceClass { + @AssignTo.Return + @Advice.OnMethodExit(onThrowable = Throwable.class, inline = false) + public static Map appendToEnvVariables(@Advice.Return Map ret) { + Map customEnvVariables = customEnvVariablesTL.get(); + if (customEnvVariables != null && !customEnvVariables.isEmpty()) { + ret = new HashMap<>(ret); + ret.putAll(customEnvVariables); + } + return ret; + } + } +} diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemEnvVariableInstrumentation.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemEnvVariableInstrumentation.java new file mode 100644 index 0000000000..dce66111c6 --- /dev/null +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemEnvVariableInstrumentation.java @@ -0,0 +1,79 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 co.elastic.apm.agent.testinstr; + +import co.elastic.apm.agent.bci.TracerAwareInstrumentation; +import co.elastic.apm.agent.sdk.advice.AssignTo; +import co.elastic.apm.agent.sdk.state.GlobalVariables; +import co.elastic.apm.agent.sdk.weakconcurrent.DetachedThreadLocal; +import co.elastic.apm.agent.sdk.weakconcurrent.WeakConcurrent; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +public abstract class SystemEnvVariableInstrumentation extends TracerAwareInstrumentation { + + protected static final DetachedThreadLocal> customEnvVariablesTL = + GlobalVariables.get(SystemEnvVariableInstrumentation.class, "customEnvVariables", WeakConcurrent.>buildThreadLocal()); + + /** + * Sets custom env variables that will be added to the actual env variables returned by {@link System#getenv()} or + * {@link System#getenv(String)} on the current thread. + * NOTE: caller must clear the custom variables when they are not required anymore through {@link #clearCustomEnvVariables()}. + * @param customEnvVariables a map of key-value pairs that will be appended to the actual environment variables + * returned by {@link System#getenv()} on the current thread + */ + public static void setCustomEnvVariables(Map customEnvVariables) { + customEnvVariablesTL.set(customEnvVariables); + } + + public static void clearCustomEnvVariables() { + customEnvVariablesTL.remove(); + } + + @Override + public ElementMatcher getTypeMatcher() { + return named("java.lang.System"); + } + + @Override + public Collection getInstrumentationGroupNames() { + return Collections.emptyList(); + } + + public static class AdviceClass { + @AssignTo.Return + @Advice.OnMethodExit(onThrowable = Throwable.class, inline = false) + public static Map appendToEnvVariables(@Advice.Return Map ret) { + Map customEnvVariables = customEnvVariablesTL.get(); + if (customEnvVariables != null && !customEnvVariables.isEmpty()) { + ret = new HashMap<>(ret); + ret.putAll(customEnvVariables); + } + return ret; + } + } +} diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemSingleEnvVariablesInstrumentation.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemSingleEnvVariablesInstrumentation.java new file mode 100644 index 0000000000..df2512ce8a --- /dev/null +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/SystemSingleEnvVariablesInstrumentation.java @@ -0,0 +1,53 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 co.elastic.apm.agent.testinstr; + +import co.elastic.apm.agent.sdk.advice.AssignTo; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import java.util.Map; + +import static net.bytebuddy.matcher.ElementMatchers.isStatic; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class SystemSingleEnvVariablesInstrumentation extends SystemEnvVariableInstrumentation { + + @Override + public ElementMatcher getMethodMatcher() { + return isStatic().and(named("getenv").and(takesArguments(1))); + } + + public static class AdviceClass { + @AssignTo.Return + @Advice.OnMethodExit(onThrowable = Throwable.class, inline = false) + public static String appendToEnvVariables(@Advice.Argument(0) String varName, @Advice.Return String ret) { + Map customEnvVariables = customEnvVariablesTL.get(); + if (customEnvVariables != null) { + String customValue = customEnvVariables.get(varName); + if (customValue != null) { + ret = customValue; + } + } + return ret; + } + } +} diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/util/CustomEnvVariables.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/util/CustomEnvVariables.java new file mode 100644 index 0000000000..4266ea7746 --- /dev/null +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/util/CustomEnvVariables.java @@ -0,0 +1,67 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 co.elastic.apm.agent.util; + +import co.elastic.apm.agent.AbstractInstrumentationTest; +import co.elastic.apm.agent.testinstr.SystemSingleEnvVariablesInstrumentation; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CustomEnvVariables extends AbstractInstrumentationTest { + + protected void runWithCustomEnvVariables(Map customEnvVariables, Runnable task) { + try { + SystemSingleEnvVariablesInstrumentation.setCustomEnvVariables(customEnvVariables); + task.run(); + } finally { + SystemSingleEnvVariablesInstrumentation.clearCustomEnvVariables(); + } + } + + @Test + void testCustomSingleEnvVariable() { + String pathVariable = "PATH"; + final String originalPath = System.getenv(pathVariable); + String mockPath = "mock/path"; + final Map customVariables = Map.of("key1", "value1", pathVariable, mockPath); + runWithCustomEnvVariables(customVariables, () -> { + String returnedPath = System.getenv(pathVariable); + assertThat(returnedPath).isEqualTo(mockPath); + }); + String returnedPath = System.getenv(pathVariable); + assertThat(returnedPath).isEqualTo(originalPath); + } + + @Test + void testSingleEnvVariables() { + final Map originalVariables = System.getenv(); + final Map customVariables = Map.of("key1", "value1", "key2", "value2"); + runWithCustomEnvVariables(customVariables, () -> { + Map returnedEnvVariables = System.getenv(); + assertThat(returnedEnvVariables).containsAllEntriesOf(originalVariables); + assertThat(returnedEnvVariables).containsAllEntriesOf(customVariables); + }); + Map returnedEnvVariables = System.getenv(); + assertThat(returnedEnvVariables).containsAllEntriesOf(originalVariables); + customVariables.forEach((key, value) -> assertThat(returnedEnvVariables).doesNotContainEntry(key, value)); + } +} diff --git a/apm-agent-core/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation b/apm-agent-core/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation new file mode 100644 index 0000000000..00c265d091 --- /dev/null +++ b/apm-agent-core/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation @@ -0,0 +1,2 @@ +co.elastic.apm.agent.testinstr.SystemSingleEnvVariablesInstrumentation +co.elastic.apm.agent.testinstr.SystemAllEnvVariablesInstrumentation From f6e4c1cd34a3cba9c71fbef8f82b4f9cb306c9ca Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Tue, 19 Oct 2021 11:04:48 +0200 Subject: [PATCH 03/12] update war plugin --- pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pom.xml b/pom.xml index 1bb3fbe4ba..6faafcbf55 100644 --- a/pom.xml +++ b/pom.xml @@ -437,6 +437,10 @@ maven-jar-plugin 3.2.0 + + maven-war-plugin + 3.3.2 + maven-dependency-plugin 3.1.1 From 91070c6152284e3dcdcc822e8dd675be1a7727bf Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Tue, 19 Oct 2021 11:21:54 +0200 Subject: [PATCH 04/12] update maven to 3.8.3 --- .mvn/wrapper/MavenWrapperDownloader.java | 51 +++++++++++++---------- .mvn/wrapper/maven-wrapper.jar | Bin 48336 -> 50710 bytes .mvn/wrapper/maven-wrapper.properties | 3 +- mvnw | 34 ++++++++++++--- mvnw.cmd | 43 ++++++++++++++----- pom.xml | 4 ++ 6 files changed, 96 insertions(+), 39 deletions(-) mode change 100755 => 100644 .mvn/wrapper/MavenWrapperDownloader.java mode change 100755 => 100644 .mvn/wrapper/maven-wrapper.jar mode change 100755 => 100644 .mvn/wrapper/maven-wrapper.properties mode change 100755 => 100644 mvnw.cmd diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java old mode 100755 new mode 100644 index d475a89ce1..b901097f2d --- a/.mvn/wrapper/MavenWrapperDownloader.java +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -1,22 +1,18 @@ /* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you 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. -*/ - + * Copyright 2007-present the original author or authors. + * + * 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. + */ import java.net.*; import java.io.*; import java.nio.channels.*; @@ -24,11 +20,12 @@ Licensed to the Apache Software Foundation (ASF) under one public class MavenWrapperDownloader { + private static final String WRAPPER_VERSION = "0.5.6"; /** * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar"; + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; /** * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to @@ -76,13 +73,13 @@ public static void main(String args[]) { } } } - System.out.println("- Downloading from: : " + url); + System.out.println("- Downloading from: " + url); File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); if(!outputFile.getParentFile().exists()) { if(!outputFile.getParentFile().mkdirs()) { System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); } } System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); @@ -98,6 +95,16 @@ public static void main(String args[]) { } private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } URL website = new URL(urlString); ReadableByteChannel rbc; rbc = Channels.newChannel(website.openStream()); diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar old mode 100755 new mode 100644 index 08ebbb67f088c53eac9a4e2cb019b93f69a1e49c..2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054 GIT binary patch delta 13080 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 b<&wLWA$|}6?E}OIh(b&V2%NINfAjwU{j*B4 diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties old mode 100755 new mode 100644 index 10673ca737..a9f1ef87bb --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1 +1,2 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/mvnw b/mvnw index 961a825001..41c0f0c23d 100755 --- a/mvnw +++ b/mvnw @@ -19,7 +19,7 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script +# Maven Start Up Batch script # # Required ENV vars: # ------------------ @@ -114,7 +114,6 @@ if $mingw ; then M2_HOME="`(cd "$M2_HOME"; pwd)`" [ -n "$JAVA_HOME" ] && JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? fi if [ -z "$JAVA_HOME" ]; then @@ -212,7 +211,11 @@ else if [ "$MVNW_VERBOSE" = true ]; then echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar" + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi while IFS="=" read key value; do case "$key" in (wrapperUrl) jarUrl="$value"; break ;; esac @@ -221,22 +224,38 @@ else echo "Downloading from: $jarUrl" fi wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi if command -v wget > /dev/null; then if [ "$MVNW_VERBOSE" = true ]; then echo "Found wget ... using wget" fi - wget "$jarUrl" -O "$wrapperJarPath" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi elif command -v curl > /dev/null; then if [ "$MVNW_VERBOSE" = true ]; then echo "Found curl ... using curl" fi - curl -o "$wrapperJarPath" "$jarUrl" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + else if [ "$MVNW_VERBOSE" = true ]; then echo "Falling back to using Java to download" fi javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi if [ -e "$javaClass" ]; then if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then if [ "$MVNW_VERBOSE" = true ]; then @@ -277,6 +296,11 @@ if $cygwin; then MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` fi +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain exec "$JAVACMD" \ diff --git a/mvnw.cmd b/mvnw.cmd old mode 100755 new mode 100644 index 830073a17e..86115719e5 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -18,7 +18,7 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script +@REM Maven Start Up Batch script @REM @REM Required ENV vars: @REM JAVA_HOME - location of a JDK home dir @@ -26,7 +26,7 @@ @REM Optional ENV vars @REM M2_HOME - location of maven2's installed home dir @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven @REM e.g. to debug Maven itself, use @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 @@ -37,7 +37,7 @@ @echo off @REM set title of command window title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% @REM set %HOME% to equivalent of $HOME @@ -120,23 +120,44 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B ) @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central @REM This allows using the maven wrapper in projects that prohibit checking in binary data. if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) ) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) ) @REM End of extension +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* if ERRORLEVEL 1 goto error goto end diff --git a/pom.xml b/pom.xml index 6faafcbf55..5b0efdfefd 100644 --- a/pom.xml +++ b/pom.xml @@ -53,6 +53,10 @@ + + 3.8.3 + + apm-agent-core elastic-apm-agent From 0e671a5dd7473aa25942043edfc0fac22ab34845 Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Tue, 19 Oct 2021 11:23:46 +0200 Subject: [PATCH 05/12] update javadoc plugin version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5b0efdfefd..b6822bdbc0 100644 --- a/pom.xml +++ b/pom.xml @@ -463,7 +463,7 @@ maven-javadoc-plugin - 3.2.0 + 3.3.1 org.codehaus.mojo From a1181aa93d50e85a0d88ae217e523a7a0c3bdeb1 Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Wed, 20 Oct 2021 10:19:18 +0200 Subject: [PATCH 06/12] log4j1 broken on Java 17, just disable tests --- .../shader/LogShadingInstrumentationTest.java | 7 +++++-- .../apm/agent/log4j1/Log4j1ShadingTest.java | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/apm-agent-plugins/apm-log-shader-plugin/apm-log-shader-plugin-common/src/test/java/co/elastic/apm/agent/log/shader/LogShadingInstrumentationTest.java b/apm-agent-plugins/apm-log-shader-plugin/apm-log-shader-plugin-common/src/test/java/co/elastic/apm/agent/log/shader/LogShadingInstrumentationTest.java index db93cfe597..dccc96aa00 100644 --- a/apm-agent-plugins/apm-log-shader-plugin/apm-log-shader-plugin-common/src/test/java/co/elastic/apm/agent/log/shader/LogShadingInstrumentationTest.java +++ b/apm-agent-plugins/apm-log-shader-plugin/apm-log-shader-plugin-common/src/test/java/co/elastic/apm/agent/log/shader/LogShadingInstrumentationTest.java @@ -344,10 +344,13 @@ private void verifyEcsFormat(String[] splitRawLogLine, JsonNode ecsLogLineTree, assertThat(ecsLogLineTree.get("event.dataset").textValue()).isEqualTo(serviceName + ".FILE"); assertThat(ecsLogLineTree.get("service.version").textValue()).isEqualTo("v42"); assertThat(ecsLogLineTree.get("some.field").textValue()).isEqualTo("some-value"); + JsonNode jsonTraceId = ecsLogLineTree.get("trace.id"); if (traceId != null) { - assertThat(ecsLogLineTree.get("trace.id").textValue()).isEqualTo(traceId); + assertThat(jsonTraceId) + .map(JsonNode::asText) + .isEqualTo(traceId); } else { - assertThat(ecsLogLineTree.get("trace.id")).isNull(); + assertThat(jsonTraceId).isNull(); } } diff --git a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/Log4j1ShadingTest.java b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/Log4j1ShadingTest.java index b5f816b0e6..ac20ee4377 100644 --- a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/Log4j1ShadingTest.java +++ b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/Log4j1ShadingTest.java @@ -25,6 +25,9 @@ import org.apache.log4j.Logger; import org.apache.log4j.MDC; import org.apache.log4j.PropertyConfigurator; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnJre; +import org.junit.jupiter.api.condition.JRE; import java.io.File; import java.util.Objects; @@ -44,6 +47,20 @@ protected void waitForFileRolling() { await().untilAsserted(() -> assertThat(new File(getShadeLogFilePath()).length()).isEqualTo(0)); } + @Test + @Override + @DisabledOnJre(value = JRE.JAVA_17, disabledReason = "log4j1 MDC is broken in Java 17 due to bogus version detection in org.apache.log4j.helpers.Loader") + public void testShadingIntoOriginalLogsDir() throws Exception { + super.testShadingIntoOriginalLogsDir(); + } + + @Test + @Override + @DisabledOnJre(value = JRE.JAVA_17, disabledReason = "log4j1 MDC is broken in Java 17 due to bogus version detection in org.apache.log4j.helpers.Loader") + public void testSimpleLogShading() throws Exception { + super.testSimpleLogShading(); + } + private static class Log4j1LoggerFacade implements LoggerFacade { private Logger log4j1Logger; From 8848fd8bbbe7442ea3167a58c2fee0da20f095ff Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Wed, 20 Oct 2021 10:48:45 +0200 Subject: [PATCH 07/12] add log4j1 instrumentation for test --- .../OptionsConverterInstrumentation.java | 54 +++++++++++++++++++ ...ic.apm.agent.sdk.ElasticApmInstrumentation | 1 + 2 files changed, 55 insertions(+) create mode 100644 apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java create mode 100644 apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation diff --git a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java new file mode 100644 index 0000000000..d7935cbbea --- /dev/null +++ b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java @@ -0,0 +1,54 @@ +package co.elastic.apm.agent.testinstr; + +import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; +import co.elastic.apm.agent.sdk.advice.AssignTo; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Collections; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * Instruments {@link org.apache.log4j.helpers.OptionConverter} to make {@link org.apache.log4j.helpers.Loader} work as + * expected on Java 17+. As log4j1 is now EOL http://logging.apache.org/log4j/1.2/ it's the best way to keep our tests + * active and relevant on this feature. + */ +public class OptionsConverterInstrumentation extends ElasticApmInstrumentation { + + @Override + public ElementMatcher getTypeMatcher() { + return named("org.apache.log4j.helpers.OptionConverter"); + } + + @Override + public ElementMatcher getMethodMatcher() { + return named("getSystemProperty"); + } + + @Override + public Collection getInstrumentationGroupNames() { + return Collections.emptyList(); + } + + public static class AdviceClass { + + @AssignTo.Return + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class, inline = false) + public static String onExit(@Advice.Return @Nullable String returnValue) { + if (returnValue == null) { + return null; + } + + if (returnValue.indexOf('.') < 0) { + return returnValue + ".0"; + } else { + return returnValue; + } + } + } +} diff --git a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation new file mode 100644 index 0000000000..37d2c95a29 --- /dev/null +++ b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation @@ -0,0 +1 @@ +co.elastic.apm.agent.testinstr.OptionsConverterInstrumentation From c3e3f4a9255500307f9173bbe6b05fd852b8a228 Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Wed, 20 Oct 2021 11:04:23 +0200 Subject: [PATCH 08/12] fix log4j1 to keep testing it --- .../shader/LogShadingInstrumentationTest.java | 5 ++--- .../apm/agent/log4j1/Log4j1ShadingTest.java | 17 --------------- .../OptionsConverterInstrumentation.java | 21 +++++++++++++++++-- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/apm-agent-plugins/apm-log-shader-plugin/apm-log-shader-plugin-common/src/test/java/co/elastic/apm/agent/log/shader/LogShadingInstrumentationTest.java b/apm-agent-plugins/apm-log-shader-plugin/apm-log-shader-plugin-common/src/test/java/co/elastic/apm/agent/log/shader/LogShadingInstrumentationTest.java index dccc96aa00..d32b75acd4 100644 --- a/apm-agent-plugins/apm-log-shader-plugin/apm-log-shader-plugin-common/src/test/java/co/elastic/apm/agent/log/shader/LogShadingInstrumentationTest.java +++ b/apm-agent-plugins/apm-log-shader-plugin/apm-log-shader-plugin-common/src/test/java/co/elastic/apm/agent/log/shader/LogShadingInstrumentationTest.java @@ -346,9 +346,8 @@ private void verifyEcsFormat(String[] splitRawLogLine, JsonNode ecsLogLineTree, assertThat(ecsLogLineTree.get("some.field").textValue()).isEqualTo("some-value"); JsonNode jsonTraceId = ecsLogLineTree.get("trace.id"); if (traceId != null) { - assertThat(jsonTraceId) - .map(JsonNode::asText) - .isEqualTo(traceId); + assertThat(jsonTraceId).isNotNull(); + assertThat(jsonTraceId.asText()).isEqualTo(traceId); } else { assertThat(jsonTraceId).isNull(); } diff --git a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/Log4j1ShadingTest.java b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/Log4j1ShadingTest.java index ac20ee4377..b5f816b0e6 100644 --- a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/Log4j1ShadingTest.java +++ b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/Log4j1ShadingTest.java @@ -25,9 +25,6 @@ import org.apache.log4j.Logger; import org.apache.log4j.MDC; import org.apache.log4j.PropertyConfigurator; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledOnJre; -import org.junit.jupiter.api.condition.JRE; import java.io.File; import java.util.Objects; @@ -47,20 +44,6 @@ protected void waitForFileRolling() { await().untilAsserted(() -> assertThat(new File(getShadeLogFilePath()).length()).isEqualTo(0)); } - @Test - @Override - @DisabledOnJre(value = JRE.JAVA_17, disabledReason = "log4j1 MDC is broken in Java 17 due to bogus version detection in org.apache.log4j.helpers.Loader") - public void testShadingIntoOriginalLogsDir() throws Exception { - super.testShadingIntoOriginalLogsDir(); - } - - @Test - @Override - @DisabledOnJre(value = JRE.JAVA_17, disabledReason = "log4j1 MDC is broken in Java 17 due to bogus version detection in org.apache.log4j.helpers.Loader") - public void testSimpleLogShading() throws Exception { - super.testSimpleLogShading(); - } - private static class Log4j1LoggerFacade implements LoggerFacade { private Logger log4j1Logger; diff --git a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java index d7935cbbea..215b5bf074 100644 --- a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java +++ b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java @@ -1,7 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 co.elastic.apm.agent.testinstr; import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; -import co.elastic.apm.agent.sdk.advice.AssignTo; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; @@ -37,7 +54,7 @@ public Collection getInstrumentationGroupNames() { public static class AdviceClass { - @AssignTo.Return + @Advice.AssignReturned.ToReturned @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class, inline = false) public static String onExit(@Advice.Return @Nullable String returnValue) { if (returnValue == null) { From 13d29ea7054b75bde37d30dcbb82955c8b2604b7 Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Fri, 3 Dec 2021 09:52:24 +0100 Subject: [PATCH 09/12] fix typo --- .../elastic/apm/agent/bci/bytebuddy/ErrorLoggingListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/bytebuddy/ErrorLoggingListener.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/bytebuddy/ErrorLoggingListener.java index bfe0abff9e..311fd0b2ea 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/bytebuddy/ErrorLoggingListener.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/bytebuddy/ErrorLoggingListener.java @@ -30,7 +30,7 @@ public class ErrorLoggingListener extends AgentBuilder.Listener.Adapter { @Override public void onError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded, Throwable throwable) { if (throwable instanceof MinimumClassFileVersionValidator.UnsupportedClassFileVersionException) { - logger.warn("{} uses an unsupported class file version (pre Java {}}) and can't be instrumented. " + + logger.warn("{} uses an unsupported class file version (pre Java {})) and can't be instrumented. " + "Consider updating to a newer version of that library.", typeName, ((MinimumClassFileVersionValidator.UnsupportedClassFileVersionException)throwable).getMinVersion()); From 3189745b7445ede32f02f0e3c149071b68972688 Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Fri, 3 Dec 2021 11:18:49 +0100 Subject: [PATCH 10/12] fix log correlaction plugin --- .../testinstr/OptionConverterInstrumentation.java | 11 +++++++---- .../apm/agent/mdc/MdcActivationListenerTest.java | 3 +++ ...co.elastic.apm.agent.sdk.ElasticApmInstrumentation | 2 ++ ...co.elastic.apm.agent.sdk.ElasticApmInstrumentation | 3 ++- 4 files changed, 14 insertions(+), 5 deletions(-) rename apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java => apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/OptionConverterInstrumentation.java (84%) create mode 100644 apm-agent-plugins/apm-log-correlation-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation diff --git a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/OptionConverterInstrumentation.java similarity index 84% rename from apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java rename to apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/OptionConverterInstrumentation.java index 215b5bf074..ed09dd28c4 100644 --- a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/testinstr/OptionsConverterInstrumentation.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/testinstr/OptionConverterInstrumentation.java @@ -35,7 +35,7 @@ * expected on Java 17+. As log4j1 is now EOL http://logging.apache.org/log4j/1.2/ it's the best way to keep our tests * active and relevant on this feature. */ -public class OptionsConverterInstrumentation extends ElasticApmInstrumentation { +public class OptionConverterInstrumentation extends ElasticApmInstrumentation { @Override public ElementMatcher getTypeMatcher() { @@ -56,12 +56,15 @@ public static class AdviceClass { @Advice.AssignReturned.ToReturned @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class, inline = false) - public static String onExit(@Advice.Return @Nullable String returnValue) { - if (returnValue == null) { - return null; + public static String onExit(@Advice.Argument(0) String key, + @Advice.Return @Nullable String returnValue) { + + if (returnValue == null || !"java.version".equals(key)) { + return returnValue; } if (returnValue.indexOf('.') < 0) { + // just convert '17' to '17.0' to make Log4j simple version parsing work and not assume Java 1.x return returnValue + ".0"; } else { return returnValue; diff --git a/apm-agent-plugins/apm-log-correlation-plugin/src/test/java/co/elastic/apm/agent/mdc/MdcActivationListenerTest.java b/apm-agent-plugins/apm-log-correlation-plugin/src/test/java/co/elastic/apm/agent/mdc/MdcActivationListenerTest.java index 5f4b8a52f7..d0ba1beb71 100644 --- a/apm-agent-plugins/apm-log-correlation-plugin/src/test/java/co/elastic/apm/agent/mdc/MdcActivationListenerTest.java +++ b/apm-agent-plugins/apm-log-correlation-plugin/src/test/java/co/elastic/apm/agent/mdc/MdcActivationListenerTest.java @@ -54,6 +54,9 @@ class MdcActivationListenerTest extends AbstractInstrumentationTest { void setUp() { org.apache.log4j.MDC.put("test", true); log4jMdcWorking = (Boolean) org.apache.log4j.MDC.get("test"); + assertThat(log4jMdcWorking) + .describedAs("MDC not working as expected") + .isNotNull(); forAllMdc(MdcImpl::clear); loggingConfiguration = config.getConfig(LoggingConfiguration.class); diff --git a/apm-agent-plugins/apm-log-correlation-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation b/apm-agent-plugins/apm-log-correlation-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation new file mode 100644 index 0000000000..61495f0b58 --- /dev/null +++ b/apm-agent-plugins/apm-log-correlation-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation @@ -0,0 +1,2 @@ +# Allows to make Log4j 1.x work on Java 17 even if not supported +co.elastic.apm.agent.testinstr.OptionConverterInstrumentation diff --git a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation index 37d2c95a29..61495f0b58 100644 --- a/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation +++ b/apm-agent-plugins/apm-log-shader-plugin/apm-log4j1-plugin/src/test/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation @@ -1 +1,2 @@ -co.elastic.apm.agent.testinstr.OptionsConverterInstrumentation +# Allows to make Log4j 1.x work on Java 17 even if not supported +co.elastic.apm.agent.testinstr.OptionConverterInstrumentation From e5cca72f6255e275cb054f8555a2965ee8eeb790 Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Fri, 3 Dec 2021 14:03:50 +0100 Subject: [PATCH 11/12] fix logging activation listener test --- .../agent/mdc/MdcActivationListenerIT.java | 46 ++----------------- 1 file changed, 3 insertions(+), 43 deletions(-) diff --git a/apm-agent-plugins/apm-log-correlation-plugin/src/test/java/co/elastic/apm/agent/mdc/MdcActivationListenerIT.java b/apm-agent-plugins/apm-log-correlation-plugin/src/test/java/co/elastic/apm/agent/mdc/MdcActivationListenerIT.java index c2e5dc294c..2d3328e07c 100644 --- a/apm-agent-plugins/apm-log-correlation-plugin/src/test/java/co/elastic/apm/agent/mdc/MdcActivationListenerIT.java +++ b/apm-agent-plugins/apm-log-correlation-plugin/src/test/java/co/elastic/apm/agent/mdc/MdcActivationListenerIT.java @@ -18,28 +18,15 @@ */ package co.elastic.apm.agent.mdc; -import co.elastic.apm.agent.MockReporter; -import co.elastic.apm.agent.bci.ElasticApmAgent; -import co.elastic.apm.agent.configuration.SpyConfiguration; -import co.elastic.apm.agent.errorlogging.Log4j2LoggerErrorCapturingInstrumentation; -import co.elastic.apm.agent.errorlogging.Slf4jLoggerErrorCapturingInstrumentation; -import co.elastic.apm.agent.impl.ElasticApmTracerBuilder; -import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.AbstractInstrumentationTest; import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.logging.LoggingConfiguration; -import net.bytebuddy.agent.ByteBuddyAgent; import org.apache.logging.log4j.ThreadContext; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assumptions; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.stubbing.Answer; import org.slf4j.Logger; import org.slf4j.MDC; -import org.stagemonitor.configuration.ConfigurationRegistry; - -import java.util.Arrays; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -48,31 +35,12 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -class MdcActivationListenerIT { +class MdcActivationListenerIT extends AbstractInstrumentationTest { - protected static ElasticApmTracer tracer; - protected static MockReporter reporter; - protected static ConfigurationRegistry config; private LoggingConfiguration loggingConfiguration; - @BeforeAll - static void beforeAll() { - reporter = new MockReporter(); - config = SpyConfiguration.createSpyConfig(); - tracer = new ElasticApmTracerBuilder() - .configurationRegistry(config) - .reporter(reporter) - .buildAndStart(); - ElasticApmAgent.initInstrumentation(tracer, ByteBuddyAgent.install(), Arrays.asList(new Slf4jLoggerErrorCapturingInstrumentation(), new Log4j2LoggerErrorCapturingInstrumentation())); - } - - @AfterAll - static void afterAll() { - ElasticApmAgent.reset(); - } - @BeforeEach - void setUp() throws Exception { + void setUp() { MDC.clear(); org.apache.log4j.MDC.clear(); ThreadContext.clearAll(); @@ -114,10 +82,6 @@ void testVerifyThatWithEnabledCorrelationAndLoggedErrorMdcErrorIdIsNotBlankWithS @Test void testVerifyThatWithEnabledCorrelationAndLoggedErrorMdcErrorIdIsNotBlankWithLog4j() { - Assumptions.assumeTrue(() -> { - org.apache.log4j.MDC.put("test", true); - return org.apache.log4j.MDC.get("test") == Boolean.TRUE; - }, "Log4j MDC is not working, this happens with some versions of Java 10 where log4j thinks it's Java 1"); when(loggingConfiguration.isLogCorrelationEnabled()).thenReturn(true); org.apache.logging.log4j.Logger logger = mock(org.apache.logging.log4j.Logger.class); doAnswer(invocation -> assertMdcErrorIdIsNotEmpty()).when(logger).error(anyString(), any(Exception.class)); @@ -135,10 +99,6 @@ void testVerifyThatWithEnabledCorrelationAndLoggedErrorMdcErrorIdIsNotBlankWithL @Test void testVerifyThatWithEnabledCorrelationAndLoggedErrorMdcErrorIdIsNotBlankWithLog4jNotInTransaction() { - Assumptions.assumeTrue(() -> { - org.apache.log4j.MDC.put("test", true); - return org.apache.log4j.MDC.get("test") == Boolean.TRUE; - }, "Log4j MDC is not working, this happens with some versions of Java 10 where log4j thinks it's Java 1"); when(loggingConfiguration.isLogCorrelationEnabled()).thenReturn(true); org.apache.logging.log4j.Logger logger = mock(org.apache.logging.log4j.Logger.class); doAnswer(invocation -> assertMdcErrorIdIsNotEmpty()).when(logger).error(anyString(), any(Exception.class)); From 121232d721e45d858f7325e3d36dcbe6ab5535f2 Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Fri, 3 Dec 2021 15:28:16 +0100 Subject: [PATCH 12/12] fix the url connection plugin test --- .../SSLContextInstrumentationTest.java | 58 ++++++++----------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/apm-agent-plugins/apm-urlconnection-plugin/src/test/java/co/elastic/apm/agent/urlconnection/SSLContextInstrumentationTest.java b/apm-agent-plugins/apm-urlconnection-plugin/src/test/java/co/elastic/apm/agent/urlconnection/SSLContextInstrumentationTest.java index 7e1b2a4398..bcb5c8ce32 100644 --- a/apm-agent-plugins/apm-urlconnection-plugin/src/test/java/co/elastic/apm/agent/urlconnection/SSLContextInstrumentationTest.java +++ b/apm-agent-plugins/apm-urlconnection-plugin/src/test/java/co/elastic/apm/agent/urlconnection/SSLContextInstrumentationTest.java @@ -20,15 +20,11 @@ import co.elastic.apm.agent.AbstractInstrumentationTest; import co.elastic.apm.agent.util.ExecutorUtils; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import javax.net.ssl.HttpsURLConnection; -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.URL; -import java.net.URLConnection; +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; @@ -36,43 +32,39 @@ class SSLContextInstrumentationTest extends AbstractInstrumentationTest { - private static Field defaultSSLSocketFactoryField; - private static ThreadPoolExecutor elasticApmThreadPool = ExecutorUtils.createSingleThreadSchedulingDaemonPool("HttpsUrlConnection-Test"); + // We can't really assert that the agent does not initialize the SSL context, but we can test how it's implemented + // thus here we just check that trying to get default SSL context/factories is not possible from agent threads. - @BeforeAll - static void setup() throws Exception { - defaultSSLSocketFactoryField = HttpsURLConnection.class.getDeclaredField("defaultSSLSocketFactory"); - defaultSSLSocketFactoryField.setAccessible(true); - defaultSSLSocketFactoryField.set(null, null); - } - - @BeforeEach - void resetState() throws Exception { - defaultSSLSocketFactoryField.set(null, null); - } + private static final ThreadPoolExecutor elasticApmThreadPool = ExecutorUtils.createSingleThreadSchedulingDaemonPool("HttpsUrlConnection-Test"); @Test - void testNonSkipped() throws Exception { - createConnection(); - Object defaultSslFactory = defaultSSLSocketFactoryField.get(null); - assertThat(defaultSslFactory).isNotNull(); - assertThat(defaultSslFactory).isEqualTo(HttpsURLConnection.getDefaultSSLSocketFactory()); + void testNonSkipped() { + createConnection(false); } @Test void testSkipped() throws Exception { - Future connectionCreationFuture = elasticApmThreadPool.submit(this::createConnection); + Future connectionCreationFuture = elasticApmThreadPool.submit(()-> createConnection(true)); connectionCreationFuture.get(); - assertThat(defaultSSLSocketFactoryField.get(null)).isNull(); - createConnection(); - assertThat(defaultSSLSocketFactoryField.get(null)).isNotNull(); } - private void createConnection() { + private void createConnection(boolean expectNull) { try { - URLConnection urlConnection = new URL("https://localhost:11111").openConnection(); - assertThat(urlConnection).isInstanceOf(HttpsURLConnection.class); - } catch (IOException e) { + SocketFactory defaultSslSocketFactory = SSLSocketFactory.getDefault(); + SSLContext defaultSslContext = SSLContext.getDefault(); + SocketFactory defaultSocketFactory = SocketFactory.getDefault(); + + if (expectNull) { + assertThat(defaultSslSocketFactory).isNull(); + assertThat(defaultSslContext).isNull(); + assertThat(defaultSocketFactory).isNull(); + } else { + assertThat(defaultSslSocketFactory).isNotNull(); + assertThat(defaultSslContext).isNotNull(); + assertThat(defaultSocketFactory).isNotNull(); + } + + } catch (Exception e) { throw new RuntimeException(e); } }