Implemented metrics:timer endpoint.

Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/5deafafa
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/5deafafa
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/5deafafa

Branch: refs/heads/master
Commit: 5deafafa4d673fbce2c89ca54cfc340597cfc384
Parents: 0ad223e
Author: Lauri Kimmel <lauri.kim...@gmx.com>
Authored: Wed May 14 00:20:13 2014 +1000
Committer: Lauri Kimmel <lauri.kim...@gmx.com>
Committed: Wed May 14 00:20:13 2014 +1000

----------------------------------------------------------------------
 .../apache/camel/metrics/MetricsComponent.java  |   4 +
 .../camel/metrics/timer/TimerEndpoint.java      |  44 +++++
 .../camel/metrics/timer/TimerProducer.java      |  73 +++++++++
 .../metrics/MetricsComponentRouteTest.java      |   5 +-
 .../camel/metrics/MetricsComponentTest.java     |   7 +-
 .../camel/metrics/timer/TimerEndpointTest.java  |  75 +++++++++
 .../camel/metrics/timer/TimerProducerTest.java  | 161 +++++++++++++++++++
 7 files changed, 365 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/5deafafa/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 7d7d5ef..1f467c4 100644
--- a/src/main/java/org/apache/camel/metrics/MetricsComponent.java
+++ b/src/main/java/org/apache/camel/metrics/MetricsComponent.java
@@ -9,6 +9,7 @@ import org.apache.camel.impl.DefaultComponent;
 import org.apache.camel.metrics.counter.CounterEndpoint;
 import org.apache.camel.metrics.histogram.HistogramEndpoint;
 import org.apache.camel.metrics.meter.MeterEndpoint;
+import org.apache.camel.metrics.timer.TimerEndpoint;
 import org.apache.camel.spi.Registry;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
