Browse Source
CounterFactory is used by ZuulException and was previously initialzed with a dummy impl. This adds a Spring Boot CounterService based implementation. Also adds the ability to implement a zuul TracerFactory.pull/6/head
9 changed files with 528 additions and 16 deletions
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
/* |
||||
* 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.zuul.metrics; |
||||
|
||||
import org.springframework.boot.actuate.metrics.CounterService; |
||||
|
||||
import com.netflix.zuul.monitoring.CounterFactory; |
||||
|
||||
/** |
||||
* A counter based monitoring factory that uses {@link CounterService} to increment counters. |
||||
* |
||||
* @author Anastasiia Smirnova |
||||
*/ |
||||
public class DefaultCounterFactory extends CounterFactory { |
||||
|
||||
private final CounterService counterService; |
||||
|
||||
public DefaultCounterFactory(CounterService counterService) { |
||||
this.counterService = counterService; |
||||
} |
||||
|
||||
@Override |
||||
public void increment(String name) { |
||||
counterService.increment(name); |
||||
} |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
/* |
||||
* 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.zuul.metrics; |
||||
|
||||
import com.netflix.zuul.monitoring.CounterFactory; |
||||
|
||||
/** |
||||
* A counter based monitoring factory that does nothing. |
||||
* |
||||
* @author Anastasiia Smirnova |
||||
*/ |
||||
public class EmptyCounterFactory extends CounterFactory { |
||||
@Override |
||||
public void increment(String name) { |
||||
} |
||||
} |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
/* |
||||
* 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.zuul.metrics; |
||||
|
||||
import com.netflix.zuul.monitoring.Tracer; |
||||
import com.netflix.zuul.monitoring.TracerFactory; |
||||
|
||||
/** |
||||
* A time based monitoring factory that does nothing. |
||||
* |
||||
* @author Anastasiia Smirnova |
||||
*/ |
||||
public class EmptyTracerFactory extends TracerFactory { |
||||
|
||||
private final EmptyTracer emptyTracer = new EmptyTracer(); |
||||
|
||||
@Override |
||||
public Tracer startMicroTracer(String name) { |
||||
return emptyTracer; |
||||
} |
||||
|
||||
private static final class EmptyTracer implements Tracer { |
||||
@Override |
||||
public void setName(String name) { |
||||
} |
||||
|
||||
@Override |
||||
public void stopAndLog() { |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
/* |
||||
* 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.zuul; |
||||
|
||||
import java.lang.reflect.Field; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import javax.servlet.ServletContextEvent; |
||||
|
||||
import org.springframework.test.util.ReflectionTestUtils; |
||||
import org.springframework.util.ReflectionUtils; |
||||
|
||||
import com.netflix.zuul.FilterLoader; |
||||
import com.netflix.zuul.ZuulFilter; |
||||
import com.netflix.zuul.filters.FilterRegistry; |
||||
import com.netflix.zuul.monitoring.CounterFactory; |
||||
import com.netflix.zuul.monitoring.TracerFactory; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import java.lang.reflect.Constructor; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertTrue; |
||||
import static org.mockito.Mockito.mock; |
||||
|
||||
public class ZuulFilterInitializerTests { |
||||
|
||||
private static final ServletContextEvent DUMMY_SERVLET_CONTEXT_EVENT = mock( |
||||
ServletContextEvent.class); |
||||
|
||||
private Map<String, ZuulFilter> filters = getFilters(); |
||||
private CounterFactory counterFactory = mock(CounterFactory.class); |
||||
private TracerFactory tracerFactory = mock(TracerFactory.class); |
||||
private FilterLoader filterLoader = new FilterLoader(); |
||||
private FilterRegistry filterRegistry = getFilterRegistry(); |
||||
|
||||
private final ZuulFilterInitializer initializer = new ZuulFilterInitializer(filters, |
||||
counterFactory, tracerFactory, filterLoader, filterRegistry); |
||||
|
||||
@Test |
||||
public void shouldSetupOnContextInitializedEvent() throws Exception { |
||||
initializer.contextInitialized(DUMMY_SERVLET_CONTEXT_EVENT); |
||||
|
||||
assertEquals(tracerFactory, TracerFactory.instance()); |
||||
assertEquals(counterFactory, CounterFactory.instance()); |
||||
assertThat(filterRegistry.getAllFilters()) |
||||
.containsAll(filters.values()); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldCleanupOnContextDestroyed() throws Exception { |
||||
initializer.contextDestroyed(DUMMY_SERVLET_CONTEXT_EVENT); |
||||
|
||||
assertEquals(null, ReflectionTestUtils.getField(TracerFactory.class, "INSTANCE")); |
||||
assertEquals(null, |
||||
ReflectionTestUtils.getField(CounterFactory.class, "INSTANCE")); |
||||
assertTrue(FilterRegistry.instance().getAllFilters().isEmpty()); |
||||
assertTrue(getHashFiltersByType().isEmpty()); |
||||
} |
||||
|
||||
private Map getHashFiltersByType() { |
||||
Field field = ReflectionUtils.findField(FilterLoader.class, "hashFiltersByType"); |
||||
ReflectionUtils.makeAccessible(field); |
||||
return (Map) ReflectionUtils.getField(field, FilterLoader.getInstance()); |
||||
} |
||||
|
||||
private Map<String, ZuulFilter> getFilters() { |
||||
Map<String, ZuulFilter> filters = new HashMap<>(); |
||||
filters.put("key1", mock(ZuulFilter.class)); |
||||
filters.put("key2", mock(ZuulFilter.class)); |
||||
return filters; |
||||
} |
||||
|
||||
private FilterRegistry getFilterRegistry() { |
||||
try { |
||||
Constructor<FilterRegistry> constructor = FilterRegistry.class |
||||
.getDeclaredConstructor(new Class[0]); |
||||
constructor.setAccessible(true); |
||||
return constructor.newInstance(new Object[0]); |
||||
} |
||||
catch (Exception e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
/* |
||||
* 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.zuul.metrics; |
||||
|
||||
import org.springframework.boot.actuate.metrics.CounterService; |
||||
|
||||
import com.netflix.zuul.monitoring.CounterFactory; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static org.mockito.Mockito.mock; |
||||
import static org.mockito.Mockito.verify; |
||||
|
||||
public class DefaultCounterFactoryTests { |
||||
|
||||
private static final String NAME = "my-super-metric-name"; |
||||
private final CounterService counterService = mock(CounterService.class); |
||||
private final CounterFactory factory = new DefaultCounterFactory(counterService); |
||||
|
||||
@Test |
||||
public void shouldIncrement() throws Exception { |
||||
factory.increment(NAME); |
||||
|
||||
verify(counterService).increment(NAME); |
||||
} |
||||
} |
@ -0,0 +1,82 @@
@@ -0,0 +1,82 @@
|
||||
/* |
||||
* 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.zuul.metrics; |
||||
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties; |
||||
import org.springframework.cloud.ClassPathExclusions; |
||||
import org.springframework.cloud.netflix.zuul.ZuulConfiguration; |
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
import com.netflix.zuul.monitoring.CounterFactory; |
||||
import com.netflix.zuul.monitoring.TracerFactory; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
|
||||
@ClassPathExclusions({ "spring-boot-starter-actuator-*.jar", |
||||
"spring-boot-actuator-*.jar" }) |
||||
public class ZuulEmptyMetricsApplicationTests { |
||||
|
||||
private AnnotationConfigApplicationContext context; |
||||
|
||||
@Before |
||||
public void setUp() throws Exception { |
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); |
||||
context.register(ZuulEmptyMetricsApplicationTestsConfiguration.class, |
||||
ZuulConfiguration.class); |
||||
context.refresh(); |
||||
|
||||
this.context = context; |
||||
} |
||||
|
||||
@After |
||||
public void tearDown() throws Exception { |
||||
if (this.context != null) { |
||||
this.context.close(); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void shouldSetupDefaultCounterFactoryIfCounterServiceIsPresent() |
||||
throws Exception { |
||||
CounterFactory factory = this.context.getBean(CounterFactory.class); |
||||
|
||||
assertEquals(EmptyCounterFactory.class, factory.getClass()); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldSetupEmptyTracerFactory() throws Exception { |
||||
TracerFactory factory = this.context.getBean(TracerFactory.class); |
||||
|
||||
assertEquals(EmptyTracerFactory.class, factory.getClass()); |
||||
} |
||||
|
||||
@Configuration |
||||
static class ZuulEmptyMetricsApplicationTestsConfiguration { |
||||
|
||||
@Bean |
||||
ServerProperties serverProperties() { |
||||
return new ServerProperties(); |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,120 @@
@@ -0,0 +1,120 @@
|
||||
/* |
||||
* 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.zuul.metrics; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.actuate.metrics.CounterService; |
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; |
||||
import org.springframework.boot.autoconfigure.web.ServerProperties; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.cloud.netflix.zuul.EnableZuulServer; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.test.annotation.DirtiesContext; |
||||
import org.springframework.test.context.junit4.SpringRunner; |
||||
|
||||
import com.netflix.zuul.exception.ZuulException; |
||||
import com.netflix.zuul.monitoring.CounterFactory; |
||||
import com.netflix.zuul.monitoring.TracerFactory; |
||||
|
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
|
||||
@RunWith(SpringRunner.class) |
||||
@SpringBootTest(classes = { |
||||
ZuulMetricsApplicationTests.ZuulMetricsApplicationTestsConfiguration.class, |
||||
ZuulMetricsApplicationTests.ZuulConfig.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) |
||||
@DirtiesContext |
||||
public class ZuulMetricsApplicationTests { |
||||
|
||||
private static final Map<String, Long> counters = new HashMap<>(); |
||||
|
||||
@Autowired |
||||
CounterFactory counterFactory; |
||||
@Autowired |
||||
TracerFactory tracerFactory; |
||||
|
||||
@Test |
||||
public void shouldSetupDefaultCounterFactoryIfCounterServiceIsPresent() |
||||
throws Exception { |
||||
assertEquals(DefaultCounterFactory.class, counterFactory.getClass()); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldSetupEmptyTracerFactory() throws Exception { |
||||
assertEquals(EmptyTracerFactory.class, tracerFactory.getClass()); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldIncrementCounters() throws Exception { |
||||
new ZuulException("any", 500, "cause"); |
||||
new ZuulException("any", 500, "cause"); |
||||
|
||||
assertEquals((long) counters.get("ZUUL::EXCEPTION:cause:500"), 2L); |
||||
|
||||
new ZuulException("any", 404, "cause2"); |
||||
new ZuulException("any", 404, "cause2"); |
||||
new ZuulException("any", 404, "cause2"); |
||||
|
||||
assertEquals((long) counters.get("ZUUL::EXCEPTION:cause2:404"), 3L); |
||||
} |
||||
|
||||
// Don't use @SpringBootApplication because we don't want to component scan
|
||||
@Configuration |
||||
@EnableAutoConfiguration |
||||
@EnableZuulServer |
||||
static class ZuulConfig { |
||||
|
||||
} |
||||
|
||||
@Configuration |
||||
static class ZuulMetricsApplicationTestsConfiguration { |
||||
|
||||
@Bean |
||||
public ServerProperties serverProperties() { |
||||
return new ServerProperties(); |
||||
} |
||||
|
||||
@Bean |
||||
public CounterService counterService() { |
||||
return new CounterService() { |
||||
// not thread safe, but we are ok with it in tests
|
||||
@Override |
||||
public void increment(String metricName) { |
||||
Long counter = counters.get(metricName); |
||||
if (counter == null) { |
||||
counter = 0L; |
||||
} |
||||
counters.put(metricName, ++counter); |
||||
} |
||||
|
||||
@Override |
||||
public void decrement(String metricName) { |
||||
} |
||||
|
||||
@Override |
||||
public void reset(String metricName) { |
||||
} |
||||
}; |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue