diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
index dbb70bd23..da9e76452 100755
--- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
+++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
@@ -130,4 +130,6 @@ public class ComponentsDefine {
public static final OfficialComponent SPRING_WEBFLUX = new OfficialComponent(67, "spring-webflux");
+ public static final OfficialComponent PLAY = new OfficialComponent(68, "Play");
+
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/AnnotationTypeNameMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/AnnotationTypeNameMatch.java
new file mode 100644
index 000000000..1a0da7c0e
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/AnnotationTypeNameMatch.java
@@ -0,0 +1,72 @@
+/*
+ * 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.annotation.AnnotationDescription;
+import net.bytebuddy.description.annotation.AnnotationSource;
+import net.bytebuddy.matcher.CollectionItemMatcher;
+import net.bytebuddy.matcher.DeclaringAnnotationMatcher;
+import net.bytebuddy.matcher.ElementMatcher;
+
+/**
+ * Annotation Type match.
+ * Similar with {@link net.bytebuddy.matcher.ElementMatchers#isAnnotatedWith},
+ * the only different between them is this match use {@link String} to declare the type, instead of {@link Class}.
+ * This can avoid the classloader risk.
+ *
+ *
+ * @author AI
+ * 2019-08-15
+ */
+public class AnnotationTypeNameMatch implements ElementMatcher {
+
+ /**
+ * the target annotation type
+ */
+ private String annotationTypeName;
+
+ /**
+ * declare the match target method with the certain type.
+ *
+ * @param annotationTypeName target annotation type
+ */
+ private AnnotationTypeNameMatch(String annotationTypeName) {
+ this.annotationTypeName = annotationTypeName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean matches(T target) {
+ return target.getAnnotationType().asErasure().getName().equals(annotationTypeName);
+ }
+
+ /**
+ * The static method to create {@link AnnotationTypeNameMatch}
+ * This is a delegate method to follow byte-buddy {@link ElementMatcher}'s code style.
+ *
+ * @param annotationTypeName target annotation type
+ * @param The type of the object that is being matched.
+ * @return new {@link AnnotationTypeNameMatch} instance.
+ */
+ public static ElementMatcher.Junction isAnnotatedWithType(String annotationTypeName) {
+ final AnnotationTypeNameMatch matcher = new AnnotationTypeNameMatch(annotationTypeName);
+ return new DeclaringAnnotationMatcher(new CollectionItemMatcher(matcher));
+ }
+}
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
new file mode 100644
index 000000000..c26b02f2f
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ReturnTypeNameMatch.java
@@ -0,0 +1,68 @@
+/*
+ * 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;
+
+
+/**
+ * Return Type match.
+ * Similar with {@link net.bytebuddy.matcher.ElementMatchers#returns},
+ * the only different between them is this match use {@link String} to declare the type, instead of {@link Class}.
+ * This can avoid the classloader risk.
+ *
+ *
+ * @author AI
+ * 2019-08-15
+ */
+public class ReturnTypeNameMatch implements ElementMatcher {
+
+ /**
+ * the target return type
+ */
+ private String returnTypeName;
+
+ /**
+ * declare the match target method with the certain type.
+ *
+ * @param returnTypeName target return type
+ */
+ private ReturnTypeNameMatch(String returnTypeName) {
+ this.returnTypeName = returnTypeName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean matches(MethodDescription target) {
+ return target.getReturnType().asErasure().getName().equals(returnTypeName);
+ }
+
+ /**
+ * The static method to create {@link ReturnTypeNameMatch}
+ * This is a delegate method to follow byte-buddy {@link ElementMatcher}'s code style.
+ *
+ * @param returnTypeName target return type
+ * @return new {@link ReturnTypeNameMatch} instance.
+ */
+ public static ElementMatcher returnsWithType(String returnTypeName) {
+ return new ReturnTypeNameMatch(returnTypeName);
+ }
+}
diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/AnnotationTypeNameMatchTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/AnnotationTypeNameMatchTest.java
new file mode 100644
index 000000000..ce8edd402
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/AnnotationTypeNameMatchTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * @author AI
+ * 2019-08-15
+ */
+public class AnnotationTypeNameMatchTest {
+
+ @Test
+ public void testMatch() throws Exception {
+ final ElementMatcher matcher = AnnotationTypeNameMatch.isAnnotatedWithType("org.apache.skywalking.apm.agent.core.plugin.bytebuddy.Inject");
+ Assert.assertTrue(matcher.matches(new MethodDescription.ForLoadedConstructor(Person.class.getConstructor(String.class))));
+ Assert.assertFalse(matcher.matches(new MethodDescription.ForLoadedConstructor(Person.class.getConstructor(String.class, int.class))));
+ }
+
+}
diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/Inject.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/Inject.java
new file mode 100644
index 000000000..29154d904
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/Inject.java
@@ -0,0 +1,34 @@
+/*
+ * 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 java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author AI
+ * 2019-08-15
+ */
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Inject {
+}
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
new file mode 100644
index 000000000..22da48562
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/Person.java
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+/**
+ * @author AI
+ * 2019-08-15
+ */
+public class Person {
+ private int age;
+ private String name;
+
+ @Inject
+ public Person(String name) {
+ this.name = name;
+ }
+
+ public Person(String name, int age) {
+ this.age = age;
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+}
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
new file mode 100644
index 000000000..e1cd0534b
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/bytebuddy/ReturnTypeNameMatchTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * @author AI
+ * 2019-08-15
+ */
+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"))));
+ }
+
+}
diff --git a/apm-sniffer/optional-plugins/play-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/play-2.x-plugin/pom.xml
new file mode 100644
index 000000000..8445bc439
--- /dev/null
+++ b/apm-sniffer/optional-plugins/play-2.x-plugin/pom.xml
@@ -0,0 +1,48 @@
+
+
+
+
+ 4.0.0
+
+ org.apache.skywalking
+ optional-plugins
+ 6.4.0-SNAPSHOT
+
+
+ apm-play-2.x-plugin
+ play-2.x-plugin
+ jar
+
+
+ UTF-8
+ 2.7.3
+ 1.8
+
+
+
+
+ com.typesafe.play
+ play_2.12
+ ${play2.version}
+ provided
+
+
+
+
diff --git a/apm-sniffer/optional-plugins/play-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/play/v2x/HttpFiltersInterceptor.java b/apm-sniffer/optional-plugins/play-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/play/v2x/HttpFiltersInterceptor.java
new file mode 100644
index 000000000..7c7198cf3
--- /dev/null
+++ b/apm-sniffer/optional-plugins/play-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/play/v2x/HttpFiltersInterceptor.java
@@ -0,0 +1,66 @@
+/*
+ * 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.play.v2x;
+
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import play.api.inject.Injector;
+import scala.collection.Seq;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author AI
+ * 2019-08-01
+ */
+public class HttpFiltersInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, Object ret) throws Throwable {
+ Object object = objInst.getSkyWalkingDynamicField();
+ Injector injector = (Injector) object;
+ TracingFilter filter = injector.instanceOf(TracingFilter.class);
+ Seq seq = (Seq) ret;
+ List