@@ -61,6 +62,9 @@ public class MetricsComponent extends DefaultComponent {
             case HISTOGRAM:
                 endpoint = new HistogramEndpoint(registry, metricsName);
                 break;
+            case TIMER:
+                endpoint = new TimerEndpoint(registry, metricsName);
+                break;
             default:
                 throw new RuntimeCamelException("Metrics type \"" + 
type.toString() + "\" not supported");
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/5deafafa/src/main/java/org/apache/camel/metrics/timer/TimerEndpoint.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/camel/metrics/timer/TimerEndpoint.java 
b/src/main/java/org/apache/camel/metrics/timer/TimerEndpoint.java
new file mode 100644
index 0000000..6de4e32
--- /dev/null
+++ b/src/main/java/org/apache/camel/metrics/timer/TimerEndpoint.java
@@ -0,0 +1,44 @@
+package org.apache.camel.metrics.timer;
+
+import org.apache.camel.Producer;
+import org.apache.camel.metrics.AbstractMetricsEndpoint;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+
+import com.codahale.metrics.MetricRegistry;
+
+@UriEndpoint(scheme = "metrics:timer")
+public class TimerEndpoint extends AbstractMetricsEndpoint {
+
+    public static final String ENDPOINT_URI = "metrics:timer";
+
+    public enum TimerAction {
+        start,
+        stop;
+    }
+
+    @UriParam
+    private TimerAction action;
+
+    public TimerEndpoint(MetricRegistry registry, String metricsName) {
+        super(registry, metricsName);
+    }
+
+    @Override
+    public Producer createProducer() throws Exception {
+        return new TimerProducer(this);
+    }
+
+    public TimerAction getAction() {
+        return action;
+    }
+
+    public void setAction(TimerAction action) {
+        this.action = action;
+    }
+
+    @Override
+    protected String createEndpointUri() {
+        return ENDPOINT_URI;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/5deafafa/src/main/java/org/apache/camel/metrics/timer/TimerProducer.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/camel/metrics/timer/TimerProducer.java 
b/src/main/java/org/apache/camel/metrics/timer/TimerProducer.java
new file mode 100644
index 0000000..f655352
--- /dev/null
+++ b/src/main/java/org/apache/camel/metrics/timer/TimerProducer.java
@@ -0,0 +1,73 @@
+package org.apache.camel.metrics.timer;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.impl.DefaultProducer;
+import org.apache.camel.metrics.timer.TimerEndpoint.TimerAction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Timer;
+
+public class TimerProducer extends DefaultProducer {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(TimerProducer.class);
+
+    public TimerProducer(Endpoint endpoint) {
+        super(endpoint);
+    }
+
+    @Override
+    public void process(Exchange exchange) throws Exception {
+        TimerEndpoint endpoint = (TimerEndpoint) getEndpoint();
+        MetricRegistry registry = endpoint.getRegistry();
+        String metricsName = endpoint.getMetricsName();
+        TimerAction action = endpoint.getAction();
+        if (action == TimerAction.start) {
+            handleStart(exchange, registry, metricsName);
+        }
+        else if (action == TimerAction.stop) {
+            handleStop(exchange, registry, metricsName);
+        }
+        else {
+            LOG.warn("No action provided for timer \"{}\"", metricsName);
+        }
+    }
+
+    void handleStart(Exchange exchange, MetricRegistry registry, String 
metricsName) {
+        String propertyName = getPropertyName(metricsName);
+        Timer.Context context = getTimerContextFromExchange(exchange, 
propertyName);
+        if (context == null) {
+            Timer timer = registry.timer(metricsName);
+            context = timer.time();
+            exchange.setProperty(propertyName, context);
+        }
+        else {
+            LOG.warn("Timer \"{}\" already running", metricsName);
+        }
+    }
+
+    void handleStop(Exchange exchange, MetricRegistry registry, String 
metricsName) {
+        String propertyName = getPropertyName(metricsName);
+        Timer.Context context = getTimerContextFromExchange(exchange, 
propertyName);
+        if (context != null) {
+            context.stop();
+            exchange.removeProperty(propertyName);
+        }
+        else {
+            LOG.warn("Timer \"{}\" not found", metricsName);
+        }
+    }
+
+    String getPropertyName(String metricsName) {
+        return new StringBuilder(TimerEndpoint.ENDPOINT_URI)
+                .append(":")
+                .append(metricsName)
+                .toString();
+    }
+
+    Timer.Context getTimerContextFromExchange(Exchange exchange, String 
propertyName) {
+        return exchange.getProperty(propertyName, Timer.Context.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/5deafafa/src/test/java/org/apache/camel/metrics/MetricsComponentRouteTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/camel/metrics/MetricsComponentRouteTest.java 
b/src/test/java/org/apache/camel/metrics/MetricsComponentRouteTest.java
index 5ff0ed4..5af70b9 100644
--- a/src/test/java/org/apache/camel/metrics/MetricsComponentRouteTest.java
+++ b/src/test/java/org/apache/camel/metrics/MetricsComponentRouteTest.java
@@ -26,8 +26,7 @@ public class MetricsComponentRouteTest extends 
CamelTestSupport {
             @Override
             public void configure() {
                 from("direct:start")
-                        // .to("metrics")
-                        // .to("metrics:")
+                        .to("metrics:timer:T?action=start")
                         .to("metrics:A")
                         .to("metrics:counter://B")
                         .to("metrics:counter:C?increment=19291")
@@ -36,7 +35,9 @@ public class MetricsComponentRouteTest extends 
CamelTestSupport {
                         .to("metrics:meter:D")
                         .to("metrics:meter:D?mark=90001")
                         .to("metrics:histogram:E")
+                        .to("metrics:timer:T")
                         .to("metrics:histogram:E?value=12000000031")
+                        .to("metrics:timer:T?action=stop")
                         .to("mock:result");
             }
         };

http://git-wip-us.apache.org/repos/asf/camel/blob/5deafafa/src/test/java/org/apache/camel/metrics/MetricsComponentTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/camel/metrics/MetricsComponentTest.java 
b/src/test/java/org/apache/camel/metrics/MetricsComponentTest.java
index 7c1c189..74d91c2 100644
--- a/src/test/java/org/apache/camel/metrics/MetricsComponentTest.java
+++ b/src/test/java/org/apache/camel/metrics/MetricsComponentTest.java
@@ -18,6 +18,7 @@ import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.metrics.counter.CounterEndpoint;
 import org.apache.camel.metrics.histogram.HistogramEndpoint;
 import org.apache.camel.metrics.meter.MeterEndpoint;
+import org.apache.camel.metrics.timer.TimerEndpoint;
 import org.apache.camel.spi.Registry;
 import org.junit.Before;
 import org.junit.Test;
@@ -143,9 +144,11 @@ public class MetricsComponentTest {
         assertThat(endpoint, is(instanceOf(HistogramEndpoint.class)));
     }
 
-    @Test(expected = RuntimeCamelException.class)
+    @Test
     public void testCreateNewEndpointForTimer() throws Exception {
-        component.createNewEndpoint(metricRegistry, MetricsType.TIMER, "a 
name");
+        Endpoint endpoint = component.createNewEndpoint(metricRegistry, 
MetricsType.TIMER, "a name");
+        assertThat(endpoint, is(notNullValue()));
+        assertThat(endpoint, is(instanceOf(TimerEndpoint.class)));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/camel/blob/5deafafa/src/test/java/org/apache/camel/metrics/timer/TimerEndpointTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/camel/metrics/timer/TimerEndpointTest.java 
b/src/test/java/org/apache/camel/metrics/timer/TimerEndpointTest.java
new file mode 100644
index 0000000..cb3232f
--- /dev/null
+++ b/src/test/java/org/apache/camel/metrics/timer/TimerEndpointTest.java
@@ -0,0 +1,75 @@
+package org.apache.camel.metrics.timer;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+
+import org.apache.camel.Producer;
+import org.apache.camel.metrics.timer.TimerEndpoint.TimerAction;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import com.codahale.metrics.MetricRegistry;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TimerEndpointTest {
+
+    private static final String METRICS_NAME = "metrics.name";
+
+    @Mock
+    private MetricRegistry registry;
+
+    private TimerEndpoint endpoint;
+
+    private InOrder inOrder;
+
+    @Before
+    public void setUp() throws Exception {
+        endpoint = new TimerEndpoint(registry, METRICS_NAME);
+        inOrder = Mockito.inOrder(registry);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testTimerEndpoint() throws Exception {
+        assertThat(endpoint, is(notNullValue()));
+        assertThat(endpoint.getRegistry(), is(registry));
+        assertThat(endpoint.getMetricsName(), is(METRICS_NAME));
+    }
+
+    @Test
+    public void testCreateProducer() throws Exception {
+        Producer producer = endpoint.createProducer();
+        assertThat(producer, is(notNullValue()));
+        assertThat(producer, is(instanceOf(TimerProducer.class)));
+    }
+
+    @Test
+    public void testGetAction() throws Exception {
+        assertThat(endpoint.getAction(), is(nullValue()));
+    }
+
+    @Test
+    public void testSetAction() throws Exception {
+        assertThat(endpoint.getAction(), is(nullValue()));
+        endpoint.setAction(TimerAction.start);
+        assertThat(endpoint.getAction(), is(TimerAction.start));
+    }
+
+    @Test
+    public void testCreateEndpointUri() throws Exception {
+        assertThat(endpoint.createEndpointUri(), 
is(TimerEndpoint.ENDPOINT_URI));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/5deafafa/src/test/java/org/apache/camel/metrics/timer/TimerProducerTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/camel/metrics/timer/TimerProducerTest.java 
b/src/test/java/org/apache/camel/metrics/timer/TimerProducerTest.java
new file mode 100644
index 0000000..86ec26d
--- /dev/null
+++ b/src/test/java/org/apache/camel/metrics/timer/TimerProducerTest.java
@@ -0,0 +1,161 @@
+package org.apache.camel.metrics.timer;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.metrics.timer.TimerEndpoint.TimerAction;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Timer;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TimerProducerTest {
+
+    private static final String METRICS_NAME = "metrics.name";
+    private static final String PROPERTY_NAME = TimerEndpoint.ENDPOINT_URI + 
":" + METRICS_NAME;
+
+    @Mock
+    private TimerEndpoint endpoint;
+
+    @Mock
+    private Exchange exchange;
+
+    @Mock
+    private MetricRegistry registry;
+
+    @Mock
+    private Timer timer;
+
+    @Mock
+    private Timer.Context context;
+
+    private TimerProducer producer;
+
+    @Mock
+    private InOrder inOrder;
+
+    @Before
+    public void setUp() throws Exception {
+        producer = new TimerProducer(endpoint);
+        inOrder = Mockito.inOrder(endpoint, exchange, registry, timer, 
context);
+        when(endpoint.getRegistry()).thenReturn(registry);
+        when(endpoint.getMetricsName()).thenReturn(METRICS_NAME);
+        when(registry.timer(METRICS_NAME)).thenReturn(timer);
+        when(timer.time()).thenReturn(context);
+    }
+
+    @Test
+    public void testTimerProducer() throws Exception {
+        assertThat(producer, is(notNullValue()));
+        assertThat(producer.getEndpoint().equals(endpoint), is(true));
+    }
+
+    @Test
+    public void testProcessStart() throws Exception {
+        when(endpoint.getAction()).thenReturn(TimerAction.start);
+        when(exchange.getProperty(PROPERTY_NAME, 
Timer.Context.class)).thenReturn(null);
+        producer.process(exchange);
+        inOrder.verify(endpoint, times(1)).getRegistry();
+        inOrder.verify(endpoint, times(1)).getMetricsName();
+        inOrder.verify(endpoint, times(1)).getAction();
+        inOrder.verify(exchange, times(1)).getProperty(PROPERTY_NAME, 
Timer.Context.class);
+        inOrder.verify(registry, times(1)).timer(METRICS_NAME);
+        inOrder.verify(timer, times(1)).time();
+        inOrder.verify(exchange, times(1)).setProperty(PROPERTY_NAME, context);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testProcessStop() throws Exception {
+        when(endpoint.getAction()).thenReturn(TimerAction.stop);
+        when(exchange.getProperty(PROPERTY_NAME, 
Timer.Context.class)).thenReturn(context);
+        producer.process(exchange);
+        inOrder.verify(endpoint, times(1)).getRegistry();
+        inOrder.verify(endpoint, times(1)).getMetricsName();
+        inOrder.verify(endpoint, times(1)).getAction();
+        inOrder.verify(exchange, times(1)).getProperty(PROPERTY_NAME, 
Timer.Context.class);
+        inOrder.verify(context, times(1)).stop();
+        inOrder.verify(exchange, times(1)).removeProperty(PROPERTY_NAME);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testProcessNoAction() throws Exception {
+        when(endpoint.getAction()).thenReturn(null);
+        producer.process(exchange);
+        inOrder.verify(endpoint, times(1)).getRegistry();
+        inOrder.verify(endpoint, times(1)).getMetricsName();
+        inOrder.verify(endpoint, times(1)).getAction();
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testHandleStart() throws Exception {
+        when(exchange.getProperty(PROPERTY_NAME, 
Timer.Context.class)).thenReturn(null);
+        producer.handleStart(exchange, registry, METRICS_NAME);
+        inOrder.verify(exchange, times(1)).getProperty(PROPERTY_NAME, 
Timer.Context.class);
+        inOrder.verify(registry, times(1)).timer(METRICS_NAME);
+        inOrder.verify(timer, times(1)).time();
+        inOrder.verify(exchange, times(1)).setProperty(PROPERTY_NAME, context);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testHandleStartAlreadyRunning() throws Exception {
+        when(exchange.getProperty(PROPERTY_NAME, 
Timer.Context.class)).thenReturn(context);
+        producer.handleStart(exchange, registry, METRICS_NAME);
+        inOrder.verify(exchange, times(1)).getProperty(PROPERTY_NAME, 
Timer.Context.class);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testHandleStop() throws Exception {
+        when(exchange.getProperty(PROPERTY_NAME, 
Timer.Context.class)).thenReturn(context);
+        producer.handleStop(exchange, registry, METRICS_NAME);
+        inOrder.verify(exchange, times(1)).getProperty(PROPERTY_NAME, 
Timer.Context.class);
+        inOrder.verify(context, times(1)).stop();
+        inOrder.verify(exchange, times(1)).removeProperty(PROPERTY_NAME);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testHandleStopContextNotFound() throws Exception {
+        when(exchange.getProperty(PROPERTY_NAME, 
Timer.Context.class)).thenReturn(null);
+        producer.handleStop(exchange, registry, METRICS_NAME);
+        inOrder.verify(exchange, times(1)).getProperty(PROPERTY_NAME, 
Timer.Context.class);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testGetPropertyName() throws Exception {
+        assertThat(producer.getPropertyName(METRICS_NAME), 
is(TimerEndpoint.ENDPOINT_URI + ":" + METRICS_NAME));
+    }
+
+    @Test
+    public void testGetTimerContextFromExchange() throws Exception {
+        when(exchange.getProperty(PROPERTY_NAME, 
Timer.Context.class)).thenReturn(context);
+        assertThat(producer.getTimerContextFromExchange(exchange, 
PROPERTY_NAME), is(context));
+        inOrder.verify(exchange, times(1)).getProperty(PROPERTY_NAME, 
Timer.Context.class);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testGetTimerContextFromExchangeNotFound() throws Exception {
+        when(exchange.getProperty(PROPERTY_NAME, 
Timer.Context.class)).thenReturn(null);
+        assertThat(producer.getTimerContextFromExchange(exchange, 
PROPERTY_NAME), is(nullValue()));
+        inOrder.verify(exchange, times(1)).getProperty(PROPERTY_NAME, 
Timer.Context.class);
+        inOrder.verifyNoMoreInteractions();
+    }
+}

Reply via email to