diff --git a/joylive-plugin/joylive-application/joylive-application-springboot2/pom.xml b/joylive-plugin/joylive-application/joylive-application-springboot2/pom.xml index 65bc4e474..3ed767392 100644 --- a/joylive-plugin/joylive-application/joylive-application-springboot2/pom.xml +++ b/joylive-plugin/joylive-application/joylive-application-springboot2/pom.xml @@ -16,6 +16,7 @@ 3.4.0 3.1.9 2023.0.3.2 + 1.0.32 @@ -44,6 +45,12 @@ ${nacos-discovery.version} provided + + io.projectreactor.netty + reactor-netty-http + ${reactor-netty-http.version} + provided + \ No newline at end of file diff --git a/joylive-plugin/joylive-application/joylive-application-springboot2/src/main/java/com/jd/live/agent/plugin/application/springboot/v2/definition/SpringNettyWebServerDefinition.java b/joylive-plugin/joylive-application/joylive-application-springboot2/src/main/java/com/jd/live/agent/plugin/application/springboot/v2/definition/SpringNettyWebServerDefinition.java new file mode 100644 index 000000000..c59c0bfc8 --- /dev/null +++ b/joylive-plugin/joylive-application/joylive-application-springboot2/src/main/java/com/jd/live/agent/plugin/application/springboot/v2/definition/SpringNettyWebServerDefinition.java @@ -0,0 +1,54 @@ +/* + * Copyright © ${year} ${owner} (${email}) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jd.live.agent.plugin.application.springboot.v2.definition; + +import com.jd.live.agent.core.bytekit.matcher.MatcherBuilder; +import com.jd.live.agent.core.event.AgentEvent; +import com.jd.live.agent.core.event.Publisher; +import com.jd.live.agent.core.extension.annotation.ConditionalOnClass; +import com.jd.live.agent.core.extension.annotation.Extension; +import com.jd.live.agent.core.inject.annotation.Inject; +import com.jd.live.agent.core.inject.annotation.Injectable; +import com.jd.live.agent.core.plugin.definition.InterceptorDefinition; +import com.jd.live.agent.core.plugin.definition.InterceptorDefinitionAdapter; +import com.jd.live.agent.core.plugin.definition.PluginDefinition; +import com.jd.live.agent.core.plugin.definition.PluginDefinitionAdapter; +import com.jd.live.agent.governance.annotation.ConditionalOnGovernanceEnabled; +import com.jd.live.agent.plugin.application.springboot.v2.interceptor.SpringCloudHttp3Interceptor; + +@Injectable +@Extension(value = "SpringApplicationDefinition_v5", order = PluginDefinition.ORDER_APPLICATION) +@ConditionalOnGovernanceEnabled +@ConditionalOnClass(SpringNettyWebServerDefinition.TYPE_SPRING_NETTY_WEB_SERVER) +@ConditionalOnClass(SpringNettyWebServerDefinition.TYPE_REACTOR_HTTP_SERVER) +public class SpringNettyWebServerDefinition extends PluginDefinitionAdapter { + + protected static final String TYPE_SPRING_NETTY_WEB_SERVER = "org.springframework.boot.web.embedded.netty.NettyWebServer"; + protected static final String TYPE_REACTOR_HTTP_SERVER = "reactor.netty.http.server.HttpServer"; + + private static final String METHOD_START = "start"; + + @Inject(Publisher.SYSTEM) + private Publisher publisher; + + public SpringNettyWebServerDefinition() { + this.matcher = () -> MatcherBuilder.named(TYPE_SPRING_NETTY_WEB_SERVER); + this.interceptors = new InterceptorDefinition[]{ + new InterceptorDefinitionAdapter(MatcherBuilder.named(METHOD_START), + () -> new SpringCloudHttp3Interceptor(publisher)), + }; + } +} diff --git a/joylive-plugin/joylive-application/joylive-application-springboot2/src/main/java/com/jd/live/agent/plugin/application/springboot/v2/interceptor/SpringCloudHttp3Interceptor.java b/joylive-plugin/joylive-application/joylive-application-springboot2/src/main/java/com/jd/live/agent/plugin/application/springboot/v2/interceptor/SpringCloudHttp3Interceptor.java new file mode 100644 index 000000000..af69a45a0 --- /dev/null +++ b/joylive-plugin/joylive-application/joylive-application-springboot2/src/main/java/com/jd/live/agent/plugin/application/springboot/v2/interceptor/SpringCloudHttp3Interceptor.java @@ -0,0 +1,56 @@ +/* + * Copyright © ${year} ${owner} (${email}) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jd.live.agent.plugin.application.springboot.v2.interceptor; + +import com.jd.live.agent.bootstrap.bytekit.context.ExecutableContext; +import com.jd.live.agent.core.event.AgentEvent; +import com.jd.live.agent.core.event.Publisher; +import com.jd.live.agent.core.plugin.definition.InterceptorAdaptor; +import org.springframework.boot.web.embedded.netty.NettyWebServer; +import reactor.netty.http.HttpProtocol; +import reactor.netty.http.server.HttpServer; + +import java.lang.reflect.Field; + +public class SpringCloudHttp3Interceptor extends InterceptorAdaptor { + + private static final String PROTOCOL_HTTP3 = "HTTP3"; + + private final Publisher publisher; + + public SpringCloudHttp3Interceptor(Publisher publisher) { + this.publisher = publisher; + } + + @Override + public void onSuccess(ExecutableContext ctx) { + NettyWebServer nettyWebServer = (NettyWebServer) ctx.getTarget(); + try { + Field httpServerField = nettyWebServer.getClass().getDeclaredField("httpServer"); + httpServerField.setAccessible(true); + HttpServer httpServer = (HttpServer) httpServerField.get(nettyWebServer); + HttpProtocol[] protocols = httpServer.configuration().protocols(); + for (HttpProtocol protocol : protocols) { + if (PROTOCOL_HTTP3.equals(protocol.name())) { + publisher.offer(AgentEvent.onApplicationStarted("Spring http3 web server started")); + break; + } + } + } catch (Exception e) { + //Not needing to throw exceptions + } + } +} diff --git a/joylive-plugin/joylive-application/joylive-application-springboot2/src/main/resources/META-INF/services/com.jd.live.agent.core.plugin.definition.PluginDefinition b/joylive-plugin/joylive-application/joylive-application-springboot2/src/main/resources/META-INF/services/com.jd.live.agent.core.plugin.definition.PluginDefinition index cd0ab743d..3f03b9fa7 100644 --- a/joylive-plugin/joylive-application/joylive-application-springboot2/src/main/resources/META-INF/services/com.jd.live.agent.core.plugin.definition.PluginDefinition +++ b/joylive-plugin/joylive-application/joylive-application-springboot2/src/main/resources/META-INF/services/com.jd.live.agent.core.plugin.definition.PluginDefinition @@ -1,4 +1,5 @@ com.jd.live.agent.plugin.application.springboot.v2.definition.SpringApplicationDefinition com.jd.live.agent.plugin.application.springboot.v2.definition.SpringApplicationRunListenersDefinition com.jd.live.agent.plugin.application.springboot.v2.definition.SpringApplicationContextDefinition -com.jd.live.agent.plugin.application.springboot.v2.definition.NacosRegistrationDefinition \ No newline at end of file +com.jd.live.agent.plugin.application.springboot.v2.definition.NacosRegistrationDefinition +com.jd.live.agent.plugin.application.springboot.v2.definition.SpringNettyWebServerDefinition