From 61513287ce078f7ef57ca480b8a75ae0ce27b2bb Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 28 Sep 2017 16:50:13 -0400 Subject: [PATCH] Migrate /hystrix.stream to management context. fixes gh-2309i --- .../endpoint/ServletWrappingEndpoint.java | 103 ------------------ .../HystrixCircuitBreakerConfiguration.java | 31 +----- ...HystrixManagementContextConfiguration.java | 71 ++++++++++++ .../netflix/hystrix/HystrixProperties.java | 70 ++++++++++++ .../hystrix/HystrixStreamEndpoint.java | 33 ------ .../main/resources/META-INF/spring.factories | 2 + .../hystrix/HystrixStreamEndpointTests.java | 12 +- 7 files changed, 152 insertions(+), 170 deletions(-) delete mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/endpoint/ServletWrappingEndpoint.java create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixManagementContextConfiguration.java create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixProperties.java delete mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixStreamEndpoint.java diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/endpoint/ServletWrappingEndpoint.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/endpoint/ServletWrappingEndpoint.java deleted file mode 100644 index fe50dfc4..00000000 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/endpoint/ServletWrappingEndpoint.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2013-2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.netflix.endpoint; - -import javax.servlet.Servlet; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.InitializingBean; -// import org.springframework.boot.actuate.endpoint.Endpoint; -// import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.context.ServletContextAware; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ServletWrappingController; - -//FIXME 2.0.x -public abstract class ServletWrappingEndpoint implements InitializingBean, - ApplicationContextAware, ServletContextAware/*, MvcEndpoint*/ { - - // TODO: move to spring-boot? - - private String path; - - private boolean sensitive; - - private boolean enabled = true; - - private final ServletWrappingController controller = new ServletWrappingController(); - - @Override - public void afterPropertiesSet() throws Exception { - this.controller.afterPropertiesSet(); - } - - @Override - public void setServletContext(ServletContext servletContext) { - this.controller.setServletContext(servletContext); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.controller.setApplicationContext(applicationContext); - } - - protected ServletWrappingEndpoint(Class servletClass, - String servletName, String path, boolean sensitive, boolean enabled) { - this.controller.setServletClass(servletClass); - this.controller.setServletName(servletName); - this.path = path; - this.sensitive = sensitive; - this.enabled = enabled; - } - - @RequestMapping("**") - public ModelAndView handle(HttpServletRequest request, HttpServletResponse response) - throws Exception { - return this.controller.handleRequest(request, response); - } - - public boolean isEnabled() { - return this.enabled; - } - - public ServletWrappingController getController() { - return this.controller; - } - - /*@Override - public String getPath() { - return this.path; - } - - @Override - public boolean isSensitive() { - return this.sensitive; - } - - @Override - public Class> getEndpointType() { - return null; - }*/ - -} diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixCircuitBreakerConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixCircuitBreakerConfiguration.java index 950c6344..20e6a611 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixCircuitBreakerConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixCircuitBreakerConfiguration.java @@ -1,11 +1,11 @@ /* - * Copyright 2013-2016 the original author or authors. + * Copyright 2013-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -16,20 +16,16 @@ package org.springframework.cloud.netflix.hystrix; -import com.netflix.hystrix.Hystrix; -import com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect; -import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; import org.apache.catalina.core.ApplicationContext; import org.springframework.beans.factory.DisposableBean; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.actuator.NamedFeature; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import com.netflix.hystrix.Hystrix; +import com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect; + /** * @author Spencer Gibb * @author Christian Dupuis @@ -53,23 +49,6 @@ public class HystrixCircuitBreakerConfiguration { return HasFeatures.namedFeatures(new NamedFeature("Hystrix", HystrixCommandAspect.class)); } - @Configuration - @ConditionalOnProperty(value = "hystrix.stream.endpoint.enabled", matchIfMissing = true) - @ConditionalOnWebApplication - @ConditionalOnClass({ Health.class, HystrixMetricsStreamServlet.class }) - protected static class HystrixWebConfiguration { - - @Bean - public HystrixStreamEndpoint hystrixStreamEndpoint() { - return new HystrixStreamEndpoint(); - } - - @Bean - public HasFeatures hystrixStreamFeature() { - return HasFeatures.namedFeature("Hystrix Stream Servlet", HystrixStreamEndpoint.class); - } - } - //FIXME: 2.0.0 /*@Configuration @ConditionalOnProperty(value = "hystrix.metrics.enabled", matchIfMissing = true) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixManagementContextConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixManagementContextConfiguration.java new file mode 100644 index 00000000..6c8c3798 --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixManagementContextConfiguration.java @@ -0,0 +1,71 @@ +/* + * Copyright 2013-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.hystrix; + +import com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.servlet.ManagementServletContext; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.cloud.client.actuator.HasFeatures; +import org.springframework.context.annotation.Bean; + +import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; + +/** + * See original {@link org.springframework.boot.actuate.autoconfigure.jolokia.JolokiaManagementContextConfiguration} + */ +@ManagementContextConfiguration +@ConditionalOnProperty(value = "management.hystrix.enabled", matchIfMissing = true) +@ConditionalOnWebApplication +@ConditionalOnBean(HystrixCommandAspect.class) // only install the stream if enabled +@ConditionalOnClass({ Health.class, HystrixMetricsStreamServlet.class }) +@EnableConfigurationProperties(HystrixProperties.class) +class HystrixManagementContextConfiguration { + + private final ManagementServletContext managementServletContext; + + private final HystrixProperties properties; + + public HystrixManagementContextConfiguration( + ManagementServletContext managementServletContext, + HystrixProperties properties) { + this.managementServletContext = managementServletContext; + this.properties = properties; + } + + @Bean + public ServletRegistrationBean jolokiaServlet() { + String path = this.managementServletContext.getContextPath() + + this.properties.getPath(); + String urlMapping = (path.endsWith("/") ? path + "*" : path + "/*"); + ServletRegistrationBean registration = new ServletRegistrationBean<>( + new HystrixMetricsStreamServlet(), urlMapping); + registration.setInitParameters(this.properties.getConfig()); + return registration; + } + + @Bean + public HasFeatures hystrixStreamFeature() { + return HasFeatures.namedFeature("Hystrix Stream Servlet", HystrixMetricsStreamServlet.class); + } +} diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixProperties.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixProperties.java new file mode 100644 index 00000000..43f318a7 --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixProperties.java @@ -0,0 +1,70 @@ +/* + * Copyright 2013-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.hystrix; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Configuration properties for Hystrix Servlet. + * + * @author Spencer Gibb + * @since 2.0.0 + */ +@ConfigurationProperties(prefix = "management.hystrix") +public class HystrixProperties { + + /** + * Enable Hystrix Stream. + */ + private boolean enabled; + + /** + * Path at which Hystrix Stream will be available. + */ + private String path = "/hystrix.stream"; + + /** + * Hystrix settings. These are traditionally set using servlet parameters. Refer to + * the documentation of Hystrix for more details. + */ + private final Map config = new HashMap<>(); + + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getPath() { + return this.path; + } + + public void setPath(String path) { + this.path = path; + } + + public Map getConfig() { + return this.config; + } + +} + diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixStreamEndpoint.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixStreamEndpoint.java deleted file mode 100644 index ebd9c362..00000000 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixStreamEndpoint.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.netflix.hystrix; - -import org.springframework.cloud.netflix.endpoint.ServletWrappingEndpoint; - -import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; - -/** - * @author Spencer Gibb - */ -public class HystrixStreamEndpoint extends ServletWrappingEndpoint { - - public HystrixStreamEndpoint() { - super(HystrixMetricsStreamServlet.class, "hystrixStream", "/hystrix.stream", - false, true); - } - -} diff --git a/spring-cloud-netflix-core/src/main/resources/META-INF/spring.factories b/spring-cloud-netflix-core/src/main/resources/META-INF/spring.factories index 99f994ab..dfa33d01 100644 --- a/spring-cloud-netflix-core/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-netflix-core/src/main/resources/META-INF/spring.factories @@ -13,3 +13,5 @@ org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\ org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration +org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration=\ +org.springframework.cloud.netflix.hystrix.HystrixManagementContextConfiguration \ No newline at end of file diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/hystrix/HystrixStreamEndpointTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/hystrix/HystrixStreamEndpointTests.java index f200eb22..d6e60150 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/hystrix/HystrixStreamEndpointTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/hystrix/HystrixStreamEndpointTests.java @@ -5,14 +5,13 @@ * 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 + * 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.springframework.cloud.netflix.hystrix; @@ -24,15 +23,14 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -65,14 +63,12 @@ public class HystrixStreamEndpointTests { private int port = 0; @Test - @Ignore // FIXME: 2.0.x public void pathStartsWithSlash() { - HystrixStreamEndpoint endpoint = new HystrixStreamEndpoint(); - // assertEquals("/hystrix.stream", endpoint.getPath()); + HystrixProperties properties = new HystrixProperties(); + assertEquals("/hystrix.stream", properties.getPath()); } @Test - @Ignore // FIXME: 2.0.x public void hystrixStreamWorks() throws Exception { String url = "http://localhost:" + port; // you have to hit a Hystrix circuit breaker before the stream sends anything