From 372d75403053c1eb81d3cc4ec696a675fab1da71 Mon Sep 17 00:00:00 2001 From: ForestWang123 <33124174+ForestWang123@users.noreply.github.com> Date: Fri, 10 Jun 2022 21:24:46 +0800 Subject: [PATCH] Fix argument type name in postgresql plugin and add type name checking (#194) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix argument type name of Array in postgresql-8.x-plugin and add type name checking in ArgumentTypeNameMatch and ReturnTypeNameMatch * Update docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md * fix methods matchers in PgStatementInstrumentation Co-authored-by: 吴晟 Wu Sheng --- CHANGES.md | 3 + .../bytebuddy/ArgumentTypeNameMatch.java | 2 + .../bytebuddy/ArrayTypeNameChecker.java | 28 +++++++ .../plugin/bytebuddy/ReturnTypeNameMatch.java | 1 + .../bytebuddy/ArgumentTypeNameMatchTest.java | 44 +++++++++++ .../agent/core/plugin/bytebuddy/Person.java | 22 ++++++ .../bytebuddy/ReturnTypeNameMatchTest.java | 14 +++- .../define/ConnectionInstrumentation.java | 2 +- .../define/PgStatementInstrumentation.java | 12 +-- .../define/ConnectionInstrumentationTest.java | 47 +++++++++++ .../PgStatementInstrumentationTest.java | 78 +++++++++++++++++++ .../Java-Plugin-Development-Guide.md | 11 ++- 12 files changed, 253 insertions(+), 11 deletions(-) create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArrayTypeNameChecker.java create mode 100644 apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArgumentTypeNameMatchTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/ConnectionInstrumentationTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/PgStatementInstrumentationTest.java diff --git a/CHANGES.md b/CHANGES.md index 9f870b9d4..5edd9e0ee 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,9 @@ Release Notes. * Support `-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector` in gRPC log report. * Fix tcnative libraries relocation for aarch64. * Add `plugin.jdbc.trace_sql_parameters` into Configuration Discovery Service. +* Fix argument type name of Array in postgresql-8.x-plugin from java.lang.String[] to [Ljava.lang.String; +* Add type name checking in ArgumentTypeNameMatch and ReturnTypeNameMatch +* Highlight ArgumentTypeNameMatch and ReturnTypeNameMatch type naming rule in docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md #### Documentation diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArgumentTypeNameMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArgumentTypeNameMatch.java index cc09ff673..2dae17640 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArgumentTypeNameMatch.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArgumentTypeNameMatch.java @@ -46,6 +46,8 @@ public class ArgumentTypeNameMatch implements ElementMatcher * @param argumentTypeName target argument type */ private ArgumentTypeNameMatch(int index, String argumentTypeName) { + ArrayTypeNameChecker.check(argumentTypeName); + this.index = index; this.argumentTypeName = argumentTypeName; } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArrayTypeNameChecker.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArrayTypeNameChecker.java new file mode 100644 index 000000000..e16f381be --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArrayTypeNameChecker.java @@ -0,0 +1,28 @@ +/* + * 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. + * + */ + +package org.apache.skywalking.apm.agent.core.plugin.bytebuddy; + +public class ArrayTypeNameChecker { + + public static void check(String typeName) { + if (typeName.endsWith("[]")) { + throw new IllegalArgumentException("Please use [Lxxx; to define an Array type, and ref to JVM Specification for details"); + } + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ReturnTypeNameMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ReturnTypeNameMatch.java index 11592ba15..290542b77 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ReturnTypeNameMatch.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ReturnTypeNameMatch.java @@ -41,6 +41,7 @@ public class ReturnTypeNameMatch implements ElementMatcher { * @param returnTypeName target return type */ private ReturnTypeNameMatch(String returnTypeName) { + ArrayTypeNameChecker.check(returnTypeName); this.returnTypeName = returnTypeName; } diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArgumentTypeNameMatchTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArgumentTypeNameMatchTest.java new file mode 100644 index 000000000..ecad86684 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ArgumentTypeNameMatchTest.java @@ -0,0 +1,44 @@ +/* + * 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. + * + */ + +package org.apache.skywalking.apm.agent.core.plugin.bytebuddy; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.junit.Assert; +import org.junit.Test; + +public class ArgumentTypeNameMatchTest { + + @Test + public void testMatch() throws Exception { + final ElementMatcher matcherPerson = ArgumentTypeNameMatch.takesArgumentWithType(0, "org.apache.skywalking.apm.agent.core.plugin.bytebuddy.Person"); + Assert.assertTrue(matcherPerson.matches(new MethodDescription.ForLoadedMethod(Person.class.getMethod("isOlderThan", Person.class)))); + Assert.assertFalse(matcherPerson.matches(new MethodDescription.ForLoadedMethod(Person.class.getMethod("isMemberOf", Person[].class)))); + + final ElementMatcher matcherPersonArray = ArgumentTypeNameMatch.takesArgumentWithType(0, "[Lorg.apache.skywalking.apm.agent.core.plugin.bytebuddy.Person;"); + Assert.assertTrue(matcherPersonArray.matches(new MethodDescription.ForLoadedMethod(Person.class.getMethod("isMemberOf", Person[].class)))); + Assert.assertFalse(matcherPersonArray.matches(new MethodDescription.ForLoadedMethod(Person.class.getMethod("isOlderThan", Person.class)))); + } + + @Test (expected = IllegalArgumentException.class) + public void testMatchWithException() { + ArgumentTypeNameMatch.takesArgumentWithType(0, "org.apache.skywalking.apm.agent.core.plugin.bytebuddy.Person[]"); + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/Person.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/Person.java index f26b0a72e..89ce815b1 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/Person.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/Person.java @@ -40,4 +40,26 @@ public class Person { return age; } + public boolean isOlderThan(Person anotherPerson) { + return this.age > anotherPerson.age; + } + + public boolean isMemberOf(Person[] persons) { + for (Person person: persons) { + if (person == this) { + return true; + } + } + + return false; + } + + public Person[] getFriends() { + return null; + } + + public Person getBestFriend() { + return null; + } + } diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ReturnTypeNameMatchTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ReturnTypeNameMatchTest.java index ac827bf2e..d865afb2b 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ReturnTypeNameMatchTest.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ReturnTypeNameMatchTest.java @@ -27,9 +27,17 @@ public class ReturnTypeNameMatchTest { @Test public void testMatch() throws Exception { - final ElementMatcher matcher = ReturnTypeNameMatch.returnsWithType("java.lang.String"); - Assert.assertTrue(matcher.matches(new MethodDescription.ForLoadedMethod(Person.class.getMethod("getName")))); - Assert.assertFalse(matcher.matches(new MethodDescription.ForLoadedMethod(Person.class.getMethod("getAge")))); + final ElementMatcher matcherString = ReturnTypeNameMatch.returnsWithType("java.lang.String"); + Assert.assertTrue(matcherString.matches(new MethodDescription.ForLoadedMethod(Person.class.getMethod("getName")))); + Assert.assertFalse(matcherString.matches(new MethodDescription.ForLoadedMethod(Person.class.getMethod("getAge")))); + + final ElementMatcher matcherPersonArray = ReturnTypeNameMatch.returnsWithType("[Lorg.apache.skywalking.apm.agent.core.plugin.bytebuddy.Person;"); + Assert.assertTrue(matcherPersonArray.matches(new MethodDescription.ForLoadedMethod(Person.class.getMethod("getFriends")))); + Assert.assertFalse(matcherPersonArray.matches(new MethodDescription.ForLoadedMethod(Person.class.getMethod("getBestFriend")))); } + @Test (expected = IllegalArgumentException.class) + public void testMatchWithException() { + ReturnTypeNameMatch.returnsWithType("org.apache.skywalking.apm.agent.core.plugin.bytebuddy.Person[]"); + } } diff --git a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/ConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/ConnectionInstrumentation.java index dfac047e0..c32b27a14 100755 --- a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/ConnectionInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/ConnectionInstrumentation.java @@ -46,7 +46,7 @@ public class ConnectionInstrumentation extends ClassInstanceMethodsEnhancePlugin private static final String PREPARE_STATEMENT_METHOD_WITH_STRING_ARRAY_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.postgresql.JDBCPrepareStatementWithStringArrayInterceptor"; public static final String PG_CONNECTION_ENHANCE_CLASS = "org.postgresql.jdbc.PgConnection"; - public static final String STRING_ARRAY_ARGUMENT_TYPE = "java.lang.String[]"; + public static final String STRING_ARRAY_ARGUMENT_TYPE = "[Ljava.lang.String;"; public static final String PG_JDBC42_CONNECTION_ENHANCE_CLASS = "org.postgresql.jdbc42.Jdbc42Connection"; public static final String PG_JDBC3_CONNECTION_ENHANCE_CLASS = "org.postgresql.jdbc3g.Jdbc3gConnection"; public static final String PG_JDBC4_CONNECTION_ENHANCE_CLASS = "org.postgresql.jdbc4.Jdbc4Connection"; diff --git a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/PgStatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/PgStatementInstrumentation.java index 8f68d15dc..657f4fa60 100755 --- a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/PgStatementInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/PgStatementInstrumentation.java @@ -26,6 +26,7 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInst import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; import static org.apache.skywalking.apm.plugin.jdbc.postgresql.Variables.PG_STATEMENT_EXECUTE_METHOD_INTERCEPTOR; @@ -43,12 +44,11 @@ public class PgStatementInstrumentation extends ClassInstanceMethodsEnhancePlugi new InstanceMethodsInterceptPoint() { @Override public ElementMatcher getMethodsMatcher() { - return named("execute").and(takesArgumentWithType(0, "java.lang.String")) - .or(named("execute").and(takesArgumentWithType(0, "java.lang.String[]"))) - .or(named("executeQuery")) - .or(named("executeUpdate").and(takesArgumentWithType(0, "java.lang.String[]"))) - .or(named("executeUpdate").and(takesArgumentWithType(0, "java.lang.String"))) - .or(named("executeLargeUpdate")); + return named("execute").and(takesArgumentWithType(0, "java.lang.String")).and(takesArguments(1)) + .or(named("execute").and(takesArgumentWithType(1, "[Ljava.lang.String;"))) + .or(named("executeQuery")) + .or(named("executeUpdate").and(takesArgumentWithType(0, "java.lang.String")).and(takesArguments(1))) + .or(named("executeUpdate").and(takesArgumentWithType(1, "[Ljava.lang.String;"))); } @Override diff --git a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/ConnectionInstrumentationTest.java b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/ConnectionInstrumentationTest.java new file mode 100644 index 000000000..2c1cf5dee --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/ConnectionInstrumentationTest.java @@ -0,0 +1,47 @@ +/* + * 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. + * + */ + +package org.apache.skywalking.apm.plugin.jdbc.postgresql.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.postgresql.jdbc.PgConnection; + +import java.lang.reflect.Array; + +public class ConnectionInstrumentationTest { + private ConnectionInstrumentation connectionInstrumentation; + + @Before + public void setUp() { + connectionInstrumentation = new ConnectionInstrumentation(); + } + + @Test + public void testMethodMatch() throws Exception { + final InstanceMethodsInterceptPoint[] interceptPoints = connectionInstrumentation.getInstanceMethodsInterceptPoints(); + Assert.assertEquals(5, interceptPoints.length); + final ElementMatcher arrayArgumentMatcher = interceptPoints[1].getMethodsMatcher(); + final MethodDescription method = new MethodDescription.ForLoadedMethod(PgConnection.class.getMethod("prepareStatement", String.class, Array.newInstance(String.class, 0).getClass())); + Assert.assertTrue(arrayArgumentMatcher.matches(method)); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/PgStatementInstrumentationTest.java b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/PgStatementInstrumentationTest.java new file mode 100644 index 000000000..f5e02847a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/define/PgStatementInstrumentationTest.java @@ -0,0 +1,78 @@ +/* + * 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. + * + */ + +package org.apache.skywalking.apm.plugin.jdbc.postgresql.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.postgresql.jdbc.PgStatement; + +import java.lang.reflect.Array; + +public class PgStatementInstrumentationTest { + private PgStatementInstrumentation pgStatementInstrumentation; + + @Before + public void setUp() { + pgStatementInstrumentation = new PgStatementInstrumentation(); + } + + @Test + public void testMethodMatch() throws Exception { + final InstanceMethodsInterceptPoint[] interceptPoints = pgStatementInstrumentation.getInstanceMethodsInterceptPoints(); + Assert.assertEquals(1, interceptPoints.length); + + final ElementMatcher arrayArgumentMatcher = interceptPoints[0].getMethodsMatcher(); + final MethodDescription methodExecuteString = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("execute", String.class)); + final MethodDescription methodExecuteStringInt = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("execute", String.class, int.class)); + final MethodDescription methodExecuteStringIntArray = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("execute", String.class, Array.newInstance(int.class, 0).getClass())); + final MethodDescription methodExecuteStringStringArray = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("execute", String.class, Array.newInstance(String.class, 0).getClass())); + + Assert.assertTrue(arrayArgumentMatcher.matches(methodExecuteString)); + Assert.assertFalse(arrayArgumentMatcher.matches(methodExecuteStringInt)); + Assert.assertFalse(arrayArgumentMatcher.matches(methodExecuteStringIntArray)); + Assert.assertTrue(arrayArgumentMatcher.matches(methodExecuteStringStringArray)); + + final MethodDescription methodExecuteUpdateString = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("executeUpdate", String.class)); + final MethodDescription methodExecuteUpdateStringInt = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("executeUpdate", String.class, int.class)); + final MethodDescription methodExecuteUpdateStringIntArray = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("executeUpdate", String.class, Array.newInstance(int.class, 0).getClass())); + final MethodDescription methodExecuteUpdateStringStringArray = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("executeUpdate", String.class, Array.newInstance(String.class, 0).getClass())); + Assert.assertTrue(arrayArgumentMatcher.matches(methodExecuteUpdateString)); + Assert.assertFalse(arrayArgumentMatcher.matches(methodExecuteUpdateStringInt)); + Assert.assertFalse(arrayArgumentMatcher.matches(methodExecuteUpdateStringIntArray)); + Assert.assertTrue(arrayArgumentMatcher.matches(methodExecuteUpdateStringStringArray)); + + final MethodDescription methodExecuteLargeUpdateString = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("executeLargeUpdate", String.class)); + final MethodDescription methodExecuteLargeUpdateStringInt = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("executeLargeUpdate", String.class, int.class)); + final MethodDescription methodExecuteLargeUpdateStringIntArray = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("executeLargeUpdate", String.class, Array.newInstance(int.class, 0).getClass())); + final MethodDescription methodExecuteLargeUpdateStringStringArray = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("executeLargeUpdate", String.class, Array.newInstance(String.class, 0).getClass())); + final MethodDescription methodExecuteLargeUpdateInvalid = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("executeLargeUpdate")); + Assert.assertFalse(arrayArgumentMatcher.matches(methodExecuteLargeUpdateString)); + Assert.assertFalse(arrayArgumentMatcher.matches(methodExecuteLargeUpdateStringInt)); + Assert.assertFalse(arrayArgumentMatcher.matches(methodExecuteLargeUpdateStringIntArray)); + Assert.assertFalse(arrayArgumentMatcher.matches(methodExecuteLargeUpdateStringStringArray)); + Assert.assertFalse(arrayArgumentMatcher.matches(methodExecuteLargeUpdateInvalid)); + + final MethodDescription methodExecuteQuery = new MethodDescription.ForLoadedMethod(PgStatement.class.getMethod("executeQuery", String.class)); + Assert.assertTrue(arrayArgumentMatcher.matches(methodExecuteQuery)); + } +} diff --git a/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md b/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md index 50ce6c98d..c86395605 100644 --- a/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md +++ b/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md @@ -297,7 +297,16 @@ public interface InstanceMethodsInterceptPoint { } ``` You may also use `Matcher` to set the target methods. Return **true** in `isOverrideArgs`, if you want to change the argument -ref in interceptor. +ref in interceptor. +Please refer to [bytebuddy](https://bytebuddy.net/#/) for details of defining `ElementMatcher`. + +In Skywalking, we provide 3 classes to facilitate `ElementMatcher` definition: +* `AnnotationTypeNameMatch`: Check on whether there is a certain annotation in the target method. +* `ReturnTypeNameMatch`: Check the return type name (package name + `.` + class name) of the target method. +* `ArgumentTypeNameMatch`: Check on the argument index and the type name (package name + `.` + class name) of the target method. + +**Attention**: +* In case of using `ReturnTypeNameMatch` and `ArgumentTypeNameMatch`, use [Lxxx; (Java file format defined in [JVM Specification](https://docs.oracle.com/javase/specs/jvms/se8/html/)) to define an Array type. For example, you should write `[Ljava.lang.String;` for `java.lang.String[]`. The following sections will tell you how to implement the interceptor.