Added header to enable overriding meter mark in the URI.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/10f5c7c4 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/10f5c7c4 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/10f5c7c4 Branch: refs/heads/master Commit: 10f5c7c4ad0b47532ecb134001c7caea11815bdb Parents: ddec990 Author: Lauri Kimmel <lauri.kim...@gmx.com> Authored: Sun Jun 1 17:31:46 2014 +1000 Committer: Lauri Kimmel <lauri.kim...@gmx.com> Committed: Mon Jun 16 21:04:22 2014 +1000 ---------------------------------------------------------------------- README.md | 50 +++++++--- .../apache/camel/metrics/MetricsComponent.java | 1 + .../camel/metrics/meter/MeterProducer.java | 9 +- .../camel/metrics/meter/MeterProducerTest.java | 38 +++++++- .../camel/metrics/meter/MeterRouteTest.java | 97 +++++++++++++++++--- 5 files changed, 165 insertions(+), 30 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/10f5c7c4/README.md ---------------------------------------------------------------------- diff --git a/README.md b/README.md index 35f9f89..10a1e4c 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,8 @@ metrics:[ meter | counter | histogram | timer ]:metricname[?options] # Metric Registry -If MetricRegistry instance for name ```metricRegistry``` is not found from Camel registry default one is used. Default MetricRegistry uses Slf4jReporter and 60 second reporting interval. -MetricRegistry instance can be configured by adding bean with name ```metricRegistry``` to Camel registry. For example using Spring Java Configuration. +If MetricRegistry instance for name `metricRegistry` is not found from Camel registry default one is used. Default MetricRegistry uses Slf4jReporter and 60 second reporting interval. +MetricRegistry instance can be configured by adding bean with name `metricRegistry` to Camel registry. For example using Spring Java Configuration. ```java @@ -57,11 +57,11 @@ MetricRegistry instance can be configured by adding bean with name ```metricRegi # Usage -Each metric has type and name. Supported types are ```counter```, ```meter```, ```histogram``` and ```timer```. Metric name is simple string. If metric type is not provided then type ```meter``` is used by default. +Each metric has type and name. Supported types are `counter`, `meter`, `histogram` and `timer`. Metric name is simple string. If metric type is not provided then type `meter` is used by default. ### Headers -Metric name defined in URI can be overridden by using Header with name ```CamelMetricsName```. +Metric name defined in URI can be overridden by using header with name `CamelMetricsName`. For example @@ -72,10 +72,10 @@ from("direct:in") .to("direct:out") ``` -will update counter with name ```new.name``` instead of ```name.not.used```. +will update counter with name `new.name` instead of `name.not.used`. All Metrics specific headers are removed from the message once Metrics endpoint finishes processing of exchange. -While processing exchange Metrics endpoint will catch all exceptions and write log entry using level warn. +While processing exchange Metrics endpoint will catch all exceptions and write log entry using level `warn`. ## Metrics type counter @@ -91,7 +91,7 @@ Where options are | increment | - | Long value to add to the counter | | decrement | - | Long value to subtract from the counter | -If neither ```increment``` or ```decrement``` is defined counter value will be incremented by one. If ```increment``` and ```decrement``` are both defined only increment operation is called. +If neither `increment` or `decrement` is defined counter value will be incremented by one. If `increment` and `decrement` are both defined only increment operation is called. ```java // update counter simple.counter by 7 @@ -116,6 +116,8 @@ from("direct:in") ### Headers +Message headers can be used to override `increment` and `decrement` values specified in Metrics component URI. + | Name | Description | Expected type | |------------------------------|---------------------------------|---------------| | CamelMetricsCounterIncrement | Override increment value in URI | Long | @@ -150,7 +152,7 @@ Where options are |-------|---------|---------------------------| | value | - | Value to use in histogram | -If no ```value``` is not set nothing is added to histogram and warning is logged. +If no `value` is not set nothing is added to histogram and warning is logged. ```java // adds value 9923 to simple.histogram @@ -168,9 +170,11 @@ from("direct:in") ### Headers +Message header can be used to override `value` specified in Metrics component URI. + | Name | Description | Expected type | |----------------------------|---------------------------------|---------------| -| CamelMetricsHistogramValue | Override increment value in URI | Long | +| CamelMetricsHistogramValue | Override histogram value in URI | Long | ```java // adds value 992 to simple.histogram @@ -193,7 +197,7 @@ Where options are |------|---------|---------------------------| | mark | - | Long value to use as mark | -If ```mark``` is not set ```meter.mark()``` is called without argument. +If `mark` is not set `meter.mark()` is called without argument. ```java // marks simple.meter without value @@ -209,6 +213,22 @@ from("direct:in") .to("direct:out") ``` +### Headers + +Message header can be used to override `mark` value specified in Metrics component URI. + +| Name | Description | Expected type | +|-----------------------|----------------------------|---------------| +| CamelMetricsMeterMark | Override mark value in URI | Long | + +```java +// updates meter simple.meter with value 345 +from("direct:in") + .setHeader(MetricsComponent.HEADER_METER_MARK, constant(345L)) + .to("metric:meter:simple.meter?mark=123") + .to("direct:out") +``` + ## Metrics type timer @@ -218,11 +238,11 @@ metrics:timer:metricname[?options] Where options are -| Name | Default | Description | -|--------|---------|---------------------------| -| action | - | ```start``` or ```stop``` | +| Name | Default | Description | +|--------|---------|-------------------| +| action | - | `start` or `stop` | -If no ```action``` or invalid value is provided warning is logged and no timer is updated. If ```action``` ```start``` is called on already running timer or ```stop``` is called on not running timer nothing is updated and warning is logged. +If no `action` or invalid value is provided warning is logged and no timer is updated. If `action` `start` is called on already running timer or `stop` is called on not running timer nothing is updated and warning is logged. ```java // measure time taken by route calculate @@ -232,4 +252,4 @@ from("direct:in") .to("metrics:timer:simple.timer?action=stop"); ``` -`Timer Context` objects are stored as `Exchange` properties. +`Timer Context` objects are stored as `Exchange` properties between different Metrics component calls. http://git-wip-us.apache.org/repos/asf/camel/blob/10f5c7c4/src/main/java/org/apache/camel/metrics/MetricsComponent.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/camel/metrics/MetricsComponent.java b/src/main/java/org/apache/camel/metrics/MetricsComponent.java index 1ff175d..ba04c23 100644 --- a/src/main/java/org/apache/camel/metrics/MetricsComponent.java +++ b/src/main/java/org/apache/camel/metrics/MetricsComponent.java @@ -31,6 +31,7 @@ public class MetricsComponent extends DefaultComponent { public static final String HEADER_COUNTER_INCREMENT = HEADER_PERFIX + "CounterIncrement"; public static final String HEADER_COUNTER_DECREMENT = HEADER_PERFIX + "CounterDecrement"; public static final String HEADER_HISTOGRAM_VALUE = HEADER_PERFIX + "HistogramValue"; + public static final String HEADER_METER_MARK = HEADER_PERFIX + "MeterMark"; private static final Logger LOG = LoggerFactory.getLogger(MetricsComponent.class); http://git-wip-us.apache.org/repos/asf/camel/blob/10f5c7c4/src/main/java/org/apache/camel/metrics/meter/MeterProducer.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/camel/metrics/meter/MeterProducer.java b/src/main/java/org/apache/camel/metrics/meter/MeterProducer.java index 5777134..7622112 100644 --- a/src/main/java/org/apache/camel/metrics/meter/MeterProducer.java +++ b/src/main/java/org/apache/camel/metrics/meter/MeterProducer.java @@ -1,6 +1,9 @@ package org.apache.camel.metrics.meter; +import static org.apache.camel.metrics.MetricsComponent.HEADER_METER_MARK; + import org.apache.camel.Exchange; +import org.apache.camel.Message; import org.apache.camel.metrics.AbstractMetricsProducer; import com.codahale.metrics.Meter; @@ -14,13 +17,15 @@ public class MeterProducer extends AbstractMetricsProducer<MeterEndpoint> { @Override protected void doProcess(Exchange exchange, MeterEndpoint endpoint, MetricRegistry registry, String metricsName) throws Exception { + Message in = exchange.getIn(); Meter meter = registry.meter(metricsName); Long mark = endpoint.getMark(); - if (mark == null) { + Long finalMark = getLongHeader(in, HEADER_METER_MARK, mark); + if (finalMark == null) { meter.mark(); } else { - meter.mark(mark); + meter.mark(finalMark); } } } http://git-wip-us.apache.org/repos/asf/camel/blob/10f5c7c4/src/test/java/org/apache/camel/metrics/meter/MeterProducerTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/camel/metrics/meter/MeterProducerTest.java b/src/test/java/org/apache/camel/metrics/meter/MeterProducerTest.java index ffa8224..66dcce2 100644 --- a/src/test/java/org/apache/camel/metrics/meter/MeterProducerTest.java +++ b/src/test/java/org/apache/camel/metrics/meter/MeterProducerTest.java @@ -1,5 +1,6 @@ package org.apache.camel.metrics.meter; +import static org.apache.camel.metrics.MetricsComponent.HEADER_METER_MARK; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; @@ -7,6 +8,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import org.apache.camel.Exchange; +import org.apache.camel.Message; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -36,6 +38,9 @@ public class MeterProducerTest { @Mock private Exchange exchange; + @Mock + private Message in; + private MeterProducer producer; private InOrder inOrder; @@ -43,9 +48,10 @@ public class MeterProducerTest { @Before public void setUp() throws Exception { producer = new MeterProducer(endpoint); - inOrder = Mockito.inOrder(endpoint, registry, meter, exchange); + inOrder = Mockito.inOrder(endpoint, registry, meter, exchange, in); when(endpoint.getRegistry()).thenReturn(registry); when(registry.meter(METRICS_NAME)).thenReturn(meter); + when(exchange.getIn()).thenReturn(in); } @Test @@ -57,20 +63,50 @@ public class MeterProducerTest { @Test public void testProcessMarkSet() throws Exception { when(endpoint.getMark()).thenReturn(MARK); + when(in.getHeader(HEADER_METER_MARK, MARK, Long.class)).thenReturn(MARK); producer.doProcess(exchange, endpoint, registry, METRICS_NAME); + inOrder.verify(exchange, times(1)).getIn(); inOrder.verify(registry, times(1)).meter(METRICS_NAME); inOrder.verify(endpoint, times(1)).getMark(); + inOrder.verify(in, times(1)).getHeader(HEADER_METER_MARK, MARK, Long.class); inOrder.verify(meter, times(1)).mark(MARK); inOrder.verifyNoMoreInteractions(); } @Test + public void testProcessMarkSetOverrideByHeaderValue() throws Exception { + when(endpoint.getMark()).thenReturn(MARK); + when(in.getHeader(HEADER_METER_MARK, MARK, Long.class)).thenReturn(MARK + 101); + producer.doProcess(exchange, endpoint, registry, METRICS_NAME); + inOrder.verify(exchange, times(1)).getIn(); + inOrder.verify(registry, times(1)).meter(METRICS_NAME); + inOrder.verify(endpoint, times(1)).getMark(); + inOrder.verify(in, times(1)).getHeader(HEADER_METER_MARK, MARK, Long.class); + inOrder.verify(meter, times(1)).mark(MARK + 101); + inOrder.verifyNoMoreInteractions(); + } + + @Test public void testProcessMarkNotSet() throws Exception { when(endpoint.getMark()).thenReturn(null); + when(in.getHeader(HEADER_METER_MARK, null, Long.class)).thenReturn(null); producer.doProcess(exchange, endpoint, registry, METRICS_NAME); inOrder.verify(registry, times(1)).meter(METRICS_NAME); inOrder.verify(endpoint, times(1)).getMark(); + inOrder.verify(in, times(1)).getHeader(HEADER_METER_MARK, null, Long.class); inOrder.verify(meter, times(1)).mark(); inOrder.verifyNoMoreInteractions(); } + + @Test + public void testProcessMarkNotSetOverrideByHeaderValue() throws Exception { + when(endpoint.getMark()).thenReturn(null); + when(in.getHeader(HEADER_METER_MARK, null, Long.class)).thenReturn(MARK); + producer.doProcess(exchange, endpoint, registry, METRICS_NAME); + inOrder.verify(registry, times(1)).meter(METRICS_NAME); + inOrder.verify(endpoint, times(1)).getMark(); + inOrder.verify(in, times(1)).getHeader(HEADER_METER_MARK, null, Long.class); + inOrder.verify(meter, times(1)).mark(MARK); + inOrder.verifyNoMoreInteractions(); + } } http://git-wip-us.apache.org/repos/asf/camel/blob/10f5c7c4/src/test/java/org/apache/camel/metrics/meter/MeterRouteTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/camel/metrics/meter/MeterRouteTest.java b/src/test/java/org/apache/camel/metrics/meter/MeterRouteTest.java index d6daf33..6bd5b59 100644 --- a/src/test/java/org/apache/camel/metrics/meter/MeterRouteTest.java +++ b/src/test/java/org/apache/camel/metrics/meter/MeterRouteTest.java @@ -1,5 +1,9 @@ package org.apache.camel.metrics.meter; +import static org.apache.camel.metrics.MetricsComponent.HEADER_METER_MARK; +import static org.apache.camel.metrics.MetricsComponent.HEADER_METRIC_NAME; +import static org.apache.camel.metrics.MetricsComponent.METRIC_REGISTRY_NAME; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; @@ -8,11 +12,12 @@ import org.apache.camel.Produce; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; -import org.apache.camel.metrics.MetricsComponent; import org.apache.camel.spring.javaconfig.SingleRouteCamelConfiguration; import org.apache.camel.test.spring.CamelSpringDelegatingTestContextLoader; import org.apache.camel.test.spring.CamelSpringJUnit4ClassRunner; import org.apache.camel.test.spring.MockEndpoints; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; @@ -34,8 +39,17 @@ public class MeterRouteTest { @EndpointInject(uri = "mock:out") private MockEndpoint endpoint; - @Produce(uri = "direct:in") - private ProducerTemplate producer; + @Produce(uri = "direct:in-1") + private ProducerTemplate producer1; + + @Produce(uri = "direct:in-2") + private ProducerTemplate producer2; + + private MetricRegistry mockRegistry; + + private Meter mockMeter; + + private InOrder inOrder; @Configuration public static class TestConfig extends SingleRouteCamelConfiguration { @@ -47,32 +61,91 @@ public class MeterRouteTest { @Override public void configure() throws Exception { - from("direct:in") + from("direct:in-1") .to("metrics:meter:A?mark=3179") .to("mock:out"); + + from("direct:in-2") + .to("metrics:meter:A") + .to("mock:out"); } }; } - @Bean(name = MetricsComponent.METRIC_REGISTRY_NAME) + @Bean(name = METRIC_REGISTRY_NAME) public MetricRegistry getMetricRegistry() { return Mockito.mock(MetricRegistry.class); } } + @Before + public void setup() { + // TODO - 12.05.2014, Lauri - is there any better way to set this up? + mockRegistry = endpoint.getCamelContext().getRegistry().lookupByNameAndType(METRIC_REGISTRY_NAME, MetricRegistry.class); + mockMeter = Mockito.mock(Meter.class); + inOrder = Mockito.inOrder(mockRegistry, mockMeter); + when(mockRegistry.meter("A")).thenReturn(mockMeter); + } + + @After + public void tearDown() { + endpoint.reset(); + reset(mockRegistry, mockMeter); + } + + @Test + public void testValueSetInUri() throws Exception { + Object body = new Object(); + endpoint.expectedBodiesReceived(body); + producer1.sendBody(body); + endpoint.assertIsSatisfied(); + inOrder.verify(mockRegistry, times(1)).meter("A"); + inOrder.verify(mockMeter, times(1)).mark(3179L); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testValueNoSetInUri() throws Exception { + Object body = new Object(); + endpoint.expectedBodiesReceived(body); + producer2.sendBody(body); + endpoint.assertIsSatisfied(); + inOrder.verify(mockRegistry, times(1)).meter("A"); + inOrder.verify(mockMeter, times(1)).mark(); + inOrder.verifyNoMoreInteractions(); + } + @Test public void testOverrideMetricsName() throws Exception { - // TODO - 12.05.2014, Lauri - is there any better way to set this up? - MetricRegistry mockRegistry = endpoint.getCamelContext().getRegistry().lookupByNameAndType(MetricsComponent.METRIC_REGISTRY_NAME, MetricRegistry.class); - Meter mockMeter = Mockito.mock(Meter.class); - InOrder inOrder = Mockito.inOrder(mockRegistry, mockMeter); when(mockRegistry.meter("B")).thenReturn(mockMeter); - - endpoint.expectedMessageCount(1); - producer.sendBodyAndHeader(new Object(), MetricsComponent.HEADER_METRIC_NAME, "B"); + Object body = new Object(); + endpoint.expectedBodiesReceived(body); + producer1.sendBodyAndHeader(body, HEADER_METRIC_NAME, "B"); endpoint.assertIsSatisfied(); inOrder.verify(mockRegistry, times(1)).meter("B"); inOrder.verify(mockMeter, times(1)).mark(3179L); inOrder.verifyNoMoreInteractions(); } + + @Test + public void testOverrideValueWithHeader() throws Exception { + Object body = new Object(); + endpoint.expectedBodiesReceived(body); + producer1.sendBodyAndHeader(body, HEADER_METER_MARK, 9926L); + endpoint.assertIsSatisfied(); + inOrder.verify(mockRegistry, times(1)).meter("A"); + inOrder.verify(mockMeter, times(1)).mark(9926L); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testValueNoSetInUriOverrideWithHeader() throws Exception { + Object body = new Object(); + endpoint.expectedBodiesReceived(body); + producer2.sendBodyAndHeader(body, HEADER_METER_MARK, 7707370L); + endpoint.assertIsSatisfied(); + inOrder.verify(mockRegistry, times(1)).meter("A"); + inOrder.verify(mockMeter, times(1)).mark(7707370L); + inOrder.verifyNoMoreInteractions(); + } }