CAMEL-8038: Fixed camel-metrics to be like others.

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

Branch: refs/heads/master
Commit: 4a84f061f74f759e77d45c369a95b704f38c1a92
Parents: 4c56828
Author: Claus Ibsen <davscl...@apache.org>
Authored: Fri Nov 14 15:47:37 2014 +0100
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Fri Nov 14 15:47:37 2014 +0100

----------------------------------------------------------------------
 .../metrics/AbstractMetricsEndpoint.java        |  53 -----
 .../metrics/AbstractMetricsProducer.java        |  27 ++-
 .../component/metrics/CounterProducer.java      |  51 +++++
 .../component/metrics/HistogramProducer.java    |  48 ++++
 .../camel/component/metrics/MeterProducer.java  |  44 ++++
 .../component/metrics/MetricsComponent.java     |  38 +--
 .../component/metrics/MetricsEndpoint.java      | 133 +++++++++++
 .../component/metrics/MetricsTimerAction.java   |  23 ++
 .../camel/component/metrics/TimerProducer.java  |  83 +++++++
 .../metrics/counter/CounterEndpoint.java        |  66 ------
 .../metrics/counter/CounterProducer.java        |  52 -----
 .../metrics/histogram/HistogramEndpoint.java    |  55 -----
 .../metrics/histogram/HistogramProducer.java    |  50 ----
 .../component/metrics/meter/MeterEndpoint.java  |  55 -----
 .../component/metrics/meter/MeterProducer.java  |  45 ----
 .../component/metrics/timer/TimerEndpoint.java  |  59 -----
 .../component/metrics/timer/TimerProducer.java  |  86 -------
 .../metrics/AbstractMetricsEndpointTest.java    | 105 ---------
 .../metrics/AbstractMetricsProducerTest.java    |  15 +-
 .../component/metrics/CounterEndpointTest.java  |  99 ++++++++
 .../component/metrics/CounterProducerTest.java  | 196 ++++++++++++++++
 .../component/metrics/CounterRouteTest.java     | 200 ++++++++++++++++
 .../metrics/HistogramEndpointTest.java          |  85 +++++++
 .../metrics/HistogramProducerTest.java          | 128 +++++++++++
 .../component/metrics/HistogramRouteTest.java   | 124 ++++++++++
 .../component/metrics/MeterEndpointTest.java    |  86 +++++++
 .../component/metrics/MeterProducerTest.java    | 127 ++++++++++
 .../camel/component/metrics/MeterRouteTest.java | 166 ++++++++++++++
 .../metrics/MetricComponentSpringTest.java      |   1 +
 .../metrics/MetricsComponentRouteTest.java      |   2 +
 .../component/metrics/MetricsComponentTest.java |  40 ++--
 .../component/metrics/MetricsEndpointTest.java  | 106 +++++++++
 .../component/metrics/MetricsTypeTest.java      |   1 +
 .../component/metrics/TimerEndpointTest.java    |  85 +++++++
 .../component/metrics/TimerProducerTest.java    | 229 +++++++++++++++++++
 .../camel/component/metrics/TimerRouteTest.java | 144 ++++++++++++
 .../metrics/counter/CounterEndpointTest.java    | 102 ---------
 .../metrics/counter/CounterProducerTest.java    | 195 ----------------
 .../metrics/counter/CounterRouteTest.java       | 210 -----------------
 .../histogram/HistogramEndpointTest.java        |  88 -------
 .../histogram/HistogramProducerTest.java        | 125 ----------
 .../metrics/histogram/HistogramRouteTest.java   | 124 ----------
 .../metrics/meter/MeterEndpointTest.java        |  89 -------
 .../metrics/meter/MeterProducerTest.java        | 126 ----------
 .../component/metrics/meter/MeterRouteTest.java | 166 --------------
 .../metrics/timer/TimerEndpointTest.java        |  89 -------
 .../metrics/timer/TimerProducerTest.java        | 229 -------------------
 .../component/metrics/timer/TimerRouteTest.java | 145 ------------
 48 files changed, 2212 insertions(+), 2383 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/AbstractMetricsEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/AbstractMetricsEndpoint.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/AbstractMetricsEndpoint.java
