polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From paulmer...@apache.org
Subject [1/3] zest-java git commit: ZEST-192 Introduce Codahale Metrics extension
Date Mon, 07 Nov 2016 14:04:45 GMT
Repository: zest-java
Updated Branches:
  refs/heads/develop 812f1446c -> ef0c40c0c


ZEST-192 Introduce Codahale Metrics extension


Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/8453ce39
Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/8453ce39
Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/8453ce39

Branch: refs/heads/develop
Commit: 8453ce39785d97052cdb246634012fbc094ffb31
Parents: 812f144
Author: Paul Merlin <paulmerlin@apache.org>
Authored: Mon Nov 7 14:53:47 2016 +0100
Committer: Paul Merlin <paulmerlin@apache.org>
Committed: Mon Nov 7 14:55:47 2016 +0100

----------------------------------------------------------------------
 extensions/metrics-codahale/build.gradle        |  37 ++
 extensions/metrics-codahale/dev-status.xml      |  39 +++
 .../src/docs/metrics-codahale.txt               |  55 +++
 .../zest/metrics/codahale/CodahaleCounter.java  |  60 ++++
 .../zest/metrics/codahale/CodahaleGauge.java    |  41 +++
 .../metrics/codahale/CodahaleHealthCheck.java   |  66 ++++
 .../metrics/codahale/CodahaleHistogram.java     |  41 +++
 .../zest/metrics/codahale/CodahaleMeter.java    |  47 +++
 .../codahale/CodahaleMetricsAssembler.java      | 122 +++++++
 .../codahale/CodahaleMetricsDeclaration.java    |  36 ++
 .../metrics/codahale/CodahaleMetricsMixin.java  | 269 +++++++++++++++
 .../codahale/CodahaleMetricsProvider.java       |  35 ++
 .../zest/metrics/codahale/CodahaleTimer.java    |  41 +++
 .../apache/zest/metrics/codahale/package.html   |  24 ++
 .../metrics/codahale/CodahaleMetricsTest.java   |  79 +++++
 .../test/metrics/AbstractZestMetricsTest.java   | 339 +++++++++++++++++++
 libraries.gradle                                |   5 +
 libraries/metrics/build.gradle                  |   1 +
 libraries/metrics/src/docs/metrics.txt          |   2 +-
 .../metrics/CodahaleTimingCaptureTest.java      |  59 ++++
 manual/src/docs/userguide/extensions.txt        |   4 +
 .../src/resources/js/progressive-enhancement.js |   2 +-
 settings.gradle                                 |   1 +
 23 files changed, 1403 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/build.gradle
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/build.gradle b/extensions/metrics-codahale/build.gradle
new file mode 100644
index 0000000..c43f760
--- /dev/null
+++ b/extensions/metrics-codahale/build.gradle
@@ -0,0 +1,37 @@
+/*
+ *  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.
+ *
+ *
+ */
+
+description = "Apache Zestâ„¢ Codahale Metrics Extension"
+
+jar { manifest { name = "Apache Zestâ„¢ Extension - Metrics - Codahale" }}
+
+dependencies {
+
+  compile project(":org.apache.zest.core:org.apache.zest.core.bootstrap")
+  compile libraries.codahale_metrics
+
+  testCompile project(":org.apache.zest.core:org.apache.zest.core.testsupport")
+  testCompile project(":org.apache.zest.libraries:org.apache.zest.library.jmx")
+  testCompile project(":org.apache.zest.libraries:org.apache.zest.library.metrics")
+
+  testRuntime project( ":org.apache.zest.core:org.apache.zest.core.runtime" )
+  testRuntime libraries.logback
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/dev-status.xml
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/dev-status.xml b/extensions/metrics-codahale/dev-status.xml
new file mode 100644
index 0000000..fb63508
--- /dev/null
+++ b/extensions/metrics-codahale/dev-status.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<module xmlns="http://zest.apache.org/schemas/2008/dev-status/1"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://zest.apache.org/schemas/2008/dev-status/1
+        http://zest.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+  <status>
+        <!--none,early,beta,stable,mature-->
+        <codebase>stable</codebase>
+
+        <!-- none, brief, good, complete -->
+        <documentation>brief</documentation>
+
+        <!-- none, some, good, complete -->
+        <unittests>some</unittests>
+    </status>
+    <licenses>
+        <license>ALv2</license>
+    </licenses>
+</module>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/docs/metrics-codahale.txt
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/docs/metrics-codahale.txt b/extensions/metrics-codahale/src/docs/metrics-codahale.txt
new file mode 100644
index 0000000..6e29384
--- /dev/null
+++ b/extensions/metrics-codahale/src/docs/metrics-codahale.txt
@@ -0,0 +1,55 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[extension-metrics-metrics, Codahale Metrics]]
+= Codahale Metrics =
+
+[devstatus]
+--------------
+source=extensions/metrics-codahale/dev-status.xml
+--------------
+
+Metrics extension backed by the http://metrics.dropwizard.io/[Codahale] metrics library
+maintained by the http://www.dropwizard.io/[Dropwizard] folks.
+
+include::../../build/docs/buildinfo/artifact.txt[]
+
+== Assembly ==
+
+Assembly is done using the provided Assembler:
+
+[snippet,java]
+----
+source=extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java
+tag=assembly
+----
+
+== Reporting to Ganglia or Graphite ==
+
+Dropwizard provide metrics reporter for Ganglia or Graphite, see the http://metrics.dropwizard.io/[official documentation]
+for details.
+
+To register reporters you need a handle to the underlying `MetricsRegistry`, the `CodahaleMetricsProvider` service
+provide accessor to it:
+
+[snippet,java]
+----
+source=extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java
+tag=registry
+----

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleCounter.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleCounter.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleCounter.java
new file mode 100644
index 0000000..63098ef
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleCounter.java
@@ -0,0 +1,60 @@
+/*
+ *  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.zest.metrics.codahale;
+
+import com.codahale.metrics.Counter;
+import org.apache.zest.api.metrics.MetricsCounter;
+
+public class CodahaleCounter
+    implements MetricsCounter
+{
+    private Counter counter;
+
+    public CodahaleCounter( Counter counter )
+    {
+
+        this.counter = counter;
+    }
+
+    @Override
+    public void increment()
+    {
+        counter.inc();
+    }
+
+    @Override
+    public void increment( int steps )
+    {
+        counter.inc( steps );
+    }
+
+    @Override
+    public void decrement()
+    {
+        counter.dec();
+    }
+
+    @Override
+    public void decrement( int steps )
+    {
+        counter.dec( steps );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleGauge.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleGauge.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleGauge.java
new file mode 100644
index 0000000..33abca3
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleGauge.java
@@ -0,0 +1,41 @@
+/*
+ *  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.zest.metrics.codahale;
+
+import com.codahale.metrics.Gauge;
+import org.apache.zest.api.metrics.MetricsGauge;
+
+public class CodahaleGauge<T>
+    implements MetricsGauge<T>
+{
+    private Gauge<T> gauge;
+
+    public CodahaleGauge( Gauge<T> gauge )
+    {
+        this.gauge = gauge;
+    }
+
+    @Override
+    public T value()
+    {
+        return gauge.getValue();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHealthCheck.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHealthCheck.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHealthCheck.java
new file mode 100644
index 0000000..ac73c78
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHealthCheck.java
@@ -0,0 +1,66 @@
+/*
+ *  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.zest.metrics.codahale;
+
+import com.codahale.metrics.health.HealthCheck;
+import org.apache.zest.api.metrics.MetricsHealthCheck;
+
+public class CodahaleHealthCheck
+    implements MetricsHealthCheck
+{
+    private final MetricsHealthCheck check;
+
+    public CodahaleHealthCheck( MetricsHealthCheck check )
+    {
+        this.check = check;
+    }
+
+    @Override
+    public Result check()
+        throws Exception
+    {
+        return check.check();
+    }
+
+    static Result wrap( HealthCheck.Result result )
+    {
+        return new Result( result.isHealthy(), result.getMessage(), result.getError() );
+    }
+
+    static HealthCheck.Result unwrap( Result result )
+    {
+        String message = result.getMessage();
+        if( result.isHealthy() )
+        {
+            if( message != null )
+            {
+                return HealthCheck.Result.healthy( message );
+            }
+            return HealthCheck.Result.healthy();
+        }
+        Throwable error = result.getException();
+        if( error != null )
+        {
+            return HealthCheck.Result.unhealthy( error );
+        }
+        return HealthCheck.Result.unhealthy( message );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHistogram.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHistogram.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHistogram.java
new file mode 100644
index 0000000..def8635
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHistogram.java
@@ -0,0 +1,41 @@
+/*
+ *  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.zest.metrics.codahale;
+
+import com.codahale.metrics.Histogram;
+import org.apache.zest.api.metrics.MetricsHistogram;
+
+public class CodahaleHistogram
+    implements MetricsHistogram
+{
+    private Histogram histogram;
+
+    public CodahaleHistogram( Histogram histogram )
+    {
+        this.histogram = histogram;
+    }
+
+    @Override
+    public void update( long newValue )
+    {
+        histogram.update( newValue );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMeter.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMeter.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMeter.java
new file mode 100644
index 0000000..63b5d39
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMeter.java
@@ -0,0 +1,47 @@
+/*
+ *  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.zest.metrics.codahale;
+
+import com.codahale.metrics.Meter;
+import org.apache.zest.api.metrics.MetricsMeter;
+
+public class CodahaleMeter
+    implements MetricsMeter
+{
+    private Meter meter;
+
+    public CodahaleMeter( Meter meter )
+    {
+        this.meter = meter;
+    }
+
+    @Override
+    public void mark()
+    {
+        meter.mark();
+    }
+
+    @Override
+    public void mark( int numberOfEvents )
+    {
+        meter.mark( numberOfEvents );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsAssembler.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsAssembler.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsAssembler.java
new file mode 100644
index 0000000..be10795
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsAssembler.java
@@ -0,0 +1,122 @@
+/*
+ *  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.zest.metrics.codahale;
+
+import com.codahale.metrics.ConsoleReporter;
+import com.codahale.metrics.CsvReporter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Reporter;
+import com.codahale.metrics.Slf4jReporter;
+import org.apache.zest.bootstrap.Assemblers;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.ModuleAssembly;
+import org.apache.zest.bootstrap.ServiceDeclaration;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+
+public class CodahaleMetricsAssembler
+    extends Assemblers.VisibilityIdentity<CodahaleMetricsAssembler>
+{
+    private final CodahaleMetricsDeclaration declaration = new CodahaleMetricsDeclaration();
+
+    public CodahaleMetricsAssembler withPrefix( String prefix )
+    {
+        declaration.prefix = prefix;
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withFullyQualifiedClassNames()
+    {
+        declaration.fqcn = true;
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withSimpleClassNames()
+    {
+        declaration.fqcn = false;
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withJmx()
+    {
+        declaration.jmx = true;
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withoutJmx()
+    {
+        declaration.jmx = false;
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withConsoleReporter( PrintStream out, long period, TimeUnit timeunit )
+    {
+        declaration.reportersFactories.add( metricRegistry -> {
+            ConsoleReporter reporter = ConsoleReporter.forRegistry( metricRegistry ).outputTo( out ).build();
+            reporter.start( period, timeunit );
+            return reporter;
+        });
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withSlf4jReporter( Slf4jReporter.LoggingLevel level, long period, TimeUnit timeunit )
+    {
+        declaration.reportersFactories.add( metricRegistry -> {
+            Slf4jReporter reporter = Slf4jReporter.forRegistry( metricRegistry ).withLoggingLevel( level ).build();
+            reporter.start( period, timeunit );
+            return reporter;
+        });
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withCsvReporter( File outDirectory, long period, TimeUnit timeunit )
+    {
+        declaration.reportersFactories.add( metricRegistry -> {
+            CsvReporter reporter = CsvReporter.forRegistry( metricRegistry ).build( outDirectory );
+            reporter.start( period, timeunit );
+            return reporter;
+        });
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withReporter( Function<MetricRegistry, Reporter> factory )
+    {
+        declaration.reportersFactories.add( factory );
+        return this;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( CodahaleMetricsProvider.class )
+                .setMetaInfo( declaration )
+                .instantiateOnStartup()
+                .visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsDeclaration.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsDeclaration.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsDeclaration.java
new file mode 100644
index 0000000..dde2d13
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsDeclaration.java
@@ -0,0 +1,36 @@
+/*
+ *  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.zest.metrics.codahale;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Reporter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+class CodahaleMetricsDeclaration
+{
+    String prefix;
+
+    boolean fqcn = false;
+
+    boolean jmx = true;
+
+    final List<Function<MetricRegistry, Reporter>> reportersFactories = new ArrayList<>();
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsMixin.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsMixin.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsMixin.java
new file mode 100644
index 0000000..553fc15
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsMixin.java
@@ -0,0 +1,269 @@
+/*
+ *  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.zest.metrics.codahale;
+
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.JmxReporter;
+import com.codahale.metrics.MetricFilter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Reporter;
+import com.codahale.metrics.health.HealthCheck;
+import com.codahale.metrics.health.HealthCheckRegistry;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.injection.scope.Structure;
+import org.apache.zest.api.injection.scope.Uses;
+import org.apache.zest.api.metrics.Metric;
+import org.apache.zest.api.metrics.MetricsCounter;
+import org.apache.zest.api.metrics.MetricsCounterFactory;
+import org.apache.zest.api.metrics.MetricsGauge;
+import org.apache.zest.api.metrics.MetricsGaugeFactory;
+import org.apache.zest.api.metrics.MetricsHealthCheck;
+import org.apache.zest.api.metrics.MetricsHealthCheckFactory;
+import org.apache.zest.api.metrics.MetricsHistogram;
+import org.apache.zest.api.metrics.MetricsHistogramFactory;
+import org.apache.zest.api.metrics.MetricsMeter;
+import org.apache.zest.api.metrics.MetricsMeterFactory;
+import org.apache.zest.api.metrics.MetricsTimer;
+import org.apache.zest.api.metrics.MetricsTimerFactory;
+import org.apache.zest.api.service.ServiceDescriptor;
+import org.apache.zest.api.structure.Application;
+import org.apache.zest.spi.metrics.MetricsProviderAdapter;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static com.codahale.metrics.MetricRegistry.name;
+
+public class CodahaleMetricsMixin extends MetricsProviderAdapter
+    implements CodahaleMetricsProvider
+{
+    @Structure
+    private Application app;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    private final List<Reporter> reporters = new ArrayList<>();
+
+    private MetricRegistry metricRegistry;
+    private HealthCheckRegistry healthCheckRegistry;
+    private String prefix;
+    private boolean fqcn;
+
+    @Override
+    public void activateService() {
+        metricRegistry = new MetricRegistry();
+        healthCheckRegistry = new HealthCheckRegistry();
+        CodahaleMetricsDeclaration declaration = descriptor.metaInfo( CodahaleMetricsDeclaration.class );
+        prefix = declaration.prefix != null ? declaration.prefix : app.name();
+        fqcn = declaration.fqcn;
+        if( declaration.jmx )
+        {
+            JmxReporter jmxReporter = JmxReporter.forRegistry( metricRegistry ).build();
+            jmxReporter.start();
+            reporters.add( jmxReporter );
+        }
+        for( Function<MetricRegistry, Reporter> reporterFactory : declaration.reportersFactories)
+        {
+            reporters.add( reporterFactory.apply( metricRegistry ) );
+        }
+    }
+
+    @Override
+    public void passivateService() throws PassivationException {
+        List<Exception> errors = new ArrayList<>();
+        for( Reporter reporter : reporters )
+        {
+            if( Closeable.class.isAssignableFrom( reporter.getClass() ) )
+            try
+            {
+                ( (Closeable) reporter ).close();
+            }
+            catch ( IOException ex )
+            {
+                errors.add( ex );
+            }
+        }
+        reporters.clear();
+        try
+        {
+            metricRegistry.removeMatching( MetricFilter.ALL );
+        }
+        catch( Exception ex )
+        {
+            errors.add( ex );
+        }
+        metricRegistry = null;
+        for( String healthCheckName : healthCheckRegistry.getNames() )
+        {
+            healthCheckRegistry.unregister( healthCheckName );
+        }
+        healthCheckRegistry = null;
+        prefix = null;
+        if( !errors.isEmpty() )
+        {
+            throw new PassivationException( errors );
+        }
+    }
+
+    @Override
+    public MetricRegistry metricRegistry()
+    {
+        return metricRegistry;
+    }
+
+    @Override
+    public HealthCheckRegistry healthCheckRegistry()
+    {
+        return healthCheckRegistry;
+    }
+
+    @Override
+    protected MetricsTimerFactory createMetricsTimerFactory()
+    {
+        return new MetricsTimerFactory()
+        {
+            @Override
+            public MetricsTimer createTimer( String name )
+            {
+                return new CodahaleTimer( metricRegistry.timer( name( prefix, name ) ) );
+            }
+
+            @Override
+            public Stream<Metric> registered()
+            {
+                return metricRegistry.getTimers().values().stream().map( CodahaleTimer::new );
+            }
+        };
+    }
+
+    @Override
+    protected MetricsMeterFactory createMetricsMeterFactory()
+    {
+        return new MetricsMeterFactory()
+        {
+            @Override
+            public MetricsMeter createMeter( String name )
+            {
+                return new CodahaleMeter( metricRegistry.meter( name( prefix, name ) ) );
+            }
+
+            @Override
+            public Stream<Metric> registered()
+            {
+                return metricRegistry.getMeters().values().stream().map( CodahaleMeter::new );
+            }
+        };
+    }
+
+    @Override
+    protected MetricsHistogramFactory createMetricsHistogramFactory()
+    {
+        return new MetricsHistogramFactory()
+        {
+            @Override
+            public MetricsHistogram createHistogram( String name )
+            {
+                return new CodahaleHistogram( metricRegistry.histogram( name( prefix, name ) ) );
+            }
+
+            @Override
+            public Stream<Metric> registered()
+            {
+                return metricRegistry.getHistograms().values().stream().map( CodahaleHistogram::new );
+            }
+        };
+    }
+
+    @Override
+    protected MetricsHealthCheckFactory createMetricsHealthCheckFactory()
+    {
+        return new MetricsHealthCheckFactory()
+        {
+            @Override
+            public MetricsHealthCheck registerHealthCheck( String name, MetricsHealthCheck check )
+            {
+                HealthCheck codahaleCheck = new HealthCheck() {
+                    @Override
+                    protected Result check() throws Exception {
+                        return CodahaleHealthCheck.unwrap( check.check() );
+                    }
+                };
+                healthCheckRegistry.register( name( prefix, name ), codahaleCheck );
+                return new CodahaleHealthCheck( check );
+            }
+
+            @Override
+            public Stream<Metric> registered()
+            {
+                return healthCheckRegistry.getNames().stream().map( name -> new MetricsHealthCheck() {
+                    @Override
+                    public Result check() throws Exception {
+                        return CodahaleHealthCheck.wrap( healthCheckRegistry.runHealthCheck( name ) );
+                    }
+                });
+            }
+        };
+    }
+
+    @Override
+    protected MetricsGaugeFactory createMetricsGaugeFactory()
+    {
+        return new MetricsGaugeFactory()
+        {
+            @Override
+            public <T> MetricsGauge<T> registerGauge( String name, final MetricsGauge<T> gauge )
+            {
+                Gauge<T> codahaleGauge = gauge::value;
+                metricRegistry.register( name( prefix, name ), codahaleGauge );
+                return new CodahaleGauge<>( codahaleGauge );
+            }
+
+            @Override
+            @SuppressWarnings( "unchecked" )
+            public Stream<Metric> registered()
+            {
+                return metricRegistry.getGauges().values().stream().map( CodahaleGauge::new );
+            }
+        };
+    }
+
+    @Override
+    protected MetricsCounterFactory createMetricsCounterFactory()
+    {
+        return new MetricsCounterFactory()
+        {
+            @Override
+            public MetricsCounter createCounter( String name )
+            {
+                return new CodahaleCounter( metricRegistry.counter( name( prefix, name) ) );
+            }
+
+            @Override
+            public Stream<Metric> registered()
+            {
+                return metricRegistry.getCounters().values().stream().map( CodahaleCounter::new );
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsProvider.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsProvider.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsProvider.java
new file mode 100644
index 0000000..e6a23d9
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsProvider.java
@@ -0,0 +1,35 @@
+/*
+ *  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.zest.metrics.codahale;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.health.HealthCheckRegistry;
+import org.apache.zest.api.metrics.MetricsProvider;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.api.service.ServiceActivation;
+
+@Mixins( CodahaleMetricsMixin.class )
+public interface CodahaleMetricsProvider
+        extends MetricsProvider, ServiceActivation
+{
+    MetricRegistry metricRegistry();
+
+    HealthCheckRegistry healthCheckRegistry();
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleTimer.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleTimer.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleTimer.java
new file mode 100644
index 0000000..f1b2522
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleTimer.java
@@ -0,0 +1,41 @@
+/*
+ *  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.zest.metrics.codahale;
+
+import com.codahale.metrics.Timer;
+import org.apache.zest.api.metrics.MetricsTimer;
+
+public class CodahaleTimer
+    implements MetricsTimer
+{
+    private Timer timer;
+
+    public CodahaleTimer( Timer timer )
+    {
+        this.timer = timer;
+    }
+
+    @Override
+    public Context start()
+    {
+        return timer.time()::stop;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/package.html
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/package.html b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/package.html
new file mode 100644
index 0000000..5a46cfb
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Codahale Metrics.</h2>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java b/extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java
new file mode 100644
index 0000000..ebac646
--- /dev/null
+++ b/extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java
@@ -0,0 +1,79 @@
+/*
+ *  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.zest.metrics.codahale;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.bootstrap.Assembler;
+import org.apache.zest.bootstrap.Assemblers;
+import org.apache.zest.test.metrics.AbstractZestMetricsTest;
+import org.apache.zest.test.metrics.MetricValuesProvider;
+import org.junit.Test;
+
+import java.util.Collection;
+
+public class CodahaleMetricsTest extends AbstractZestMetricsTest
+{
+    @Override
+    protected Assemblers.Visible<? extends Assembler> metricsAssembler()
+    {
+        // START SNIPPET: assembly
+        return new CodahaleMetricsAssembler();
+        // END SNIPPET: assembly
+    }
+
+    @Test
+    public void uowTimerCodahale() throws PassivationException, ActivationException
+    {
+        assertUowTimer( codahaleMetricValuesProvider() );
+    }
+
+    @Test
+    public void timingCaptureCodahale() throws PassivationException, ActivationException
+    {
+        assertTimingCapture( codahaleMetricValuesProvider() );
+    }
+
+    private MetricValuesProvider codahaleMetricValuesProvider()
+    {
+        Module module = metricsModule();
+        // START SNIPPET: registry
+        CodahaleMetricsProvider metricsProvider = module.findService( CodahaleMetricsProvider.class ).get();
+        // END SNIPPET: registry
+        return new MetricValuesProvider()
+        {
+            @Override
+            public Collection<String> registeredMetricNames()
+            {
+                // START SNIPPET: registry
+                MetricRegistry metricRegistry = metricsProvider.metricRegistry();
+                // END SNIPPET: registry
+                return metricRegistry.getNames();
+            }
+
+            @Override
+            public long timerCount( String timerName )
+            {
+                MetricRegistry metricRegistry = metricsProvider.metricRegistry();
+                return metricRegistry.timer( timerName ).getCount();
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/test/java/org/apache/zest/test/metrics/AbstractZestMetricsTest.java
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/src/test/java/org/apache/zest/test/metrics/AbstractZestMetricsTest.java b/extensions/metrics-codahale/src/test/java/org/apache/zest/test/metrics/AbstractZestMetricsTest.java
new file mode 100644
index 0000000..4fb767f
--- /dev/null
+++ b/extensions/metrics-codahale/src/test/java/org/apache/zest/test/metrics/AbstractZestMetricsTest.java
@@ -0,0 +1,339 @@
+/*
+ *  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.zest.test.metrics;
+
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.association.ManyAssociation;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.concern.Concerns;
+import org.apache.zest.api.entity.EntityBuilder;
+import org.apache.zest.api.identity.Identity;
+import org.apache.zest.api.identity.StringIdentity;
+import org.apache.zest.api.injection.scope.Structure;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.service.ServiceActivation;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.api.unitofwork.NoSuchEntityException;
+import org.apache.zest.api.unitofwork.UnitOfWork;
+import org.apache.zest.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.zest.bootstrap.ApplicationAssembly;
+import org.apache.zest.bootstrap.Assembler;
+import org.apache.zest.bootstrap.Assemblers;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.LayerAssembly;
+import org.apache.zest.bootstrap.ModuleAssembly;
+import org.apache.zest.library.metrics.TimingCapture;
+import org.apache.zest.library.metrics.TimingCaptureAllConcern;
+import org.apache.zest.library.metrics.TimingCaptureConcern;
+import org.apache.zest.test.AbstractZestBaseTest;
+import org.apache.zest.test.EntityTestAssembler;
+import org.apache.zest.test.metrics.MetricValuesProvider;
+import org.apache.zest.test.util.JmxFixture;
+import org.junit.Test;
+
+import java.util.Collection;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation.Propagation.MANDATORY;
+import static org.apache.zest.api.usecase.UsecaseBuilder.newUsecase;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+
+// TODO Test errors
+public abstract class AbstractZestMetricsTest extends AbstractZestBaseTest
+{
+    public interface Person
+    {
+        Property<String> name();
+    }
+
+    public interface PersonList
+    {
+        Identity LIST_ID = StringIdentity.fromString( "person-list" );
+
+        ManyAssociation<Person> all();
+    }
+
+    @Concerns( {TimingCaptureAllConcern.class, UnitOfWorkConcern.class} )
+    @Mixins( CommandsMixin.class )
+    public interface Commands extends ServiceActivation
+    {
+        @UnitOfWorkPropagation( MANDATORY )
+        Person create( Identity id, String name );
+
+        @UnitOfWorkPropagation( MANDATORY )
+        void rename( Identity id, String newName );
+
+        @UnitOfWorkPropagation( MANDATORY )
+        void delete( Identity id );
+    }
+
+    public static class CommandsMixin implements Commands
+    {
+        @Structure
+        private Module module;
+
+        @Override
+        public void activateService() throws Exception
+        {
+            try (UnitOfWork uow = module.unitOfWorkFactory().newUnitOfWork( newUsecase( "Init Person List" ) ) )
+            {
+                try
+                {
+                    uow.get( PersonList.class, PersonList.LIST_ID );
+                }
+                catch( NoSuchEntityException ex )
+                {
+                    uow.newEntity( PersonList.class, PersonList.LIST_ID );
+                    uow.complete();
+                }
+            }
+        }
+
+        @Override
+        public void passivateService()
+        {
+        }
+
+        @Override
+        public Person create( Identity id, String name )
+        {
+            UnitOfWork uow = module.unitOfWorkFactory().currentUnitOfWork();
+            PersonList list = uow.get( PersonList.class, PersonList.LIST_ID );
+            EntityBuilder<Person> builder = uow.newEntityBuilder( Person.class, id );
+            builder.instance().name().set( name );
+            Person person = builder.newInstance();
+            list.all().add( person );
+            return person;
+        }
+
+        @Override
+        public void rename( Identity id, String newName )
+        {
+            module.unitOfWorkFactory().currentUnitOfWork().get( Person.class, id ).name().set( newName );
+        }
+
+        @Override
+        public void delete( Identity id )
+        {
+            UnitOfWork uow = module.unitOfWorkFactory().currentUnitOfWork();
+            PersonList list = uow.get( PersonList.class, PersonList.LIST_ID );
+            Person person = uow.get( Person.class, id );
+            list.all().remove( person );
+            uow.remove( person );
+        }
+    }
+
+    @Concerns( {TimingCaptureConcern.class, UnitOfWorkConcern.class} )
+    @Mixins( QueriesMixin.class )
+    public interface Queries
+    {
+        @UnitOfWorkPropagation( MANDATORY )
+        Person byId( Identity id );
+
+        @TimingCapture
+        @UnitOfWorkPropagation( MANDATORY )
+        Iterable<Person> all();
+    }
+
+    public static class QueriesMixin implements Queries
+    {
+        @Structure
+        private Module module;
+
+        @Override
+        public Person byId( Identity id )
+        {
+            return module.unitOfWorkFactory().currentUnitOfWork().get( Person.class, id );
+        }
+
+        @Override
+        public Iterable<Person> all()
+        {
+            return module.unitOfWorkFactory().currentUnitOfWork()
+                    .get( PersonList.class, PersonList.LIST_ID )
+                    .all().toList();
+        }
+    }
+
+    @Override
+    protected final void defineApplication( ApplicationAssembly app ) throws AssemblyException
+    {
+        app.setName( "app" );
+
+        LayerAssembly domain = app.layer( "domain" );
+        ModuleAssembly model = domain.module( "model" );
+        model.entities( Person.class, PersonList.class )
+                .visibleIn( Visibility.layer );
+        ModuleAssembly services = domain.module( "services" );
+        services.services( Commands.class, Queries.class )
+                .instantiateOnStartup()
+                .visibleIn( Visibility.application );
+
+        LayerAssembly config = app.layer( "config" );
+        ModuleAssembly configModule = config.module( "config" );
+        new EntityTestAssembler()
+                .visibleIn( Visibility.module )
+                .assemble( configModule );
+
+        LayerAssembly infra = app.layer( "infra" );
+        ModuleAssembly storage = infra.module( "storage" );
+        entityStoreAssembler( configModule, Visibility.application )
+                .visibleIn( Visibility.application )
+                .assemble( storage );
+        metricsAssembler()
+                .visibleIn( Visibility.application )
+                .assemble( infra.module( "metrics" ) );
+
+        domain.uses( infra );
+        infra.uses( config );
+    }
+
+    protected Assemblers.Visible<? extends Assembler> entityStoreAssembler( ModuleAssembly configModule, Visibility configVisibility ) throws AssemblyException
+    {
+        return new EntityTestAssembler();
+    }
+
+    protected abstract Assemblers.Visible<? extends Assembler> metricsAssembler();
+
+    protected Module metricsModule()
+    {
+        return application.findModule( "infra", "metrics" );
+    }
+
+    protected static final String UOW_TIMER_NAME = "app.domain.services.UnitOfWork.timer";
+    protected static final String ALL_NAME = "app.domain.services.AbstractZestMetricsTest.Queries.all";
+    protected static final String CREATE_NAME = "app.domain.services.AbstractZestMetricsTest.Commands.create";
+    protected static final String RENAME_NAME = "app.domain.services.AbstractZestMetricsTest.Commands.rename";
+    protected static final String DELETE_NAME = "app.domain.services.AbstractZestMetricsTest.Commands.delete";
+
+    protected final void assertUowTimer( MetricValuesProvider metrics ) throws PassivationException, ActivationException
+    {
+        Long initialUowCount = metrics.timerCount( UOW_TIMER_NAME );
+        runScenario1();
+        assertThat( UOW_TIMER_NAME + " count incremented by 3", metrics.timerCount( UOW_TIMER_NAME ), is( initialUowCount + 3L ) );
+        application.passivate();
+        application.activate();
+        assertThat( UOW_TIMER_NAME + " count reset on passivation", metrics.timerCount( UOW_TIMER_NAME ), equalTo( initialUowCount ) );
+    }
+
+    protected final void assertTimingCapture( MetricValuesProvider metrics ) throws PassivationException, ActivationException
+    {
+        // Initial state
+        assertThat( ALL_NAME + " count is 0 at start", metrics.timerCount( ALL_NAME ), is( 0L ) );
+        assertThat( CREATE_NAME + " count is 0 at start", metrics.timerCount( CREATE_NAME ), is( 0L ) );
+        assertThat( RENAME_NAME + " count is 0 at start", metrics.timerCount( RENAME_NAME ), is( 0L ) );
+        assertThat( DELETE_NAME+ " count is 0 at start", metrics.timerCount( DELETE_NAME ), is( 0L ) );
+
+        // Run scenario
+        runScenario1();
+
+        // Queries.byId() timings are not captured
+        assertThat( "Queries.byId() has no timer", metrics.registeredMetricNames(), not( contains( containsString( "byId" ) ) ) );
+
+        // Captured timings
+        assertThat( ALL_NAME + " count is 4 after scenario", metrics.timerCount( ALL_NAME ), is( 4L ) );
+        assertThat( CREATE_NAME + " count is 1 after scenario", metrics.timerCount( CREATE_NAME ), is( 1L ) );
+        assertThat( RENAME_NAME + " count is 1 after scenario", metrics.timerCount( RENAME_NAME ), is( 1L ) );
+        assertThat( DELETE_NAME + " count is 1 after scenario", metrics.timerCount( DELETE_NAME ), is( 1L ) );
+
+        // Reset on passivation
+        application.passivate();
+        application.activate();
+        assertThat( ALL_NAME + " count is 0 after restart", metrics.timerCount( ALL_NAME ), is( 0L ) );
+        assertThat( CREATE_NAME + " count is 0 after restart", metrics.timerCount( CREATE_NAME ), is( 0L ) );
+        assertThat( RENAME_NAME + " count is 0 after restart", metrics.timerCount( RENAME_NAME ), is( 0L ) );
+        assertThat( DELETE_NAME + " count is 0 after restart", metrics.timerCount( DELETE_NAME ), is( 0L ) );
+    }
+
+    protected final void runScenario1()
+    {
+        Module services = application.findModule( "domain", "services" );
+        Commands commands = services.findService( Commands.class ).get();
+        Queries queries = services.findService( Queries.class ).get();
+
+        Identity identity = StringIdentity.fromString( "1" );
+
+        try (UnitOfWork uow = services.unitOfWorkFactory().newUnitOfWork( newUsecase( "Step 1" ) ) )
+        {
+            assertThat( queries.all().iterator().hasNext(), is( false ) );
+            assertThat( commands.create( identity, "Bob Geldof" ).name().get(), equalTo( "Bob Geldof" ) );
+            assertThat( queries.byId( identity ).name().get(), equalTo( "Bob Geldof" ) );
+            uow.complete();
+        }
+
+        try (UnitOfWork uow = services.unitOfWorkFactory().newUnitOfWork(newUsecase("Step 2")))
+        {
+            assertThat( queries.all().iterator().next().name().get(), equalTo( "Bob Geldof" ) );
+            assertThat( queries.byId( identity ).name().get(), equalTo( "Bob Geldof" ) );
+            commands.rename( identity, "Nina Hagen" );
+            assertThat( queries.all().iterator().next().name().get(), equalTo( "Nina Hagen" ) );
+            uow.complete();
+        }
+
+        try (UnitOfWork uow = services.unitOfWorkFactory().newUnitOfWork(newUsecase("Step 3")))
+        {
+            commands.delete( identity );
+            assertThat( queries.all().iterator().hasNext(), is( false ) );
+            uow.complete();
+        }
+    }
+
+    protected static class JmxMetricTestAdapter implements MetricValuesProvider
+    {
+        private final JmxFixture jmx = new JmxFixture( "metrics:name=" );
+
+        @Override
+        public long timerCount( String name )
+        {
+            if( jmx.objectExists( name ) ) {
+                return jmx.attributeValue( name, "Count", Long.class );
+            }
+            return 0L;
+        }
+
+        @Override
+        public Collection<String> registeredMetricNames()
+        {
+            return jmx.allObjectNames().stream()
+                    .filter( objName -> objName.startsWith( jmx.prefix() ) )
+                    .map( objName -> objName.substring( jmx.prefix().length() ) )
+                    .collect( toList() );
+        }
+    }
+
+    @Test
+    public void uowTimerJmx() throws PassivationException, ActivationException
+    {
+        assertUowTimer( new JmxMetricTestAdapter() );
+    }
+
+    @Test
+    public void timingCaptureJmx() throws PassivationException, ActivationException
+    {
+        assertTimingCapture( new JmxMetricTestAdapter() );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/libraries.gradle
----------------------------------------------------------------------
diff --git a/libraries.gradle b/libraries.gradle
index d99551c..59086b0 100644
--- a/libraries.gradle
+++ b/libraries.gradle
@@ -22,6 +22,7 @@
 def asmVersion = '5.1'
 def bonecpVersion = '0.8.0.RELEASE'
 def bouncyVersion = '1.55'
+def codahaleMetricsVersion = '3.1.2'
 def commonsDbcpVersion = '2.1.1'
 def commonsLangVersion = '3.5'
 def derbyVersion = '10.13.1.1'
@@ -215,6 +216,10 @@ rootProject.ext {
           pdfbox: "org.apache.pdfbox:pdfbox:$pdfboxVersion",
           prefuse: "de.sciss:prefuse-core:$prefuseVersion",
           spymemcached: "net.spy:spymemcached:$spymemcachedVersion",
+          codahale_metrics: [
+              "io.dropwizard.metrics:metrics-core:$codahaleMetricsVersion",
+              "io.dropwizard.metrics:metrics-healthchecks:$codahaleMetricsVersion"
+          ],
 
           // Testing
           junit: "junit:junit:$junitVersion",

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/libraries/metrics/build.gradle
----------------------------------------------------------------------
diff --git a/libraries/metrics/build.gradle b/libraries/metrics/build.gradle
index 0f27a3c..24823c3 100644
--- a/libraries/metrics/build.gradle
+++ b/libraries/metrics/build.gradle
@@ -27,6 +27,7 @@ dependencies {
 
   testCompile(project(":org.apache.zest.core:org.apache.zest.core.testsupport"))
   testCompile(project(":org.apache.zest.extensions:org.apache.zest.extension.metrics-yammer"))
+  testCompile(project(":org.apache.zest.extensions:org.apache.zest.extension.metrics-codahale"))
 
   testRuntime(project(":org.apache.zest.core:org.apache.zest.core.runtime"))
   testRuntime(libraries.logback)

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/libraries/metrics/src/docs/metrics.txt
----------------------------------------------------------------------
diff --git a/libraries/metrics/src/docs/metrics.txt b/libraries/metrics/src/docs/metrics.txt
index 179f3e0..991a3e3 100644
--- a/libraries/metrics/src/docs/metrics.txt
+++ b/libraries/metrics/src/docs/metrics.txt
@@ -33,7 +33,7 @@ There are currently the following possibilities available;
 
 Before looking at the details of these, we need to point out that there are some pre-conditions for Metrics to be
 working. First of all, you need to install a Metrics Extensions, most likely the
-<<extension-metrics-yammer, Yammer Metrics Extension>>. See your chosen extension for details on how to do that.
+<<extension-metrics-codahale, Codahale Metrics Extension>>. See your chosen extension for details on how to do that.
 
 Once the Metrics extension is installed, you will also need a suitable backend to gather all the data out of a
 production plant and likewise a good front-end to view this. See your chosen Metrics Extension for this as well.

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/libraries/metrics/src/test/java/org/apache/zest/library/metrics/CodahaleTimingCaptureTest.java
----------------------------------------------------------------------
diff --git a/libraries/metrics/src/test/java/org/apache/zest/library/metrics/CodahaleTimingCaptureTest.java b/libraries/metrics/src/test/java/org/apache/zest/library/metrics/CodahaleTimingCaptureTest.java
new file mode 100644
index 0000000..30a2762
--- /dev/null
+++ b/libraries/metrics/src/test/java/org/apache/zest/library/metrics/CodahaleTimingCaptureTest.java
@@ -0,0 +1,59 @@
+/*
+ *  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.zest.library.metrics;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.zest.bootstrap.Assembler;
+import org.apache.zest.bootstrap.Assemblers;
+import org.apache.zest.metrics.codahale.CodahaleMetricsAssembler;
+import org.apache.zest.metrics.codahale.CodahaleMetricsProvider;
+import org.apache.zest.test.metrics.MetricValuesProvider;
+
+import java.util.Collection;
+
+public class CodahaleTimingCaptureTest extends AbstractTimingCaptureTest
+{
+    @Override
+    protected Assemblers.Visible<? extends Assembler> metricsAssembler()
+    {
+        return new CodahaleMetricsAssembler();
+    }
+
+    @Override
+    protected MetricValuesProvider metricValuesProvider()
+    {
+        CodahaleMetricsProvider metricsProvider = serviceFinder.findService( CodahaleMetricsProvider.class ).get();
+        MetricRegistry metricRegistry = metricsProvider.metricRegistry();
+        return new MetricValuesProvider()
+        {
+            @Override
+            public Collection<String> registeredMetricNames()
+            {
+                return metricRegistry.getNames();
+            }
+
+            @Override
+            public long timerCount( String timerName )
+            {
+                return metricRegistry.timer( application.name() + '.' + timerName ).getCount();
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/manual/src/docs/userguide/extensions.txt
----------------------------------------------------------------------
diff --git a/manual/src/docs/userguide/extensions.txt b/manual/src/docs/userguide/extensions.txt
index 9d95997..ce7d495 100644
--- a/manual/src/docs/userguide/extensions.txt
+++ b/manual/src/docs/userguide/extensions.txt
@@ -129,6 +129,10 @@ include::../../../../extensions/indexing-sql/src/docs/index-sql.txt[]
 
 :leveloffset: 2
 
+include::../../../../extensions/metrics-codahale/src/docs/metrics-codahale.txt[]
+
+:leveloffset: 2
+
 include::../../../../extensions/metrics-yammer/src/docs/metrics-yammer.txt[]
 
 :leveloffset: 2

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/manual/src/resources/js/progressive-enhancement.js
----------------------------------------------------------------------
diff --git a/manual/src/resources/js/progressive-enhancement.js b/manual/src/resources/js/progressive-enhancement.js
index f496cdf..9af8dc9 100644
--- a/manual/src/resources/js/progressive-enhancement.js
+++ b/manual/src/resources/js/progressive-enhancement.js
@@ -161,7 +161,7 @@ $( document ).ready( function($){
             case "Ehcache Cache":
             case "Memory EntityStore":
             case "ElasticSearch Index/Query":
-            case "Yammer Metrics":
+            case "Codahale Metrics":
             case "Migration":
                 $dt.attr( "style", "margin-top: 24px" );
                 break;            

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/settings.gradle
----------------------------------------------------------------------
diff --git a/settings.gradle b/settings.gradle
index 8d724c9..73b3a37 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -73,6 +73,7 @@ include 'core:functional',
         'extensions:indexing-rdf',
         'extensions:indexing-solr',
         'extensions:indexing-sql',
+        'extensions:metrics-codahale',
         'extensions:metrics-yammer',
         'extensions:migration',
         'extensions:reindexer',


Mime
View raw message