You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2022/08/19 10:20:38 UTC

[skywalking-java] branch main updated: Add plugin to support micronaut (#291)

This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-java.git


The following commit(s) were added to refs/heads/main by this push:
     new 4b564ade6 Add plugin to support micronaut (#291)
4b564ade6 is described below

commit 4b564ade6469e9827c63b4e7e5c97df41663000b
Author: pg.yang <pg...@hotmail.com>
AuthorDate: Fri Aug 19 18:20:32 2022 +0800

    Add plugin to support micronaut (#291)
---
 .github/workflows/plugins-test.3.yaml              |   1 +
 CHANGES.md                                         |   1 +
 .../network/trace/component/ComponentsDefine.java  |   3 +
 .../micronaut-http-client-plugin/pom.xml           |  53 +++++
 .../BuildExchangeStreamPublisherInterceptor.java   |  55 +++++
 .../http/client/ExchangeImplInterceptor.java       |  56 +++++
 .../micronaut/http/client/MicronautCommons.java    | 106 ++++++++++
 .../client/MicronautHttpClientPluginConfig.java    |  45 ++++
 .../define/MicronautClientInstrumentation.java     |  87 ++++++++
 .../src/main/resources/skywalking-plugin.def       |  17 ++
 .../micronaut-http-server-plugin/pom.xml           |  55 +++++
 .../http/server/HandleStatusErrorInterceptor.java  |  47 +++++
 .../micronaut/http/server/MicronautCommons.java    |  72 +++++++
 .../server/MicronautHttpServerPluginConfig.java    |  45 ++++
 .../http/server/RouteMatchExecuteInterceptor.java  |  44 ++++
 .../server/WriteFinalNettyResponseInterceptor.java |  67 ++++++
 .../server/define/RouteMatchInstrumentation.java   |  69 +++++++
 .../RoutingInBoundHandlerInstrumentation.java      |  87 ++++++++
 .../src/main/resources/skywalking-plugin.def       |  18 ++
 .../apm-sdk-plugin/micronaut-plugins/pom.xml       |  42 ++++
 apm-sniffer/apm-sdk-plugin/pom.xml                 |   1 +
 .../setup/service-agent/java-agent/Plugin-list.md  |   2 +
 .../service-agent/java-agent/Supported-list.md     |   2 +
 .../service-agent/java-agent/configurations.md     |   2 +
 .../micronaut-http-scenario/bin/startup.sh         |  22 ++
 .../config/expectedData.yaml                       | 191 +++++++++++++++++
 .../micronaut-http-scenario/configuration.yml      |  20 ++
 .../scenarios/micronaut-http-scenario/pom.xml      | 226 +++++++++++++++++++++
 .../src/main/assembly/assembly.xml                 |  41 ++++
 .../apm/testcase/micronaut/Application.java        |  27 +++
 .../controller/ErrorHandlerController.java         |  35 ++++
 .../micronaut/controller/HelloController.java      |  69 +++++++
 .../micronaut-http-scenario/support-version.list   |  22 ++
 33 files changed, 1630 insertions(+)

diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml
index 8fce605da..0629de603 100644
--- a/.github/workflows/plugins-test.3.yaml
+++ b/.github/workflows/plugins-test.3.yaml
@@ -68,6 +68,7 @@ jobs:
           - vertx-web-3.54minus-scenario
           - vertx-web-3.6plus-scenario
           - mariadb-scenario
+          - micronaut-http-scenario
           - quasar-scenario
           - baidu-brpc-scenario
           - retransform-class-scenario
diff --git a/CHANGES.md b/CHANGES.md
index 20e0b3516..3cf412f66 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -17,6 +17,7 @@ Release Notes.
 * Fix race condition causing agent to not reconnect after network error
 * Force the injected high-priority classes in order to avoid NoClassDefFoundError.
 * Plugin to support xxl-job 2.3.x.
+* Add plugin to support Micronaut(HTTP Client/Server) 3.2.x-3.6.x
 
 #### Documentation
 
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 c3671ff69..23d7f9f1d 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
@@ -224,4 +224,7 @@ public class ComponentsDefine {
     public static final OfficialComponent APACHE_SHENYU = new OfficialComponent(127, "Apache-ShenYu");
 
     public static final OfficialComponent HUTOOL = new OfficialComponent(128, "Hutool");
+
+    public static final OfficialComponent MICRONAUT = new OfficialComponent(131, "Micronaut");
+
 }
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml
new file mode 100644
index 000000000..1fb5f2804
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.skywalking</groupId>
+        <artifactId>micronaut-plugins</artifactId>
+        <version>8.12.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>micronaut-http-client-plugin</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.projectreactor</groupId>
+            <artifactId>reactor-core</artifactId>
+            <version>3.4.21</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>io.micronaut</groupId>
+            <artifactId>micronaut-http-client</artifactId>
+            <version>3.6.0</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/BuildExchangeStreamPublisherInterceptor.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/BuildExchangeStreamPublisherInterceptor.java
new file mode 100644
index 000000000..0eb23c51e
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/BuildExchangeStreamPublisherInterceptor.java
@@ -0,0 +1,55 @@
+/*
+ * 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.micronaut.http.client;
+
+import io.micronaut.http.HttpResponse;
+import io.micronaut.http.MutableHttpRequest;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.reactivestreams.Publisher;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.function.Function;
+import static org.apache.skywalking.apm.plugin.micronaut.http.client.MicronautCommons.beginTrace;
+import static org.apache.skywalking.apm.plugin.micronaut.http.client.MicronautCommons.buildTracePublisher;
+import static org.apache.skywalking.apm.plugin.micronaut.http.client.MicronautCommons.finish;
+
+public class BuildExchangeStreamPublisherInterceptor implements InstanceMethodsAroundInterceptor {
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        MutableHttpRequest<?> request = (MutableHttpRequest) allArguments[1];
+        Function<URI, Publisher<? extends HttpResponse<?>>> function = (Function<URI, Publisher<? extends HttpResponse<?>>>) ret;
+        return (Function<URI, Publisher<? extends HttpResponse<?>>>) uri -> {
+            beginTrace(request, uri);
+            return buildTracePublisher(request, function.apply(uri));
+        };
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+        MutableHttpRequest<?> request = (MutableHttpRequest) allArguments[1];
+        finish(request, span -> span.log(t).errorOccurred());
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/ExchangeImplInterceptor.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/ExchangeImplInterceptor.java
new file mode 100644
index 000000000..eb8dd1bcb
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/ExchangeImplInterceptor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.micronaut.http.client;
+
+import io.micronaut.http.HttpResponse;
+import io.micronaut.http.MutableHttpRequest;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.reactivestreams.Publisher;
+
+import java.lang.reflect.Method;
+import java.net.URI;
+
+import static org.apache.skywalking.apm.plugin.micronaut.http.client.MicronautCommons.finish;
+import static org.apache.skywalking.apm.plugin.micronaut.http.client.MicronautCommons.buildTracePublisher;
+import static org.apache.skywalking.apm.plugin.micronaut.http.client.MicronautCommons.beginTrace;
+
+public class ExchangeImplInterceptor implements InstanceMethodsAroundInterceptor {
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+        MutableHttpRequest<?> request = (MutableHttpRequest<?>) allArguments[2];
+        URI requestURI = (URI) allArguments[0];
+        beginTrace(request, requestURI);
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        MutableHttpRequest<?> request = (MutableHttpRequest<?>) allArguments[2];
+        Publisher<HttpResponse<?>> retPublisher = (Publisher<HttpResponse<?>>) ret;
+        return buildTracePublisher(request, retPublisher);
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+        finish((MutableHttpRequest<?>) allArguments[0], span -> span.errorOccurred().log(t));
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/MicronautCommons.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/MicronautCommons.java
new file mode 100644
index 000000000..e71d5b1e8
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/MicronautCommons.java
@@ -0,0 +1,106 @@
+/*
+ * 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.micronaut.http.client;
+
+import io.micronaut.http.HttpResponse;
+import io.micronaut.http.MutableHttpRequest;
+import io.micronaut.http.context.ServerRequestContext;
+import org.apache.skywalking.apm.agent.core.context.CarrierItem;
+import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.apache.skywalking.apm.util.StringUtil;
+import org.reactivestreams.Publisher;
+import reactor.core.publisher.Flux;
+
+import java.net.URI;
+import java.util.function.Consumer;
+
+public class MicronautCommons {
+
+    private static final String SPAN_KEY = "CORS_SPAN";
+    private static final String SKY_CONTEXT_SNAPSHOT_KEY = "CORS_SNAPSHOT";
+
+    static void beginTrace(MutableHttpRequest<?> request, URI requestURI) {
+        String requestMethod = request.getMethod().name();
+        AbstractSpan span = ContextManager.createExitSpan(requestMethod + ":" + request.getPath(), requestURI.getHost() + ":" + requestURI.getPort());
+        //The key is set in micronaut-http-server-plugin . See org.apache.skywalking.apm.plugin.micronaut.http.server#beginTrace
+        ServerRequestContext.currentRequest().flatMap(req -> req.getAttribute(SKY_CONTEXT_SNAPSHOT_KEY)).ifPresent(e -> ContextManager.continued((ContextSnapshot) e));
+        final ContextCarrier contextCarrier = new ContextCarrier();
+        ContextManager.inject(contextCarrier);
+        span.setComponent(ComponentsDefine.MICRONAUT);
+        Tags.HTTP.METHOD.set(span, requestMethod);
+        Tags.URL.set(span, String.format("%s://%s:%s%s", requestURI.getScheme(), requestURI.getHost(), requestURI.getPort(), requestURI.getPath()));
+        SpanLayer.asHttp(span);
+        CarrierItem next = contextCarrier.items();
+        while (next.hasNext()) {
+            next = next.next();
+            request.header(next.getHeadKey(), next.getHeadValue());
+        }
+        span.prepareForAsync();
+        ContextManager.stopSpan(span);
+        request.setAttribute(SPAN_KEY, span);
+        if (MicronautHttpClientPluginConfig.Plugin.MicronautHttpClient.COLLECT_HTTP_PARAMS) {
+            collectHttpParam(request, span);
+        }
+    }
+
+    static Publisher<? extends HttpResponse<?>> buildTracePublisher(MutableHttpRequest<?> request, Publisher<? extends HttpResponse<?>> retPublisher) {
+        return Flux.from(retPublisher).doOnError(ex -> finish(request, span -> span.log(ex).errorOccurred()))
+                .doOnNext(resp ->
+                        finish(request, span -> {
+                            Tags.HTTP_RESPONSE_STATUS_CODE.set(span, resp.code());
+                            if (resp.code() >= 400) {
+                                span.errorOccurred();
+                            }
+                            //Activate HTTP parameters collecting automatically in the profiling context.
+                            if (!MicronautHttpClientPluginConfig.Plugin.MicronautHttpClient.COLLECT_HTTP_PARAMS && span.isProfiling()) {
+                                collectHttpParam(request, span);
+                            }
+                        })
+                );
+    }
+
+    static void collectHttpParam(MutableHttpRequest<?> httpRequest, AbstractSpan span) {
+        String tag = httpRequest.getUri().getQuery();
+        tag = MicronautHttpClientPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ?
+                StringUtil.cut(tag, MicronautHttpClientPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tag;
+        if (StringUtil.isNotEmpty(tag)) {
+            Tags.HTTP.PARAMS.set(span, tag);
+        }
+    }
+
+    static void finish(MutableHttpRequest<?> request, Consumer<AbstractSpan> action) {
+        try {
+            request.getAttribute(SPAN_KEY)
+                    .map(span -> (AbstractSpan) span)
+                    .ifPresent(span -> {
+                        action.accept(span);
+                        span.asyncFinish();
+                    });
+        } finally {
+            request.removeAttribute(SPAN_KEY, AbstractSpan.class);
+        }
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/MicronautHttpClientPluginConfig.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/MicronautHttpClientPluginConfig.java
new file mode 100644
index 000000000..54f3aca77
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/MicronautHttpClientPluginConfig.java
@@ -0,0 +1,45 @@
+/*
+ * 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.micronaut.http.client;
+
+import org.apache.skywalking.apm.agent.core.boot.PluginConfig;
+
+public class MicronautHttpClientPluginConfig {
+
+    public static class Plugin {
+        @PluginConfig(root = MicronautHttpClientPluginConfig.class)
+        public static class MicronautHttpClient {
+            /**
+             * This config item controls that whether the HttpClient plugin should collect the parameters of the request.
+             */
+            public static boolean COLLECT_HTTP_PARAMS = false;
+        }
+
+        @PluginConfig(root = MicronautHttpClientPluginConfig.class)
+        public static class Http {
+            /**
+             * When either {@link MicronautHttpClient#COLLECT_HTTP_PARAMS} is enabled, how many characters to keep and send to the
+             * OAP backend, use negative values to keep and send the complete parameters, NB. this config item is added
+             * for the sake of performance
+             */
+            public static int HTTP_PARAMS_LENGTH_THRESHOLD = 1024;
+        }
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/define/MicronautClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/define/MicronautClientInstrumentation.java
new file mode 100644
index 000000000..202a75b65
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/client/define/MicronautClientInstrumentation.java
@@ -0,0 +1,87 @@
+/*
+ * 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.micronaut.http.client.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+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.match.NameMatch.byName;
+
+public class MicronautClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String ENHANCE_CLASS = "io.micronaut.http.client.netty.DefaultHttpClient";
+    private static final String CLIENT_EXCHANGE_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.micronaut.http.client.ExchangeImplInterceptor";
+    private static final String STREAM_EXCHANGE_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.micronaut.http.client.BuildExchangeStreamPublisherInterceptor";
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[0];
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[]{
+                new InstanceMethodsInterceptPoint() {
+                    //microaut 3.4.4-3.6.x (As of now, the latest version is 3.6.0)
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named("exchangeImpl").and(takesArguments(5));
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return CLIENT_EXCHANGE_INTERCEPT_CLASS;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                },
+                // microaut 3.2.0-3.4.3
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named("buildExchangePublisher").and(takesArguments(4));
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return STREAM_EXCHANGE_INTERCEPT_CLASS;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                }
+        };
+    }
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return byName(ENHANCE_CLASS);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 000000000..560b24df1
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1,17 @@
+# 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.
+
+micronaut-http-client-3.2.x-3.6.x=org.apache.skywalking.apm.plugin.micronaut.http.client.define.MicronautClientInstrumentation
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml
new file mode 100644
index 000000000..4b282e46f
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.skywalking</groupId>
+        <artifactId>micronaut-plugins</artifactId>
+        <version>8.12.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>micronaut-http-server-plugin</artifactId>
+    <packaging>jar</packaging>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.micronaut</groupId>
+            <artifactId>micronaut-http</artifactId>
+            <version>3.6.0</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>io.micronaut</groupId>
+            <artifactId>micronaut-http-server-netty</artifactId>
+            <version>3.6.0</version>
+            <scope>provided</scope>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/HandleStatusErrorInterceptor.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/HandleStatusErrorInterceptor.java
new file mode 100644
index 000000000..094c2d108
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/HandleStatusErrorInterceptor.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.micronaut.http.server;
+
+import io.micronaut.http.server.netty.NettyHttpRequest;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+
+import java.lang.reflect.Method;
+
+import static org.apache.skywalking.apm.plugin.micronaut.http.server.MicronautCommons.cleanup;
+import static org.apache.skywalking.apm.plugin.micronaut.http.server.MicronautCommons.beginTrace;
+
+public class HandleStatusErrorInterceptor implements InstanceMethodsAroundInterceptor {
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+        beginTrace((NettyHttpRequest<?>) allArguments[1]);
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+        cleanup((NettyHttpRequest<?>) allArguments[1]);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/MicronautCommons.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/MicronautCommons.java
new file mode 100644
index 000000000..f3b24f769
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/MicronautCommons.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.plugin.micronaut.http.server;
+
+import io.micronaut.http.HttpRequest;
+import org.apache.skywalking.apm.agent.core.context.CarrierItem;
+import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.apache.skywalking.apm.util.StringUtil;
+
+class MicronautCommons {
+    static final String SPAN_KEY = "CORS_SPAN";
+    static final String SKY_CONTEXT_SNAPSHOT_KEY = "CORS_SNAPSHOT";
+
+    static void collectHttpParam(HttpRequest<?> httpRequest, AbstractSpan span) {
+        String tag = httpRequest.getUri().getQuery();
+        tag = MicronautHttpServerPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ?
+                StringUtil.cut(tag, MicronautHttpServerPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tag;
+        if (StringUtil.isNotEmpty(tag)) {
+            Tags.HTTP.PARAMS.set(span, tag);
+        }
+    }
+
+    static void cleanup(HttpRequest<?> request) {
+        request.removeAttribute(MicronautCommons.SKY_CONTEXT_SNAPSHOT_KEY, ContextSnapshot.class);
+        request.removeAttribute(MicronautCommons.SPAN_KEY, AbstractSpan.class);
+    }
+
+    static void beginTrace(HttpRequest<?> request) {
+        ContextCarrier contextCarrier = new ContextCarrier();
+        CarrierItem next = contextCarrier.items();
+        while (next.hasNext()) {
+            next = next.next();
+            next.setHeadValue(request.getHeaders().get(next.getHeadKey()));
+        }
+        String operationName = String.join(":", request.getMethod(), request.getPath());
+        AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier);
+        ContextSnapshot capture = ContextManager.capture();
+        request.setAttribute(SPAN_KEY, span);
+        request.setAttribute(SKY_CONTEXT_SNAPSHOT_KEY, capture);
+        Tags.URL.set(span, String.format("%s://%s:%s%s", request.isSecure() ? "https" : "http", request.getServerName(), request.getServerAddress().getPort(), request.getUri().getPath()));
+        Tags.HTTP.METHOD.set(span, request.getMethodName());
+        span.setComponent(ComponentsDefine.MICRONAUT);
+        SpanLayer.asHttp(span);
+        span.prepareForAsync();
+        ContextManager.stopSpan(span);
+        if (MicronautHttpServerPluginConfig.Plugin.MicronautHttpServer.COLLECT_HTTP_PARAMS) {
+            collectHttpParam(request, span);
+        }
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/MicronautHttpServerPluginConfig.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/MicronautHttpServerPluginConfig.java
new file mode 100644
index 000000000..5abbf2227
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/MicronautHttpServerPluginConfig.java
@@ -0,0 +1,45 @@
+/*
+ * 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.micronaut.http.server;
+
+import org.apache.skywalking.apm.agent.core.boot.PluginConfig;
+
+public class MicronautHttpServerPluginConfig {
+
+    public static class Plugin {
+        @PluginConfig(root = MicronautHttpServerPluginConfig.class)
+        public static class MicronautHttpServer {
+            /**
+             * This config item controls that whether the Http plugin should collect the parameters of the request.
+             */
+            public static boolean COLLECT_HTTP_PARAMS = false;
+        }
+
+        @PluginConfig(root = MicronautHttpServerPluginConfig.class)
+        public static class Http {
+            /**
+             * When either {@link MicronautHttpServer#COLLECT_HTTP_PARAMS} is enabled, how many characters to keep and send to the
+             * OAP backend, use negative values to keep and send the complete parameters, NB. this config item is added
+             * for the sake of performance
+             */
+            public static int HTTP_PARAMS_LENGTH_THRESHOLD = 1024;
+        }
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/RouteMatchExecuteInterceptor.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/RouteMatchExecuteInterceptor.java
new file mode 100644
index 000000000..4f4891857
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/RouteMatchExecuteInterceptor.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.plugin.micronaut.http.server;
+
+import io.micronaut.http.context.ServerRequestContext;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+
+import java.lang.reflect.Method;
+
+public class RouteMatchExecuteInterceptor implements InstanceMethodsAroundInterceptor {
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+        ServerRequestContext.currentRequest().ifPresent(MicronautCommons::beginTrace);
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+        ServerRequestContext.currentRequest().ifPresent(MicronautCommons::cleanup);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/WriteFinalNettyResponseInterceptor.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/WriteFinalNettyResponseInterceptor.java
new file mode 100644
index 000000000..f6b9113f8
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/WriteFinalNettyResponseInterceptor.java
@@ -0,0 +1,67 @@
+/*
+ * 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.micronaut.http.server;
+
+import io.micronaut.http.HttpRequest;
+import io.micronaut.http.MutableHttpResponse;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+
+import java.lang.reflect.Method;
+
+import static org.apache.skywalking.apm.plugin.micronaut.http.server.MicronautCommons.cleanup;
+import static org.apache.skywalking.apm.plugin.micronaut.http.server.MicronautCommons.collectHttpParam;
+
+public class WriteFinalNettyResponseInterceptor implements InstanceMethodsAroundInterceptor {
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        MutableHttpResponse<?> message = (MutableHttpResponse<?>) allArguments[0];
+        HttpRequest<?> request = (HttpRequest<?>) allArguments[1];
+        request.getAttribute(MicronautCommons.SPAN_KEY)
+                .map(span -> (AbstractSpan) span)
+                .ifPresent(span -> {
+                    int code = message.status().getCode();
+                    Tags.HTTP_RESPONSE_STATUS_CODE.set(span, code);
+                    if (code >= 400) {
+                        span.errorOccurred();
+                    }
+                    //Activate HTTP parameters collecting automatically in the profiling context.
+                    if (!MicronautHttpServerPluginConfig.Plugin.MicronautHttpServer.COLLECT_HTTP_PARAMS && span.isProfiling()) {
+                        collectHttpParam((HttpRequest<?>) allArguments[1], span);
+                    }
+                    span.asyncFinish();
+                });
+        cleanup(request);
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+        cleanup((HttpRequest<?>) allArguments[1]);
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/define/RouteMatchInstrumentation.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/define/RouteMatchInstrumentation.java
new file mode 100644
index 000000000..ff8445556
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/define/RouteMatchInstrumentation.java
@@ -0,0 +1,69 @@
+/*
+ * 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.micronaut.http.server.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+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.match.NameMatch.byName;
+
+public class RouteMatchInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String EXECUTE_INTERCEPTOR = "org.apache.skywalking.apm.plugin.micronaut.http.server.RouteMatchExecuteInterceptor";
+
+    private static final String ROUTE_MATCH_CLASS_NAME = "io.micronaut.web.router.AbstractRouteMatch";
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return byName(ROUTE_MATCH_CLASS_NAME);
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[0];
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[]{
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named("execute").and(takesArguments(1));
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return EXECUTE_INTERCEPTOR;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                }
+        };
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/define/RoutingInBoundHandlerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/define/RoutingInBoundHandlerInstrumentation.java
new file mode 100644
index 000000000..3eef57aea
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/micronaut/http/server/define/RoutingInBoundHandlerInstrumentation.java
@@ -0,0 +1,87 @@
+/*
+ * 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.micronaut.http.server.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+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.match.NameMatch.byName;
+
+public class RoutingInBoundHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String CLASS_NAME = "io.micronaut.http.server.netty.RoutingInBoundHandler";
+
+    private static final String FINAL_RESPONSE_INTERCEPTOR = "org.apache.skywalking.apm.plugin.micronaut.http.server.WriteFinalNettyResponseInterceptor";
+
+    private static final String HANDLE_ERROR_INTERCEPTOR = "org.apache.skywalking.apm.plugin.micronaut.http.server.HandleStatusErrorInterceptor";
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return byName(CLASS_NAME);
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[0];
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[]{
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named("handleStatusError").and(takesArguments(4));
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return HANDLE_ERROR_INTERCEPTOR;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                },
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named("writeFinalNettyResponse").and(takesArguments(3));
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return FINAL_RESPONSE_INTERCEPTOR;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                }
+        };
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 000000000..36bd74e91
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +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.
+
+micronaut-http-server-3.2.x-3.6.x=org.apache.skywalking.apm.plugin.micronaut.http.server.define.RouteMatchInstrumentation
+micronaut-http-server-3.2.x-3.6.x=org.apache.skywalking.apm.plugin.micronaut.http.server.define.RoutingInBoundHandlerInstrumentation
\ No newline at end of file
diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml
new file mode 100644
index 000000000..2ce0a6b9e
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>apm-sdk-plugin</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>8.12.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>micronaut-plugins</artifactId>
+    <packaging>pom</packaging>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <sdk.plugin.related.dir>/..</sdk.plugin.related.dir>
+    </properties>
+
+    <modules>
+        <module>micronaut-http-server-plugin</module>
+        <module>micronaut-http-client-plugin</module>
+    </modules>
+
+</project>
diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml
index 93fabad88..538162693 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -122,6 +122,7 @@
         <module>tomcat-thread-pool-plugin</module>
         <module>guava-eventbus-plugin</module>
         <module>hutool-plugins</module>
+        <module>micronaut-plugins</module>
     </modules>
     <packaging>pom</packaging>
 
diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md b/docs/en/setup/service-agent/java-agent/Plugin-list.md
index 3029b158a..60b9c2d10 100644
--- a/docs/en/setup/service-agent/java-agent/Plugin-list.md
+++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md
@@ -141,3 +141,5 @@
 - shenyu-2.4.x
 - jdk-threadpool-plugin
 - hutool-http-5.x
+- micronaut-http-client-3.2.x-3.6.x
+- micronaut-http-server-3.2.x-3.6.x
diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md
index 98cdc7658..7ac7c1826 100644
--- a/docs/en/setup/service-agent/java-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/java-agent/Supported-list.md
@@ -20,6 +20,7 @@ metrics based on the tracing data.
   * [Play Framework](https://www.playframework.com/) 2.6.x -> 2.8.x
   * [Light4J Microservices Framework](https://doc.networknt.com/) 1.6.x -> 2.x
   * [Netty SocketIO](https://github.com/mrniko/netty-socketio) 1.x
+  * [Micrinaut Http Server](https://github.com/micronaut-projects/micronaut-core) 3.2.x -> 3.6.x
 * HTTP Client
   * [Feign](https://github.com/OpenFeign/feign) 9.x
   * [Netflix Spring Cloud Feign](https://github.com/spring-cloud/spring-cloud-openfeign) 1.1.x -> 2.x
@@ -31,6 +32,7 @@ metrics based on the tracing data.
   * [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client) 2.1+
   * JRE HttpURLConnection (Optional²)
   * [Hutool-http](https://www.hutool.cn/) client 5.x
+  * [Micrinaut Http Client](https://github.com/micronaut-projects/micronaut-core) 3.2.x -> 3.6.x
 * HTTP Gateway
   * [Spring Cloud Gateway](https://spring.io/projects/spring-cloud-gateway) 2.0.2.RELEASE -> 3.x (Optional²)
   * [Apache ShenYu](https://shenyu.apache.org) (Rich protocol support: `HTTP`,`Spring Cloud`,`gRPC`,`Dubbo`,`SOFARPC`,`Motan`,`Tars`) 2.4.x (Optional²)
diff --git a/docs/en/setup/service-agent/java-agent/configurations.md b/docs/en/setup/service-agent/java-agent/configurations.md
index 54562d7ee..c729c9de1 100644
--- a/docs/en/setup/service-agent/java-agent/configurations.md
+++ b/docs/en/setup/service-agent/java-agent/configurations.md
@@ -111,6 +111,8 @@ This is the properties list supported in `agent/config/agent.config`.
 | `plugin.neo4j.cypher_parameters_max_length`                     | If set to positive number, the `db.cypher.parameters` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.                                                                                                                                                                                                                                                                    [...]
 | `plugin.neo4j.cypher_body_max_length`                           | If set to positive number, the `db.statement` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.                                                                                                                                                                                                                                                                            [...]
 | `plugin.cpupolicy.sample_cpu_usage_percent_limit`               | If set to a positive number and activate `trace sampler CPU policy plugin`, the trace would not be collected when agent process CPU usage percent is greater than `plugin.cpupolicy.sample_cpu_usage_percent_limit`.                                                                                                                                                                                                                     [...]
+| `plugin.micronauthttpclient.collect_http_params`                | This config item controls that whether the Micronaut http client plugin should collect the parameters of the request. Also, activate implicitly in the profiled trace.                                                                                                                                                                                                                                                                   [...]
+| `plugin.micronauthttpserver.collect_http_params`                | This config item controls that whether the Micronaut http server plugin should collect the parameters of the request. Also, activate implicitly in the profiled trace.                                                                                                                                                                                                                                                                   [...]
 
 # Dynamic Configurations
 All configurations above are static, if you need to change some agent settings at runtime, please read [CDS - Configuration Discovery Service document](configuration-discovery.md) for more details.
diff --git a/test/plugin/scenarios/micronaut-http-scenario/bin/startup.sh b/test/plugin/scenarios/micronaut-http-scenario/bin/startup.sh
new file mode 100644
index 000000000..815d657d9
--- /dev/null
+++ b/test/plugin/scenarios/micronaut-http-scenario/bin/startup.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+#
+# 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.
+
+home="$(cd "$(dirname $0)"; pwd)"
+
+java -jar ${agent_opts}  "-Dskywalking.agent.service_name=micronaut-scenario-8081" "-Dmicronaut.server.port=8081"  "-Dskywalking.plugin.micronauthttpclient.collect_http_params=true" "-Dskywalking.plugin.micronauthttpserver.collect_http_params=true"  ${home}/../libs/micronaut-http-scenario.jar &
+java -jar ${agent_opts} "-Dskywalking.agent.service_name=micronaut-scenario-8080" "-Dmicronaut.server.port=8080"  "-Dskywalking.plugin.micronauthttpclient.collect_http_params=true" "-Dskywalking.plugin.micronauthttpserver.collect_http_params=true"  ${home}/../libs/micronaut-http-scenario.jar &
\ No newline at end of file
diff --git a/test/plugin/scenarios/micronaut-http-scenario/config/expectedData.yaml b/test/plugin/scenarios/micronaut-http-scenario/config/expectedData.yaml
new file mode 100644
index 000000000..2530b2ba9
--- /dev/null
+++ b/test/plugin/scenarios/micronaut-http-scenario/config/expectedData.yaml
@@ -0,0 +1,191 @@
+# 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.
+
+segmentItems:
+  - serviceName: micronaut-scenario-8080
+    segmentSize: ge 4
+    segments:
+      - segmentId: not null
+        spans:
+          - operationName: GET:/micronaut/success
+            operationId: 0
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 131
+            isError: false
+            spanType: Exit
+            peer: localhost:8081
+            skipAnalysis: false
+            tags:
+              - {key: http.method, value: GET}
+              - {key: url, value: 'http://localhost:8081/micronaut/success'}
+              - {key: http.params, value: a=1&b=2}
+              - {key: http.status_code, value: '200'}
+            refs:
+              - {parentEndpoint: 'GET:/micronaut/start', networkAddress: '', refType: CrossThread,
+                 parentSpanId: 0, parentTraceSegmentId: not null,
+                 parentServiceInstance: not null, parentService: micronaut-scenario-8080,
+                 traceId: not null}
+      - segmentId: not null
+        spans:
+          - operationName: GET:/micronaut/404
+            operationId: 0
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 131
+            isError: true
+            spanType: Exit
+            peer: localhost:8081
+            skipAnalysis: false
+            tags:
+              - {key: http.method, value: GET}
+              - {key: url, value: 'http://localhost:8081/micronaut/404'}
+            logs:
+              - logEvent:
+                  - {key: event, value: error}
+                  - {key: error.kind, value: io.micronaut.http.client.exceptions.HttpClientResponseException}
+                  - {key: message, value: Not Found}
+                  - {key: stack,value: not null}
+            refs:
+              - {parentEndpoint: 'GET:/micronaut/start', networkAddress: '', refType: CrossThread,
+                 parentSpanId: 0, parentTraceSegmentId: not null,
+                 parentServiceInstance: not null, parentService: micronaut-scenario-8080,
+                 traceId: not null}
+      - segmentId: not null
+        spans:
+          - operationName: GET:/micronaut/error
+            operationId: 0
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 131
+            isError: true
+            spanType: Exit
+            peer: localhost:8081
+            skipAnalysis: false
+            tags:
+              - {key: http.method, value: GET}
+              - {key: url, value: 'http://localhost:8081/micronaut/error'}
+            logs:
+              - logEvent:
+                  - {key: event, value: error}
+                  - {key: error.kind, value: io.micronaut.http.client.exceptions.HttpClientResponseException}
+                  - {key: message, value: not null}
+                  - {key: stack,value: not null}
+            refs:
+              - {parentEndpoint: 'GET:/micronaut/start', networkAddress: '', refType: CrossThread,
+                 parentSpanId: 0, parentTraceSegmentId: not null,
+                 parentServiceInstance: not null, parentService: micronaut-scenario-8080,
+                 traceId: not null}
+      - segmentId: not null
+        spans:
+          - operationName: GET:/micronaut/start
+            operationId: 0
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 131
+            isError: false
+            spanType: Entry
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - {key: url, value: 'http://localhost:8080/micronaut/start'}
+              - {key: http.method, value: GET}
+              - {key: http.status_code, value: '200'}
+  - serviceName: micronaut-scenario-8081
+    segmentSize: 3
+    segments:
+      - segmentId: not null
+        spans:
+          - operationName: GET:/micronaut/success
+            operationId: 0
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 131
+            isError: false
+            spanType: Entry
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - {key: url, value: 'http://localhost:8081/micronaut/success'}
+              - {key: http.method, value: GET}
+              - {key: http.params, value: a=1&b=2}
+              - {key: http.status_code, value: '200'}
+            refs:
+              - {parentEndpoint: 'GET:/micronaut/success', networkAddress: 'localhost:8081',
+                 refType: CrossProcess, parentSpanId: 0, parentTraceSegmentId: not null,
+                 parentServiceInstance: not null, parentService: micronaut-scenario-8080,
+                 traceId: not null}
+      - segmentId: not null
+        spans:
+          - operationName: GET:/micronaut/404
+            operationId: 0
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 131
+            isError: true
+            spanType: Entry
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - {key: url, value: 'http://localhost:8081/micronaut/404'}
+              - {key: http.method, value: GET}
+              - {key: http.status_code, value: '404'}
+            refs:
+              - {parentEndpoint: 'GET:/micronaut/404', networkAddress: 'localhost:8081', refType: CrossProcess,
+                 parentSpanId: 0, parentTraceSegmentId: not null,
+                 parentServiceInstance: not null, parentService: micronaut-scenario-8080,
+                 traceId: not null}
+      - segmentId: not null
+        spans:
+          - operationName: GET:/micronaut/error
+            operationId: 0
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 131
+            isError: true
+            spanType: Entry
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - {key: url, value: 'http://localhost:8081/micronaut/error'}
+              - {key: http.method, value: GET}
+              - {key: http.status_code, value: '500'}
+            refs:
+              - {parentEndpoint: 'GET:/micronaut/error', networkAddress: 'localhost:8081',
+                 refType: CrossProcess, parentSpanId: 0, parentTraceSegmentId: not null,
+                 parentServiceInstance: not null, parentService: micronaut-scenario-8080,
+                 traceId: not null}
\ No newline at end of file
diff --git a/test/plugin/scenarios/micronaut-http-scenario/configuration.yml b/test/plugin/scenarios/micronaut-http-scenario/configuration.yml
new file mode 100644
index 000000000..295905807
--- /dev/null
+++ b/test/plugin/scenarios/micronaut-http-scenario/configuration.yml
@@ -0,0 +1,20 @@
+# 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.
+
+type: jvm
+entryService: http://localhost:8080/micronaut/start
+healthCheck: http://localhost:8080/micronaut/healthCheck
+startScript: ./bin/startup.sh
\ No newline at end of file
diff --git a/test/plugin/scenarios/micronaut-http-scenario/pom.xml b/test/plugin/scenarios/micronaut-http-scenario/pom.xml
new file mode 100644
index 000000000..f9706e1da
--- /dev/null
+++ b/test/plugin/scenarios/micronaut-http-scenario/pom.xml
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.skywalking</groupId>
+    <artifactId>micronaut-http-scenario</artifactId>
+    <version>1.0.0</version>
+
+    <packaging>jar</packaging>
+    <name>micronaut-scenario</name>
+    <properties>
+        <packaging>jar</packaging>
+        <jdk.version>1.8</jdk.version>
+        <!-- If you are building with JDK 9 or higher, you can uncomment the lines below to set the release version -->
+        <!-- <release.version>8</release.version> -->
+        <compiler.version>1.8</compiler.version>
+        <micronaut.runtime>netty</micronaut.runtime>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <exec.mainClass>org.apache.skywalking.apm.testcase.micronaut.Application</exec.mainClass>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.micronaut</groupId>
+            <artifactId>micronaut-inject</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.micronaut</groupId>
+            <artifactId>micronaut-validation</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.micronaut</groupId>
+            <artifactId>micronaut-inject-groovy</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.spockframework</groupId>
+            <artifactId>spock-core</artifactId>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.codehaus.groovy</groupId>
+                    <artifactId>groovy-all</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>io.micronaut.test</groupId>
+            <artifactId>micronaut-test-spock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.micronaut</groupId>
+            <artifactId>micronaut-http-client</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.micronaut</groupId>
+            <artifactId>micronaut-http-server-netty</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.micronaut</groupId>
+            <artifactId>micronaut-jackson-databind</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.projectreactor</groupId>
+            <artifactId>reactor-core</artifactId>
+        </dependency>
+
+    </dependencies>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>io.micronaut</groupId>
+                <artifactId>micronaut-bom</artifactId>
+                <version>${test.framework.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+
+    <build>
+        <finalName>micronaut-http-scenario</finalName>
+
+        <plugins>
+            <plugin>
+                <groupId>io.micronaut.build</groupId>
+                <artifactId>micronaut-maven-plugin</artifactId>
+                <version>3.4.0</version>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>3.0.0-M7</version>
+                <configuration>
+                    <includes>
+                        <include>**/*Spec.*</include>
+                        <include>**/*Test.*</include>
+                    </includes>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.10.1</version>
+                <configuration>
+                    <annotationProcessorPaths combine.children="append">
+                        <path>
+                            <groupId>io.micronaut</groupId>
+                            <artifactId>micronaut-inject-java</artifactId>
+                            <version>${test.framework.version}</version>
+                        </path>
+                        <path>
+                            <groupId>io.micronaut</groupId>
+                            <artifactId>micronaut-http-validation</artifactId>
+                            <version>${test.framework.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                    <compilerArgs>
+                        <arg>-Amicronaut.processing.group=org.apache.skywalking</arg>
+                        <arg>-Amicronaut.processing.module=micronaut-http-scenario</arg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.gmavenplus</groupId>
+                <artifactId>gmavenplus-plugin</artifactId>
+                <version>1.13.0</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>addSources</goal>
+                            <goal>generateStubs</goal>
+                            <goal>compile</goal>
+                            <goal>removeStubs</goal>
+                            <goal>addTestSources</goal>
+                            <goal>generateTestStubs</goal>
+                            <goal>compileTests</goal>
+                            <goal>removeTestStubs</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>3.3.0</version>
+                <executions>
+                    <execution>
+                        <id>default-shade</id>
+                        <configuration>
+                            <createDependencyReducedPom>false</createDependencyReducedPom>
+                            <transformers>
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                    <mainClass>${exec.mainClass}</mainClass>
+                                </transformer>
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
+                            </transformers>
+
+                        </configuration>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>src/main/assembly/assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>./target/</outputDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/test/plugin/scenarios/micronaut-http-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/micronaut-http-scenario/src/main/assembly/assembly.xml
new file mode 100644
index 000000000..b969f0138
--- /dev/null
+++ b/test/plugin/scenarios/micronaut-http-scenario/src/main/assembly/assembly.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+<assembly
+    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <fileSets>
+        <fileSet>
+            <directory>./bin</directory>
+            <fileMode>0775</fileMode>
+        </fileSet>
+    </fileSets>
+
+    <files>
+        <file>
+            <source>${project.build.directory}/micronaut-http-scenario.jar</source>
+            <outputDirectory>./libs</outputDirectory>
+            <fileMode>0775</fileMode>
+        </file>
+    </files>
+</assembly>
diff --git a/test/plugin/scenarios/micronaut-http-scenario/src/main/java/org/apache/skywalking/apm/testcase/micronaut/Application.java b/test/plugin/scenarios/micronaut-http-scenario/src/main/java/org/apache/skywalking/apm/testcase/micronaut/Application.java
new file mode 100644
index 000000000..f30ded120
--- /dev/null
+++ b/test/plugin/scenarios/micronaut-http-scenario/src/main/java/org/apache/skywalking/apm/testcase/micronaut/Application.java
@@ -0,0 +1,27 @@
+/*
+ * 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.testcase.micronaut;
+
+import io.micronaut.runtime.Micronaut;
+
+public class Application {
+    public static void main(String[] args) {
+        Micronaut.run(Application.class, args);
+    }
+}
diff --git a/test/plugin/scenarios/micronaut-http-scenario/src/main/java/org/apache/skywalking/apm/testcase/micronaut/controller/ErrorHandlerController.java b/test/plugin/scenarios/micronaut-http-scenario/src/main/java/org/apache/skywalking/apm/testcase/micronaut/controller/ErrorHandlerController.java
new file mode 100644
index 000000000..f67aedf6a
--- /dev/null
+++ b/test/plugin/scenarios/micronaut-http-scenario/src/main/java/org/apache/skywalking/apm/testcase/micronaut/controller/ErrorHandlerController.java
@@ -0,0 +1,35 @@
+/*
+ * 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.testcase.micronaut.controller;
+
+import io.micronaut.http.HttpRequest;
+import io.micronaut.http.HttpResponse;
+import io.micronaut.http.MediaType;
+import io.micronaut.http.annotation.Controller;
+import io.micronaut.http.annotation.Error;
+
+@Controller
+public class ErrorHandlerController {
+
+    @Error(global = true)
+    public HttpResponse<String> error(HttpRequest request, Throwable e) {
+        return HttpResponse.<String>serverError().contentType(MediaType.TEXT_HTML_TYPE)
+                .body("causeError -> ");
+    }
+}
diff --git a/test/plugin/scenarios/micronaut-http-scenario/src/main/java/org/apache/skywalking/apm/testcase/micronaut/controller/HelloController.java b/test/plugin/scenarios/micronaut-http-scenario/src/main/java/org/apache/skywalking/apm/testcase/micronaut/controller/HelloController.java
new file mode 100644
index 000000000..f2f5b139a
--- /dev/null
+++ b/test/plugin/scenarios/micronaut-http-scenario/src/main/java/org/apache/skywalking/apm/testcase/micronaut/controller/HelloController.java
@@ -0,0 +1,69 @@
+/*
+ * 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.testcase.micronaut.controller;
+
+import io.micronaut.http.HttpRequest;
+import io.micronaut.http.MediaType;
+import io.micronaut.http.annotation.Controller;
+import io.micronaut.http.annotation.Get;
+import io.micronaut.http.client.HttpClient;
+import io.micronaut.http.client.annotation.Client;
+import jakarta.inject.Inject;
+
+@Controller("/micronaut")
+public class HelloController {
+    @Inject
+    @Client("http://localhost:8081")
+    private HttpClient client;
+
+    @Get(value = "healthCheck")
+    public String checkHealth() {
+        return "checked";
+    }
+
+    @Get(produces = MediaType.TEXT_PLAIN, value = "start")
+    public String start() throws InterruptedException {
+        try {
+            client.toBlocking().retrieve(HttpRequest.GET("/micronaut/success?a=1&b=2"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        try {
+            client.toBlocking().retrieve(HttpRequest.GET("/micronaut/404"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        try {
+            client.toBlocking().retrieve(HttpRequest.GET("/micronaut/error"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "end";
+    }
+
+    @Get(produces = MediaType.TEXT_PLAIN, value = "success")
+    public String success() {
+        return "success";
+    }
+
+    @Get(produces = MediaType.TEXT_PLAIN, value = "error")
+    public String error() {
+        throw new NullPointerException();
+    }
+}
diff --git a/test/plugin/scenarios/micronaut-http-scenario/support-version.list b/test/plugin/scenarios/micronaut-http-scenario/support-version.list
new file mode 100644
index 000000000..fe14e0896
--- /dev/null
+++ b/test/plugin/scenarios/micronaut-http-scenario/support-version.list
@@ -0,0 +1,22 @@
+# 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.
+
+3.6.0
+3.5.4
+3.4.3
+3.3.4
+3.2.7
+3.2.0
\ No newline at end of file