deleted file mode 100644
index 594e0c3..0000000
--- 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/AbstractMetricsEndpoint.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.camel.component.metrics;
-
-import com.codahale.metrics.MetricRegistry;
-import org.apache.camel.Consumer;
-import org.apache.camel.Processor;
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.impl.DefaultEndpoint;
-
-
-public abstract class AbstractMetricsEndpoint extends DefaultEndpoint {
-
-    protected final MetricRegistry registry;
-    protected final String metricsName;
-
-    public AbstractMetricsEndpoint(MetricRegistry registry, String 
metricsName) {
-        this.registry = registry;
-        this.metricsName = metricsName;
-    }
-
-    @Override
-    public Consumer createConsumer(Processor processor) throws Exception {
-        throw new RuntimeCamelException("Cannot consume from " + 
getClass().getSimpleName() + ": " + getEndpointUri());
-    }
-
-    @Override
-    public boolean isSingleton() {
-        return false;
-    }
-
-    public MetricRegistry getRegistry() {
-        return registry;
-    }
-
-    public String getMetricsName() {
-        return metricsName;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/AbstractMetricsProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/AbstractMetricsProducer.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/AbstractMetricsProducer.java
index 4ee8b21..538b0c4 100644
--- 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/AbstractMetricsProducer.java
+++ 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/AbstractMetricsProducer.java
@@ -24,34 +24,37 @@ import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
-public abstract class AbstractMetricsProducer<T extends 
AbstractMetricsEndpoint> extends DefaultProducer {
+public abstract class AbstractMetricsProducer extends DefaultProducer {
 
     public static final String HEADER_PATTERN = MetricsConstants.HEADER_PERFIX 
+ "*";
     private static final Logger LOG = 
LoggerFactory.getLogger(AbstractMetricsProducer.class);
 
-    public AbstractMetricsProducer(T endpoint) {
+    public AbstractMetricsProducer(MetricsEndpoint endpoint) {
         super(endpoint);
     }
 
     @Override
+    public MetricsEndpoint getEndpoint() {
+        return (MetricsEndpoint) super.getEndpoint();
+    }
+
+    @Override
     public void process(Exchange exchange) throws Exception {
-        @SuppressWarnings("unchecked")
-        T endpoint = (T) getEndpoint();
         Message in = exchange.getIn();
-        String defaultMetricsName = endpoint.getMetricsName();
+        String defaultMetricsName = getEndpoint().getMetricsName();
         String finalMetricsName = getMetricsName(in, defaultMetricsName);
-        MetricRegistry registry = endpoint.getRegistry();
+        MetricRegistry registry = getEndpoint().getRegistry();
+
         try {
-            doProcess(exchange, endpoint, registry, finalMetricsName);
+            doProcess(exchange, getEndpoint(), registry, finalMetricsName);
         } catch (Exception e) {
-            LOG.warn("Failed to produce metrics for {} in {} - {}", new 
Object[] {
-                finalMetricsName, getClass().getSimpleName(), e.getMessage() 
});
+            exchange.setException(e);
+        } finally {
+            clearMetricsHeaders(in);
         }
-        clearMetricsHeaders(in);
     }
 
-    protected abstract void doProcess(Exchange exchange, T endpoint, 
MetricRegistry registry, String metricsName) throws Exception;
+    protected abstract void doProcess(Exchange exchange, MetricsEndpoint 
endpoint, MetricRegistry registry, String metricsName) throws Exception;
 
     public String getMetricsName(Message in, String defaultValue) {
         return getStringHeader(in, MetricsConstants.HEADER_METRIC_NAME, 
defaultValue);

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/CounterProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/CounterProducer.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/CounterProducer.java
new file mode 100644
index 0000000..afb9a7b
--- /dev/null
+++ 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/CounterProducer.java
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.component.metrics;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.metrics.AbstractMetricsProducer;
+import org.apache.camel.component.metrics.MetricsEndpoint;
+
+import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_COUNTER_DECREMENT;
+import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_COUNTER_INCREMENT;
+
+public class CounterProducer extends AbstractMetricsProducer {
+
+    public CounterProducer(MetricsEndpoint endpoint) {
+        super(endpoint);
+    }
+
+    @Override
+    protected void doProcess(Exchange exchange, MetricsEndpoint endpoint, 
MetricRegistry registry, String metricsName) throws Exception {
+        Message in = exchange.getIn();
+        Counter counter = registry.counter(metricsName);
+        Long increment = endpoint.getIncrement();
+        Long decrement = endpoint.getDecrement();
+        Long finalIncrement = getLongHeader(in, HEADER_COUNTER_INCREMENT, 
increment);
+        Long finalDecrement = getLongHeader(in, HEADER_COUNTER_DECREMENT, 
decrement);
+        if (finalIncrement != null) {
+            counter.inc(finalIncrement);
+        } else if (finalDecrement != null) {
+            counter.dec(finalDecrement);
+        } else {
+            counter.inc();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/HistogramProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/HistogramProducer.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/HistogramProducer.java
new file mode 100644
index 0000000..73836f7
--- /dev/null
+++ 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/HistogramProducer.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.component.metrics;
+
+import com.codahale.metrics.Histogram;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_HISTOGRAM_VALUE;
+
+public class HistogramProducer extends AbstractMetricsProducer {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(HistogramProducer.class);
+
+    public HistogramProducer(MetricsEndpoint endpoint) {
+        super(endpoint);
+    }
+
+    @Override
+    protected void doProcess(Exchange exchange, MetricsEndpoint endpoint, 
MetricRegistry registry, String metricsName) throws Exception {
+        Message in = exchange.getIn();
+        Histogram histogram = registry.histogram(metricsName);
+        Long value = endpoint.getValue();
+        Long finalValue = getLongHeader(in, HEADER_HISTOGRAM_VALUE, value);
+        if (finalValue != null) {
+            histogram.update(finalValue);
+        } else {
+            LOG.warn("Cannot update histogram \"{}\" with null value", 
metricsName);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MeterProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MeterProducer.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MeterProducer.java
new file mode 100644
index 0000000..4aac25f
--- /dev/null
+++ 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MeterProducer.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.component.metrics;
+
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+
+import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_METER_MARK;
+
+public class MeterProducer extends AbstractMetricsProducer {
+
+    public MeterProducer(MetricsEndpoint endpoint) {
+        super(endpoint);
+    }
+
+    @Override
+    protected void doProcess(Exchange exchange, MetricsEndpoint endpoint, 
MetricRegistry registry, String metricsName) throws Exception {
+        Message in = exchange.getIn();
+        Meter meter = registry.meter(metricsName);
+        Long mark = endpoint.getMark();
+        Long finalMark = getLongHeader(in, HEADER_METER_MARK, mark);
+        if (finalMark == null) {
+            meter.mark();
+        } else {
+            meter.mark(finalMark);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsComponent.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsComponent.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsComponent.java
index 962721e..7de4479 100644
--- 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsComponent.java
+++ 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsComponent.java
@@ -23,11 +23,7 @@ import com.codahale.metrics.MetricRegistry;
 import com.codahale.metrics.Slf4jReporter;
 import org.apache.camel.Endpoint;
 import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.component.metrics.counter.CounterEndpoint;
-import org.apache.camel.component.metrics.histogram.HistogramEndpoint;
-import org.apache.camel.component.metrics.meter.MeterEndpoint;
-import org.apache.camel.component.metrics.timer.TimerEndpoint;
-import org.apache.camel.impl.DefaultComponent;
+import org.apache.camel.impl.UriEndpointComponent;
 import org.apache.camel.spi.Registry;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
@@ -36,7 +32,7 @@ import org.slf4j.LoggerFactory;
 /**
  * Represents the component that manages metrics endpoints.
  */
-public class MetricsComponent extends DefaultComponent {
+public class MetricsComponent extends UriEndpointComponent {
 
     public static final String METRIC_REGISTRY_NAME = "metricRegistry";
     public static final MetricsType DEFAULT_METRICS_TYPE = MetricsType.METER;
@@ -46,6 +42,10 @@ public class MetricsComponent extends DefaultComponent {
 
     private MetricRegistry metricRegistry;
 
+    public MetricsComponent() {
+        super(MetricsEndpoint.class);
+    }
+
     @Override
     protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
         if (metricRegistry == null) {
@@ -54,8 +54,9 @@ public class MetricsComponent extends DefaultComponent {
         }
         String metricsName = getMetricsName(remaining);
         MetricsType metricsType = getMetricsType(remaining);
-        LOG.info("Metrics type: {}; name: {}", metricsType, metricsName);
-        Endpoint endpoint = createNewEndpoint(metricRegistry, metricsType, 
metricsName);
+
+        LOG.debug("Metrics type: {}; name: {}", metricsType, metricsName);
+        Endpoint endpoint = new MetricsEndpoint(uri, this, metricRegistry, 
metricsType, metricsName);
         setProperties(endpoint, parameters);
         return endpoint;
     }
@@ -65,27 +66,6 @@ public class MetricsComponent extends DefaultComponent {
         return name == null ? remaining : name;
     }
 
-    Endpoint createNewEndpoint(MetricRegistry registry, MetricsType type, 
String metricsName) {
-        Endpoint endpoint;
-        switch (type) {
-        case COUNTER:
-            endpoint = new CounterEndpoint(registry, metricsName);
-            break;
-        case METER:
-            endpoint = new MeterEndpoint(registry, metricsName);
-            break;
-        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");
-        }
-        return endpoint;
-    }
-
     MetricsType getMetricsType(String remaining) {
         String name = ObjectHelper.before(remaining, ":");
         MetricsType type;

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsEndpoint.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsEndpoint.java
new file mode 100644
index 0000000..0d77413
--- /dev/null
+++ 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsEndpoint.java
@@ -0,0 +1,133 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.component.metrics;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.camel.Component;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.impl.DefaultEndpoint;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriPath;
+
+@UriEndpoint(scheme = "metrics", label = "monitoring")
+public class MetricsEndpoint extends DefaultEndpoint {
+
+    protected final MetricRegistry registry;
+
+    @UriPath(description = "Type of metrics")
+    protected final MetricsType metricsType;
+    @UriPath(description = "Name of metrics")
+    protected final String metricsName;
+    @UriParam(description = "Action when using timer type")
+    private MetricsTimerAction action;
+    @UriParam(description = "Mark when using meter type")
+    private Long mark;
+    @UriParam(description = "Value value when using histogram type")
+    private Long value;
+    @UriParam(description = "Increment value when using counter type")
+    private Long increment;
+    @UriParam(description = "Decrement value when using counter type")
+    private Long decrement;
+
+    public MetricsEndpoint(String uri, Component component, MetricRegistry 
registry, MetricsType metricsType, String metricsName) {
+        super(uri, component);
+        this.registry = registry;
+        this.metricsType = metricsType;
+        this.metricsName = metricsName;
+    }
+
+    @Override
+    public Consumer createConsumer(Processor processor) throws Exception {
+        throw new RuntimeCamelException("Cannot consume from " + 
getClass().getSimpleName() + ": " + getEndpointUri());
+    }
+
+    @Override
+    public Producer createProducer() throws Exception {
+        if (metricsType == MetricsType.COUNTER) {
+            return new CounterProducer(this);
+        } else if (metricsType == MetricsType.HISTOGRAM) {
+            return new HistogramProducer(this);
+        } else if (metricsType == MetricsType.METER) {
+            return new MeterProducer(this);
+        } else if (metricsType == MetricsType.TIMER) {
+            return new TimerProducer(this);
+        } else {
+            throw new IllegalArgumentException("Metrics type " + metricsType + 
" is not supported");
+        }
+    }
+
+    @Override
+    public boolean isSingleton() {
+        return true;
+    }
+
+    public MetricRegistry getRegistry() {
+        return registry;
+    }
+
+    public String getMetricsName() {
+        return metricsName;
+    }
+
+    public MetricsType getMetricsType() {
+        return metricsType;
+    }
+
+    public MetricsTimerAction getAction() {
+        return action;
+    }
+
+    public void setAction(MetricsTimerAction action) {
+        this.action = action;
+    }
+
+    public Long getMark() {
+        return mark;
+    }
+
+    public void setMark(Long mark) {
+        this.mark = mark;
+    }
+
+    public Long getValue() {
+        return value;
+    }
+
+    public void setValue(Long value) {
+        this.value = value;
+    }
+
+    public Long getIncrement() {
+        return increment;
+    }
+
+    public void setIncrement(Long increment) {
+        this.increment = increment;
+    }
+
+    public Long getDecrement() {
+        return decrement;
+    }
+
+    public void setDecrement(Long decrement) {
+        this.decrement = decrement;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsTimerAction.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsTimerAction.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsTimerAction.java
new file mode 100644
index 0000000..4dcb8c9
--- /dev/null
+++ 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/MetricsTimerAction.java
@@ -0,0 +1,23 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.component.metrics;
+
+public enum MetricsTimerAction {
+
+    start, stop
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/TimerProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/TimerProducer.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/TimerProducer.java
new file mode 100644
index 0000000..dfc7580
--- /dev/null
+++ 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/TimerProducer.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.component.metrics;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Timer;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_TIMER_ACTION;
+
+public class TimerProducer extends AbstractMetricsProducer {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(TimerProducer.class);
+
+    public TimerProducer(MetricsEndpoint endpoint) {
+        super(endpoint);
+    }
+
+    @Override
+    protected void doProcess(Exchange exchange, MetricsEndpoint endpoint, 
MetricRegistry registry, String metricsName) throws Exception {
+        Message in = exchange.getIn();
+        MetricsTimerAction action = endpoint.getAction();
+        MetricsTimerAction finalAction = in.getHeader(HEADER_TIMER_ACTION, 
action, MetricsTimerAction.class);
+        if (finalAction == MetricsTimerAction.start) {
+            handleStart(exchange, registry, metricsName);
+        } else if (finalAction == MetricsTimerAction.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("timer")
+                .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/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/counter/CounterEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/counter/CounterEndpoint.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/counter/CounterEndpoint.java
deleted file mode 100644
index 2eae8f2..0000000
--- 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/counter/CounterEndpoint.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.camel.component.metrics.counter;
-
-import com.codahale.metrics.MetricRegistry;
-import org.apache.camel.Producer;
-import org.apache.camel.component.metrics.AbstractMetricsEndpoint;
-import org.apache.camel.spi.UriEndpoint;
-import org.apache.camel.spi.UriParam;
-
-
-@UriEndpoint(scheme = "metrics")
-public class CounterEndpoint extends AbstractMetricsEndpoint {
-
-    public static final String ENDPOINT_URI = "metrics:counter";
-
-    @UriParam
-    private Long increment;
-
-    @UriParam
-    private Long decrement;
-
-    public CounterEndpoint(MetricRegistry registry, String metricsName) {
-        super(registry, metricsName);
-    }
-
-    @Override
-    public Producer createProducer() throws Exception {
-        return new CounterProducer(this);
-    }
-
-    public Long getIncrement() {
-        return increment;
-    }
-
-    public void setIncrement(Long increment) {
-        this.increment = increment;
-    }
-
-    public Long getDecrement() {
-        return decrement;
-    }
-
-    public void setDecrement(Long decrement) {
-        this.decrement = decrement;
-    }
-
-    @Override
-    protected String createEndpointUri() {
-        return ENDPOINT_URI;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/counter/CounterProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/counter/CounterProducer.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/counter/CounterProducer.java
deleted file mode 100644
index 7525866..0000000
--- 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/counter/CounterProducer.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.camel.component.metrics.counter;
-
-
-import com.codahale.metrics.Counter;
-import com.codahale.metrics.MetricRegistry;
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.metrics.AbstractMetricsProducer;
-
-import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_COUNTER_DECREMENT;
-import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_COUNTER_INCREMENT;
-
-
-public class CounterProducer extends AbstractMetricsProducer<CounterEndpoint> {
-
-    public CounterProducer(CounterEndpoint endpoint) {
-        super(endpoint);
-    }
-
-    @Override
-    protected void doProcess(Exchange exchange, CounterEndpoint endpoint, 
MetricRegistry registry, String metricsName) throws Exception {
-        Message in = exchange.getIn();
-        Counter counter = registry.counter(metricsName);
-        Long increment = endpoint.getIncrement();
-        Long decrement = endpoint.getDecrement();
-        Long finalIncrement = getLongHeader(in, HEADER_COUNTER_INCREMENT, 
increment);
-        Long finalDecrement = getLongHeader(in, HEADER_COUNTER_DECREMENT, 
decrement);
-        if (finalIncrement != null) {
-            counter.inc(finalIncrement);
-        } else if (finalDecrement != null) {
-            counter.dec(finalDecrement);
-        } else {
-            counter.inc();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/histogram/HistogramEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/histogram/HistogramEndpoint.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/histogram/HistogramEndpoint.java
deleted file mode 100644
index bf7ce6c..0000000
--- 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/histogram/HistogramEndpoint.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.camel.component.metrics.histogram;
-
-import com.codahale.metrics.MetricRegistry;
-import org.apache.camel.Producer;
-import org.apache.camel.component.metrics.AbstractMetricsEndpoint;
-import org.apache.camel.spi.UriEndpoint;
-import org.apache.camel.spi.UriParam;
-
-
-@UriEndpoint(scheme = "metrics")
-public class HistogramEndpoint extends AbstractMetricsEndpoint {
-
-    public static final String ENDPOINT_URI = "metrics:histogram";
-
-    @UriParam
-    private Long value;
-
-    public HistogramEndpoint(MetricRegistry registry, String metricsName) {
-        super(registry, metricsName);
-    }
-
-    @Override
-    public Producer createProducer() throws Exception {
-        return new HistogramProducer(this);
-    }
-
-    public Long getValue() {
-        return value;
-    }
-
-    public void setValue(Long value) {
-        this.value = value;
-    }
-
-    @Override
-    protected String createEndpointUri() {
-        return ENDPOINT_URI;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/histogram/HistogramProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/histogram/HistogramProducer.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/histogram/HistogramProducer.java
deleted file mode 100644
index 530e934..0000000
--- 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/histogram/HistogramProducer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.camel.component.metrics.histogram;
-
-
-import com.codahale.metrics.Histogram;
-import com.codahale.metrics.MetricRegistry;
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.metrics.AbstractMetricsProducer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_HISTOGRAM_VALUE;
-
-public class HistogramProducer extends 
AbstractMetricsProducer<HistogramEndpoint> {
-
-    private static final Logger LOG = 
LoggerFactory.getLogger(HistogramProducer.class);
-
-    public HistogramProducer(HistogramEndpoint endpoint) {
-        super(endpoint);
-    }
-
-    @Override
-    protected void doProcess(Exchange exchange, HistogramEndpoint endpoint, 
MetricRegistry registry, String metricsName) throws Exception {
-        Message in = exchange.getIn();
-        Histogram histogram = registry.histogram(metricsName);
-        Long value = endpoint.getValue();
-        Long finalValue = getLongHeader(in, HEADER_HISTOGRAM_VALUE, value);
-        if (finalValue != null) {
-            histogram.update(finalValue);
-        } else {
-            LOG.warn("Cannot update histogram \"{}\" with null value", 
metricsName);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/meter/MeterEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/meter/MeterEndpoint.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/meter/MeterEndpoint.java
deleted file mode 100644
index f376261..0000000
--- 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/meter/MeterEndpoint.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.camel.component.metrics.meter;
-
-import com.codahale.metrics.MetricRegistry;
-import org.apache.camel.Producer;
-import org.apache.camel.component.metrics.AbstractMetricsEndpoint;
-import org.apache.camel.spi.UriEndpoint;
-import org.apache.camel.spi.UriParam;
-
-
-@UriEndpoint(scheme = "metrics")
-public class MeterEndpoint extends AbstractMetricsEndpoint {
-
-    public static final String ENDPOINT_URI = "metrics:meter";
-
-    @UriParam
-    private Long mark;
-
-    public MeterEndpoint(MetricRegistry registry, String metricsName) {
-        super(registry, metricsName);
-    }
-
-    @Override
-    public Producer createProducer() throws Exception {
-        return new MeterProducer(this);
-    }
-
-    public Long getMark() {
-        return mark;
-    }
-
-    public void setMark(Long mark) {
-        this.mark = mark;
-    }
-
-    @Override
-    protected String createEndpointUri() {
-        return ENDPOINT_URI;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/meter/MeterProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/meter/MeterProducer.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/meter/MeterProducer.java
deleted file mode 100644
index f6becca..0000000
--- 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/meter/MeterProducer.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.camel.component.metrics.meter;
-
-import com.codahale.metrics.Meter;
-import com.codahale.metrics.MetricRegistry;
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.metrics.AbstractMetricsProducer;
-
-import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_METER_MARK;
-
-public class MeterProducer extends AbstractMetricsProducer<MeterEndpoint> {
-
-    public MeterProducer(MeterEndpoint endpoint) {
-        super(endpoint);
-    }
-
-    @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();
-        Long finalMark = getLongHeader(in, HEADER_METER_MARK, mark);
-        if (finalMark == null) {
-            meter.mark();
-        } else {
-            meter.mark(finalMark);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/timer/TimerEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/timer/TimerEndpoint.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/timer/TimerEndpoint.java
deleted file mode 100644
index f1591a0..0000000
--- 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/timer/TimerEndpoint.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.camel.component.metrics.timer;
-
-import com.codahale.metrics.MetricRegistry;
-import org.apache.camel.Producer;
-import org.apache.camel.component.metrics.AbstractMetricsEndpoint;
-import org.apache.camel.spi.UriEndpoint;
-import org.apache.camel.spi.UriParam;
-
-@UriEndpoint(scheme = "metrics")
-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/4a84f061/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/timer/TimerProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/timer/TimerProducer.java
 
b/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/timer/TimerProducer.java
deleted file mode 100644
index 1254cbe..0000000
--- 
a/components/camel-metrics/src/main/java/org/apache/camel/component/metrics/timer/TimerProducer.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.camel.component.metrics.timer;
-
-import com.codahale.metrics.MetricRegistry;
-import com.codahale.metrics.Timer;
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.metrics.AbstractMetricsProducer;
-import org.apache.camel.component.metrics.timer.TimerEndpoint.TimerAction;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_TIMER_ACTION;
-import static 
org.apache.camel.component.metrics.timer.TimerEndpoint.ENDPOINT_URI;
-
-public class TimerProducer extends AbstractMetricsProducer<TimerEndpoint> {
-
-    private static final Logger LOG = 
LoggerFactory.getLogger(TimerProducer.class);
-
-    public TimerProducer(TimerEndpoint endpoint) {
-        super(endpoint);
-    }
-
-    @Override
-    protected void doProcess(Exchange exchange, TimerEndpoint endpoint, 
MetricRegistry registry, String metricsName) throws Exception {
-        Message in = exchange.getIn();
-        TimerAction action = endpoint.getAction();
-        TimerAction finalAction = in.getHeader(HEADER_TIMER_ACTION, action, 
TimerAction.class);
-        if (finalAction == TimerAction.start) {
-            handleStart(exchange, registry, metricsName);
-        } else if (finalAction == 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(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/4a84f061/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/AbstractMetricsEndpointTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/AbstractMetricsEndpointTest.java
 
b/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/AbstractMetricsEndpointTest.java
deleted file mode 100644
index e663153..0000000
--- 
a/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/AbstractMetricsEndpointTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.camel.component.metrics;
-
-import com.codahale.metrics.MetricRegistry;
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.Processor;
-import org.apache.camel.Producer;
-import org.apache.camel.RuntimeCamelException;
-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 static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class AbstractMetricsEndpointTest {
-
-    private static final String METRICS_NAME = "metrics.name";
-
-    @Mock
-    private MetricRegistry registry;
-
-    @Mock
-    private Processor processor;
-
-    @Mock
-    private Exchange exchange;
-
-    @Mock
-    private Message in;
-
-    private AbstractMetricsEndpoint endpoint;
-
-    private InOrder inOrder;
-
-    @Before
-    public void setUp() throws Exception {
-        endpoint = new AbstractMetricsEndpoint(registry, METRICS_NAME) {
-            @Override
-            public Producer createProducer() throws Exception {
-                return null;
-            }
-
-            @Override
-            protected String createEndpointUri() {
-                return "not real endpoint";
-            }
-        };
-        inOrder = Mockito.inOrder(registry, processor, exchange, in);
-        when(exchange.getIn()).thenReturn(in);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        inOrder.verifyNoMoreInteractions();
-    }
-
-    @Test
-    public void testAbstractMetricsEndpoint() throws Exception {
-        assertThat(endpoint.getMetricsName(), is(METRICS_NAME));
-        assertThat(endpoint.getRegistry(), is(registry));
-    }
-
-    @Test(expected = RuntimeCamelException.class)
-    public void testCreateConsumer() throws Exception {
-        endpoint.createConsumer(processor);
-    }
-
-    @Test
-    public void testIsSingleton() throws Exception {
-        assertThat(endpoint.isSingleton(), is(false));
-    }
-
-    @Test
-    public void testGetRegistry() throws Exception {
-        assertThat(endpoint.getRegistry(), is(registry));
-    }
-
-    @Test
-    public void testGetMetricsName() throws Exception {
-        assertThat(endpoint.getMetricsName(), is(METRICS_NAME));
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/AbstractMetricsProducerTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/AbstractMetricsProducerTest.java
 
b/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/AbstractMetricsProducerTest.java
index d441c24..706002c 100644
--- 
a/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/AbstractMetricsProducerTest.java
+++ 
b/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/AbstractMetricsProducerTest.java
@@ -27,6 +27,7 @@ import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
+
 import static 
org.apache.camel.component.metrics.AbstractMetricsProducer.HEADER_PATTERN;
 import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_HISTOGRAM_VALUE;
 import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_METRIC_NAME;
@@ -41,7 +42,7 @@ public class AbstractMetricsProducerTest {
     public static final String METRIC_NAME = "a metric";
 
     @Mock
-    private AbstractMetricsEndpoint endpoint;
+    private MetricsEndpoint endpoint;
 
     @Mock
     private Exchange exchange;
@@ -52,23 +53,23 @@ public class AbstractMetricsProducerTest {
     @Mock
     private MetricRegistry registry;
 
-    private AbstractMetricsProducer<AbstractMetricsEndpoint> okProducer;
+    private AbstractMetricsProducer okProducer;
 
-    private AbstractMetricsProducer<AbstractMetricsEndpoint> failProducer;
+    private AbstractMetricsProducer failProducer;
 
     private InOrder inOrder;
 
     @Before
     public void setUp() throws Exception {
-        okProducer = new 
AbstractMetricsProducer<AbstractMetricsEndpoint>(endpoint) {
+        okProducer = new AbstractMetricsProducer(endpoint) {
             @Override
-            protected void doProcess(Exchange exchange, 
AbstractMetricsEndpoint endpoint, MetricRegistry registry, String metricsName) 
throws Exception {
+            protected void doProcess(Exchange exchange, MetricsEndpoint 
endpoint, MetricRegistry registry, String metricsName) throws Exception {
             }
         };
-        failProducer = new 
AbstractMetricsProducer<AbstractMetricsEndpoint>(endpoint) {
+        failProducer = new AbstractMetricsProducer(endpoint) {
 
             @Override
-            protected void doProcess(Exchange exchange, 
AbstractMetricsEndpoint endpoint, MetricRegistry registry, String metricsName) 
throws Exception {
+            protected void doProcess(Exchange exchange, MetricsEndpoint 
endpoint, MetricRegistry registry, String metricsName) throws Exception {
                 throw new Exception("Muchos problemos");
             }
         };

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterEndpointTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterEndpointTest.java
 
b/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterEndpointTest.java
new file mode 100644
index 0000000..ba423b7
--- /dev/null
+++ 
b/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterEndpointTest.java
@@ -0,0 +1,99 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.component.metrics;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.camel.Producer;
+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 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;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CounterEndpointTest {
+
+    private static final String METRICS_NAME = "metrics.name";
+    private static final Long VALUE = System.currentTimeMillis();
+
+    @Mock
+    private MetricRegistry registry;
+
+    private MetricsEndpoint endpoint;
+
+    private InOrder inOrder;
+
+    @Before
+    public void setUp() throws Exception {
+        endpoint = new MetricsEndpoint(null, null, registry, 
MetricsType.COUNTER, METRICS_NAME);
+        inOrder = Mockito.inOrder(registry);
+    }
+
+    @After
+    public void tearDown() {
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testCounterEndpoint() throws Exception {
+        assertThat(endpoint.getRegistry(), is(registry));
+        assertThat(endpoint.getMetricsName(), is(METRICS_NAME));
+        assertThat(endpoint.getIncrement(), is(nullValue()));
+        assertThat(endpoint.getDecrement(), is(nullValue()));
+    }
+
+    @Test
+    public void testCreateProducer() throws Exception {
+        Producer producer = endpoint.createProducer();
+        assertThat(producer, is(notNullValue()));
+        assertThat(producer, is(instanceOf(CounterProducer.class)));
+    }
+
+    @Test
+    public void testGetIncrement() throws Exception {
+        assertThat(endpoint.getIncrement(), is(nullValue()));
+    }
+
+    @Test
+    public void testSetIncrement() throws Exception {
+        assertThat(endpoint.getIncrement(), is(nullValue()));
+        endpoint.setIncrement(VALUE);
+        assertThat(endpoint.getIncrement(), is(VALUE));
+    }
+
+    @Test
+    public void testGetDecrement() throws Exception {
+        assertThat(endpoint.getDecrement(), is(nullValue()));
+    }
+
+    @Test
+    public void testSetDecrement() throws Exception {
+        assertThat(endpoint.getDecrement(), is(nullValue()));
+        endpoint.setDecrement(VALUE);
+        assertThat(endpoint.getDecrement(), is(VALUE));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterProducerTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterProducerTest.java
 
b/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterProducerTest.java
new file mode 100644
index 0000000..d2edf44
--- /dev/null
+++ 
b/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterProducerTest.java
@@ -0,0 +1,196 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.component.metrics;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+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 static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_COUNTER_DECREMENT;
+import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_COUNTER_INCREMENT;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CounterProducerTest {
+
+    private static final String METRICS_NAME = "metrics.name";
+    private static final Long INCREMENT = 100000L;
+    private static final Long DECREMENT = 91929199L;
+
+    @Mock
+    private MetricsEndpoint endpoint;
+
+    @Mock
+    private Exchange exchange;
+
+    @Mock
+    private MetricRegistry registry;
+
+    @Mock
+    private Counter counter;
+
+    @Mock
+    private Message in;
+
+    private CounterProducer producer;
+
+    private InOrder inOrder;
+
+    @Before
+    public void setUp() throws Exception {
+        producer = new CounterProducer(endpoint);
+        inOrder = Mockito.inOrder(endpoint, exchange, registry, counter, in);
+        when(endpoint.getRegistry()).thenReturn(registry);
+        when(registry.counter(METRICS_NAME)).thenReturn(counter);
+        when(exchange.getIn()).thenReturn(in);
+    }
+
+    @Test
+    public void testCounterProducer() throws Exception {
+        assertThat(producer.getEndpoint().equals(endpoint), is(true));
+    }
+
+    @Test
+    public void testProcessWithIncrementOnly() throws Exception {
+        when(endpoint.getIncrement()).thenReturn(INCREMENT);
+        when(endpoint.getDecrement()).thenReturn(null);
+        when(in.getHeader(HEADER_COUNTER_INCREMENT, INCREMENT, 
Long.class)).thenReturn(INCREMENT);
+        when(in.getHeader(HEADER_COUNTER_DECREMENT, null, 
Long.class)).thenReturn(null);
+        producer.doProcess(exchange, endpoint, registry, METRICS_NAME);
+        inOrder.verify(exchange, times(1)).getIn();
+        inOrder.verify(registry, times(1)).counter(METRICS_NAME);
+        inOrder.verify(endpoint, times(1)).getIncrement();
+        inOrder.verify(endpoint, times(1)).getDecrement();
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_INCREMENT, 
INCREMENT, Long.class);
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_DECREMENT, null, 
Long.class);
+        inOrder.verify(counter, times(1)).inc(INCREMENT);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testProcessWithDecrementOnly() throws Exception {
+        when(endpoint.getIncrement()).thenReturn(null);
+        when(endpoint.getDecrement()).thenReturn(DECREMENT);
+        when(in.getHeader(HEADER_COUNTER_INCREMENT, null, 
Long.class)).thenReturn(null);
+        when(in.getHeader(HEADER_COUNTER_DECREMENT, DECREMENT, 
Long.class)).thenReturn(DECREMENT);
+        producer.doProcess(exchange, endpoint, registry, METRICS_NAME);
+        inOrder.verify(exchange, times(1)).getIn();
+        inOrder.verify(registry, times(1)).counter(METRICS_NAME);
+        inOrder.verify(endpoint, times(1)).getIncrement();
+        inOrder.verify(endpoint, times(1)).getDecrement();
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_INCREMENT, null, 
Long.class);
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_DECREMENT, 
DECREMENT, Long.class);
+        inOrder.verify(counter, times(1)).dec(DECREMENT);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testDoProcessWithIncrementAndDecrement() throws Exception {
+        when(endpoint.getIncrement()).thenReturn(INCREMENT);
+        when(endpoint.getDecrement()).thenReturn(DECREMENT);
+        when(in.getHeader(HEADER_COUNTER_INCREMENT, INCREMENT, 
Long.class)).thenReturn(INCREMENT);
+        when(in.getHeader(HEADER_COUNTER_DECREMENT, DECREMENT, 
Long.class)).thenReturn(DECREMENT);
+        producer.doProcess(exchange, endpoint, registry, METRICS_NAME);
+        inOrder.verify(exchange, times(1)).getIn();
+        inOrder.verify(registry, times(1)).counter(METRICS_NAME);
+        inOrder.verify(endpoint, times(1)).getIncrement();
+        inOrder.verify(endpoint, times(1)).getDecrement();
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_INCREMENT, 
INCREMENT, Long.class);
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_DECREMENT, 
DECREMENT, Long.class);
+        inOrder.verify(counter, times(1)).inc(INCREMENT);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testProcessWithOutIncrementAndDecrement() throws Exception {
+        when(endpoint.getIncrement()).thenReturn(null);
+        when(endpoint.getDecrement()).thenReturn(null);
+        when(in.getHeader(HEADER_COUNTER_INCREMENT, null, 
Long.class)).thenReturn(null);
+        when(in.getHeader(HEADER_COUNTER_DECREMENT, null, 
Long.class)).thenReturn(null);
+        producer.doProcess(exchange, endpoint, registry, METRICS_NAME);
+        inOrder.verify(exchange, times(1)).getIn();
+        inOrder.verify(registry, times(1)).counter(METRICS_NAME);
+        inOrder.verify(endpoint, times(1)).getIncrement();
+        inOrder.verify(endpoint, times(1)).getDecrement();
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_INCREMENT, null, 
Long.class);
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_DECREMENT, null, 
Long.class);
+        inOrder.verify(counter, times(1)).inc();
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testProcessWithHeaderValuesOnly() throws Exception {
+        when(endpoint.getIncrement()).thenReturn(null);
+        when(endpoint.getDecrement()).thenReturn(null);
+        when(in.getHeader(HEADER_COUNTER_INCREMENT, null, 
Long.class)).thenReturn(INCREMENT + 1);
+        when(in.getHeader(HEADER_COUNTER_DECREMENT, null, 
Long.class)).thenReturn(DECREMENT - 1);
+        producer.doProcess(exchange, endpoint, registry, METRICS_NAME);
+        inOrder.verify(exchange, times(1)).getIn();
+        inOrder.verify(registry, times(1)).counter(METRICS_NAME);
+        inOrder.verify(endpoint, times(1)).getIncrement();
+        inOrder.verify(endpoint, times(1)).getDecrement();
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_INCREMENT, null, 
Long.class);
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_DECREMENT, null, 
Long.class);
+        inOrder.verify(counter, times(1)).inc(INCREMENT + 1);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testProcessOverridingIncrement() throws Exception {
+        when(endpoint.getIncrement()).thenReturn(INCREMENT);
+        when(endpoint.getDecrement()).thenReturn(DECREMENT);
+        when(in.getHeader(HEADER_COUNTER_INCREMENT, INCREMENT, 
Long.class)).thenReturn(INCREMENT + 1);
+        when(in.getHeader(HEADER_COUNTER_DECREMENT, DECREMENT, 
Long.class)).thenReturn(DECREMENT);
+        producer.doProcess(exchange, endpoint, registry, METRICS_NAME);
+        inOrder.verify(exchange, times(1)).getIn();
+        inOrder.verify(registry, times(1)).counter(METRICS_NAME);
+        inOrder.verify(endpoint, times(1)).getIncrement();
+        inOrder.verify(endpoint, times(1)).getDecrement();
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_INCREMENT, 
INCREMENT, Long.class);
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_DECREMENT, 
DECREMENT, Long.class);
+        inOrder.verify(counter, times(1)).inc(INCREMENT + 1);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testProcessOverridingDecrement() throws Exception {
+        when(endpoint.getIncrement()).thenReturn(null);
+        when(endpoint.getDecrement()).thenReturn(DECREMENT);
+        when(in.getHeader(HEADER_COUNTER_INCREMENT, null, 
Long.class)).thenReturn(null);
+        when(in.getHeader(HEADER_COUNTER_DECREMENT, DECREMENT, 
Long.class)).thenReturn(DECREMENT - 1);
+        producer.doProcess(exchange, endpoint, registry, METRICS_NAME);
+        inOrder.verify(exchange, times(1)).getIn();
+        inOrder.verify(registry, times(1)).counter(METRICS_NAME);
+        inOrder.verify(endpoint, times(1)).getIncrement();
+        inOrder.verify(endpoint, times(1)).getDecrement();
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_INCREMENT, null, 
Long.class);
+        inOrder.verify(in, times(1)).getHeader(HEADER_COUNTER_DECREMENT, 
DECREMENT, Long.class);
+        inOrder.verify(counter, times(1)).dec(DECREMENT - 1);
+        inOrder.verifyNoMoreInteractions();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterRouteTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterRouteTest.java
 
b/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterRouteTest.java
new file mode 100644
index 0000000..ed78774
--- /dev/null
+++ 
b/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/CounterRouteTest.java
@@ -0,0 +1,200 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.component.metrics;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.camel.EndpointInject;
+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.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;
+import org.mockito.Mockito;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+
+import static 
org.apache.camel.component.metrics.MetricsComponent.METRIC_REGISTRY_NAME;
+import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_COUNTER_DECREMENT;
+import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_COUNTER_INCREMENT;
+import static 
org.apache.camel.component.metrics.MetricsConstants.HEADER_METRIC_NAME;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+@RunWith(CamelSpringJUnit4ClassRunner.class)
+@ContextConfiguration(
+        classes = { CounterRouteTest.TestConfig.class },
+        loader = CamelSpringDelegatingTestContextLoader.class)
+@MockEndpoints
+public class CounterRouteTest {
+
+    @EndpointInject(uri = "mock:out")
+    private MockEndpoint endpoint;
+
+    @Produce(uri = "direct:in-1")
+    private ProducerTemplate producer1;
+
+    @Produce(uri = "direct:in-2")
+    private ProducerTemplate producer2;
+
+    @Produce(uri = "direct:in-3")
+    private ProducerTemplate producer3;
+
+    @Produce(uri = "direct:in-4")
+    private ProducerTemplate producer4;
+
+    private MetricRegistry mockRegistry;
+
+    private Counter mockCounter;
+
+    private InOrder inOrder;
+
+    @Configuration
+    public static class TestConfig extends SingleRouteCamelConfiguration {
+
+        @Bean
+        @Override
+        public RouteBuilder route() {
+            return new RouteBuilder() {
+
+                @Override
+                public void configure() throws Exception {
+                    from("direct:in-1")
+                            .to("metrics:counter:A?increment=5")
+                            .to("mock:out");
+
+                    from("direct:in-2")
+                            .to("metrics:counter:A?decrement=9")
+                            .to("mock:out");
+
+                    from("direct:in-3")
+                            .setHeader(HEADER_COUNTER_INCREMENT, 
constant(417L))
+                            .to("metrics:counter:A")
+                            .to("mock:out");
+
+                    from("direct:in-4")
+                            .setHeader(HEADER_COUNTER_INCREMENT, 
simple("${body.length}"))
+                            .to("metrics:counter:A")
+                            .to("mock:out");
+                }
+            };
+        }
+
+        @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);
+        mockCounter = mock(Counter.class);
+        inOrder = Mockito.inOrder(mockRegistry, mockCounter);
+    }
+
+    @After
+    public void tearDown() {
+        endpoint.reset();
+        reset(mockRegistry, mockCounter);
+    }
+
+    @Test
+    public void testOverrideMetricsName() throws Exception {
+        when(mockRegistry.counter("B")).thenReturn(mockCounter);
+        endpoint.expectedMessageCount(1);
+        producer1.sendBodyAndHeader(new Object(), HEADER_METRIC_NAME, "B");
+        endpoint.assertIsSatisfied();
+        inOrder.verify(mockRegistry, times(1)).counter("B");
+        inOrder.verify(mockCounter, times(1)).inc(5L);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testOverrideIncrement() throws Exception {
+        when(mockRegistry.counter("A")).thenReturn(mockCounter);
+        endpoint.expectedMessageCount(1);
+        producer1.sendBodyAndHeader(new Object(), HEADER_COUNTER_INCREMENT, 
14L);
+        endpoint.assertIsSatisfied();
+        inOrder.verify(mockRegistry, times(1)).counter("A");
+        inOrder.verify(mockCounter, times(1)).inc(14L);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testOverrideIncrementAndDecrement() throws Exception {
+        when(mockRegistry.counter("A")).thenReturn(mockCounter);
+        endpoint.expectedMessageCount(1);
+        Map<String, Object> headers = new HashMap<String, Object>();
+        headers.put(HEADER_COUNTER_INCREMENT, 912L);
+        headers.put(HEADER_COUNTER_DECREMENT, 43219L);
+        producer1.sendBodyAndHeaders(new Object(), headers);
+        endpoint.assertIsSatisfied();
+        inOrder.verify(mockRegistry, times(1)).counter("A");
+        inOrder.verify(mockCounter, times(1)).inc(912L);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testOverrideDecrement() throws Exception {
+        when(mockRegistry.counter("A")).thenReturn(mockCounter);
+        endpoint.expectedMessageCount(1);
+        producer2.sendBodyAndHeader(new Object(), HEADER_COUNTER_DECREMENT, 
7L);
+        endpoint.assertIsSatisfied();
+        inOrder.verify(mockRegistry, times(1)).counter("A");
+        inOrder.verify(mockCounter, times(1)).dec(7L);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testOverrideUsingConstantValue() throws Exception {
+        when(mockRegistry.counter("A")).thenReturn(mockCounter);
+        endpoint.expectedMessageCount(1);
+        producer3.sendBody(new Object());
+        endpoint.assertIsSatisfied();
+        inOrder.verify(mockRegistry, times(1)).counter("A");
+        inOrder.verify(mockCounter, times(1)).inc(417L);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testOverrideUsingScriptEvaluation() throws Exception {
+        when(mockRegistry.counter("A")).thenReturn(mockCounter);
+        endpoint.expectedMessageCount(1);
+        String message = "Hello from Camel Metrics!";
+        producer4.sendBody(message);
+        endpoint.assertIsSatisfied();
+        inOrder.verify(mockRegistry, times(1)).counter("A");
+        inOrder.verify(mockCounter, times(1)).inc(message.length());
+        inOrder.verifyNoMoreInteractions();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4a84f061/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/HistogramEndpointTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/HistogramEndpointTest.java
 
b/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/HistogramEndpointTest.java
new file mode 100644
index 0000000..60b743d
--- /dev/null
+++ 
b/components/camel-metrics/src/test/java/org/apache/camel/component/metrics/HistogramEndpointTest.java
@@ -0,0 +1,85 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.component.metrics;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.camel.Producer;
+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 static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+
+@RunWith(MockitoJUnitRunner.class)
+public class HistogramEndpointTest {
+
+    private static final String METRICS_NAME = "metrics.name";
+    private static final Long VALUE = System.currentTimeMillis();
+
+    @Mock
+    private MetricRegistry registry;
+
+    private MetricsEndpoint endpoint;
+
+    private InOrder inOrder;
+
+    @Before
+    public void setUp() throws Exception {
+        endpoint = new MetricsEndpoint(null, null, registry, 
MetricsType.HISTOGRAM, METRICS_NAME);
+        inOrder = Mockito.inOrder(registry);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testHistogramEndpoint() 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(HistogramProducer.class));
+    }
+
+    @Test
+    public void testGetValue() throws Exception {
+        assertThat(endpoint.getValue(), is(nullValue()));
+    }
+
+    @Test
+    public void testSetValue() throws Exception {
+        assertThat(endpoint.getValue(), is(nullValue()));
+        endpoint.setValue(VALUE);
+        assertThat(endpoint.getValue(), is(VALUE));
+    }
+
+}

Reply via email to