The Metrics dependencies are all messed up. Killed libry("metrics") and put the 
3 classes into core api, moved the abstract testcases over to testsupport. And 
updated the documentation.


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

Branch: refs/heads/develop
Commit: 5b90154dd037bc17f3d6a8fd3012de3541a8b802
Parents: 46e0282
Author: niclas <[email protected]>
Authored: Sun Mar 5 23:38:58 2017 +0800
Committer: niclas <[email protected]>
Committed: Sun Mar 5 23:38:58 2017 +0800

----------------------------------------------------------------------
 core/api/src/docs/metrics.txt                   |  44 +++
 .../polygene/api/metrics/TimingCapture.java     |  37 ++
 .../api/metrics/TimingCaptureAllConcern.java    |  84 +++++
 .../api/metrics/TimingCaptureConcern.java       |  49 +++
 .../api/metrics/DocumentationSupport.java       |  56 +++
 core/testsupport/build.gradle                   |   1 +
 .../metrics/AbstractPolygeneMetricsTest.java    | 338 +++++++++++++++++++
 .../test/metrics/AbstractTimingCaptureTest.java | 149 ++++++++
 .../cassandra/EmptyCassandraTableMixin.java     |   2 +-
 extensions/metrics-codahale/build.gradle        |   1 -
 .../codahale/CodahaleMetricsAssembler.java      | 122 -------
 .../codahale/CodahaleMetricsDeclaration.java    |  36 --
 .../metrics/codahale/CodahaleMetricsMixin.java  |   9 +-
 .../assembly/CodahaleMetricsAssembler.java      | 124 +++++++
 .../assembly/CodahaleMetricsDeclaration.java    |  57 ++++
 .../metrics/codahale/CodahaleMetricsTest.java   |   2 +
 .../codahale/CodahaleTimingCaptureTest.java     |  61 ++++
 .../metrics/AbstractPolygeneMetricsTest.java    | 338 -------------------
 libraries/metrics/build.gradle                  |  36 --
 libraries/metrics/dev-status.xml                |  39 ---
 libraries/metrics/src/docs/metrics.txt          |  66 ----
 .../polygene/library/metrics/TimingCapture.java |  37 --
 .../metrics/TimingCaptureAllConcern.java        |  88 -----
 .../library/metrics/TimingCaptureConcern.java   |  50 ---
 .../polygene/library/metrics/package.html       |  24 --
 .../metrics/AbstractTimingCaptureTest.java      | 147 --------
 .../metrics/CodahaleTimingCaptureTest.java      |  59 ----
 .../library/metrics/DocumentationSupport.java   |  80 -----
 manual/src/docs/userguide/libraries.txt         |   4 -
 settings.gradle                                 |   1 -
 30 files changed, 1008 insertions(+), 1133 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/core/api/src/docs/metrics.txt
----------------------------------------------------------------------
diff --git a/core/api/src/docs/metrics.txt b/core/api/src/docs/metrics.txt
index 766ed3a..bac278d 100644
--- a/core/api/src/docs/metrics.txt
+++ b/core/api/src/docs/metrics.txt
@@ -105,3 +105,47 @@ regularly to report its status, which is then forwarded to 
the monitoring system
 
source=core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
 tag=healthcheck
 --------------
+
+
+= Timing Capture =
+A lot of metrics are around the time it takes to execute something and 
Polygene supports this at its core.
+
+== Usage ==
+There are currently the following possibilities available;
+
+    * @TimingCapture - capture timing on a single method
+    * TimingCaptureAll - capture timing on all methods of a composite
+
+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-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.
+
+== TimingCaptureAll ==
+There is a TimingCaptureAllConcern, which when added to a composite will 
install a _Timer_ for every method call
+in the composite.
+
+== @TimingCapture ==
+The +@TimingCapture+ annotation can be placed on any method of the composite, 
to indicate that
+a Timer is wanted on that method.
+
+Example;
+
+[snippet,java]
+----
+source=core/spi/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
+tag=capture
+----
+
+== Which method? ==
+It is valid to annotate either the composite interface methods or the mixin 
implementation methods.
+Any of the method declarations should work. From the testcases we have the 
following example;
+
+[snippet,java]
+----
+source=libraries/metrics/src/test/java/org/apache/polygene/library/metrics/AbstractTimingCaptureTest.java
+tag=complex-capture
+----
+

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCapture.java
----------------------------------------------------------------------
diff --git 
a/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCapture.java 
b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCapture.java
new file mode 100644
index 0000000..8c9007a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCapture.java
@@ -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.
+ *
+ *
+ */
+
+package org.apache.polygene.api.metrics;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.METHOD } )
+@Documented
+@InjectionScope
+public @interface TimingCapture
+{
+    String value() default "";
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureAllConcern.java
----------------------------------------------------------------------
diff --git 
a/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureAllConcern.java
 
b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureAllConcern.java
new file mode 100644
index 0000000..da11550
--- /dev/null
+++ 
b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureAllConcern.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.api.metrics;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Module;
+
+public class TimingCaptureAllConcern extends ConcernOf<InvocationHandler>
+    implements InvocationHandler
+{
+    private final MetricsTimer timer;
+
+    public TimingCaptureAllConcern( @Structure Module module,
+                                    @Service @Optional MetricsProvider metrics,
+                                    @Invocation Method method
+    )
+    {
+        if( metrics == null )
+        {
+            timer = null;
+        }
+        else
+        {
+            MetricsTimerFactory factory = metrics.createFactory( 
MetricsTimerFactory.class );
+            TimingCapture capture = method.getAnnotation( TimingCapture.class 
);
+            String timerName;
+            if( capture == null || "".equals( capture.value() ) )
+            {
+                timerName = MetricNames.nameFor( module, method );
+            }
+            else
+            {
+                timerName = capture.value();
+            }
+            timer = factory.createTimer( timerName );
+        }
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        MetricsTimer.Context timing = null;
+        if( timer != null )
+        {
+            timing = timer.start();
+        }
+        try
+        {
+            return next.invoke( proxy, method, args );
+        }
+        finally
+        {
+            if( timing != null )
+            {
+                timing.stop();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureConcern.java
----------------------------------------------------------------------
diff --git 
a/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureConcern.java
 
b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureConcern.java
new file mode 100644
index 0000000..b94daea
--- /dev/null
+++ 
b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureConcern.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.api.metrics;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Module;
+
+@AppliesTo( TimingCapture.class )
+public class TimingCaptureConcern extends TimingCaptureAllConcern
+{
+
+    public TimingCaptureConcern( @Structure Module module,
+                                 @Service @Optional MetricsProvider metrics,
+                                 @Invocation Method method
+    )
+    {
+        super( module, metrics, method );
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return super.invoke( proxy, method, args );
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
----------------------------------------------------------------------
diff --git 
a/core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
 
b/core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
index 005a5d2..aaaa052 100644
--- 
a/core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
+++ 
b/core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
@@ -20,9 +20,13 @@
 
 package org.apache.polygene.api.metrics;
 
+import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
 
 public class DocumentationSupport
 {
@@ -105,4 +109,56 @@ public class DocumentationSupport
             return errorMessage.equals( "OK" );
         }
     }
+
+
+    // START SNIPPET: capture
+    public interface Router
+    {
+        @TimingCapture
+        List<Coordinate> route( String source, String destination );
+    }
+
+    public class RouterAlgorithm1
+        implements Router
+    {
+        @Override
+        public List<Coordinate> route( String source, String destination )
+        {
+// END SNIPPET: capture
+            return null;
+// START SNIPPET: capture
+        }
+    }
+
+    public class RouterAlgorithm2
+        implements Router
+    {
+        @Override
+        public List<Coordinate> route( String source, String destination )
+        {
+// END SNIPPET: capture
+            return null;
+// START SNIPPET: capture
+        }
+
+        // END SNIPPET: capture
+        public class MyAssembler implements Assembler
+        {
+            // START SNIPPET: capture
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.addServices( Router.class ).identifiedBy( "router1" 
).withMixins( RouterAlgorithm1.class );
+                module.addServices( Router.class ).identifiedBy( "router2" 
).withMixins( RouterAlgorithm2.class );
+// END SNIPPET: capture
+// START SNIPPET: capture
+            }
+        }
+    }
+// END SNIPPET: capture
+
+    public class Coordinate
+    {
+    }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/core/testsupport/build.gradle
----------------------------------------------------------------------
diff --git a/core/testsupport/build.gradle b/core/testsupport/build.gradle
index dd05437..adfa425 100644
--- a/core/testsupport/build.gradle
+++ b/core/testsupport/build.gradle
@@ -25,6 +25,7 @@ jar { manifest { name = "Apache Polygene™ Core Test 
Support" } }
 dependencies {
   api polygene.core.bootstrap
   api libraries.junit
+  api libraries.hamcrest
 
   testRuntimeOnly polygene.core.runtime
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractPolygeneMetricsTest.java
----------------------------------------------------------------------
diff --git 
a/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractPolygeneMetricsTest.java
 
b/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractPolygeneMetricsTest.java
new file mode 100644
index 0000000..98efb6a
--- /dev/null
+++ 
b/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractPolygeneMetricsTest.java
@@ -0,0 +1,338 @@
+/*
+ *  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.polygene.test.metrics;
+
+import java.util.Collection;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.metrics.TimingCapture;
+import org.apache.polygene.api.metrics.TimingCaptureAllConcern;
+import org.apache.polygene.api.metrics.TimingCaptureConcern;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneBaseTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.util.JmxFixture;
+import org.junit.Test;
+
+import static java.util.stream.Collectors.toList;
+import static 
org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation.Propagation.MANDATORY;
+import static org.apache.polygene.api.usecase.UsecaseBuilder.newUsecase;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.hamcrest.collection.IsIterableContainingInOrder .contains;
+import static org.junit.Assert.assertThat;
+
+// TODO Test errors
+public abstract class AbstractPolygeneMetricsTest extends 
AbstractPolygeneBaseTest
+{
+    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.AbstractPolygeneMetricsTest.Queries.all";
+    protected static final String CREATE_NAME = 
"app.domain.services.AbstractPolygeneMetricsTest.Commands.create";
+    protected static final String RENAME_NAME = 
"app.domain.services.AbstractPolygeneMetricsTest.Commands.rename";
+    protected static final String DELETE_NAME = 
"app.domain.services.AbstractPolygeneMetricsTest.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/polygene-java/blob/5b90154d/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractTimingCaptureTest.java
----------------------------------------------------------------------
diff --git 
a/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractTimingCaptureTest.java
 
b/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractTimingCaptureTest.java
new file mode 100644
index 0000000..4b25622
--- /dev/null
+++ 
b/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractTimingCaptureTest.java
@@ -0,0 +1,149 @@
+/*
+ *  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.polygene.test.metrics;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.metrics.TimingCapture;
+import org.apache.polygene.api.metrics.TimingCaptureAllConcern;
+import org.apache.polygene.api.metrics.TimingCaptureConcern;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+public abstract class AbstractTimingCaptureTest extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.layer().application().setName( "SomeApplication" );
+        module.transients( Country1.class );
+        module.transients( Country2.class ).withConcerns( 
TimingCaptureAllConcern.class );
+        module.transients( Country3.class ).withConcerns( 
TimingCaptureConcern.class );
+        metricsAssembler().assemble( module );
+    }
+
+    protected abstract Assemblers.Visible<? extends Assembler> 
metricsAssembler();
+
+    protected abstract MetricValuesProvider metricValuesProvider();
+
+    @Test
+    public void givenNonInstrumentedCompositeExpectNoTimers()
+    {
+        Country underTest = transientBuilderFactory.newTransient( 
Country1.class );
+        updateName( underTest, 10 );
+        assertThat( metricValuesProvider().timerCount( "Layer 1.Module 
1.AbstractTimingCaptureTest.Country.name" ), is( 0L ) );
+        assertThat( metricValuesProvider().timerCount( "Layer 1.Module 
1.AbstractTimingCaptureTest.Country.updateName" ), is( 0L ) );
+    }
+
+    @Test
+    public void 
givenInstrumentedWithAllCompositeWhenCallingUpdateNameExpectTimers()
+    {
+        Country underTest = transientBuilderFactory.newTransient( 
Country2.class );
+        updateName( underTest, 10 );
+        assertThat( metricValuesProvider().timerCount( "Layer 1.Module 
1.AbstractTimingCaptureTest.Country.name" ), is( 10L ) );
+        assertThat( metricValuesProvider().timerCount( "Layer 1.Module 
1.AbstractTimingCaptureTest.Country.updateName" ), is( 10L ) );
+    }
+
+    @Test
+    public void 
givenOneMethodAnnotatedWhenCallingUpdateNameExpectTimerForThatMethodOnly()
+    {
+        Country underTest = transientBuilderFactory.newTransient( 
Country3.class );
+        updateName( underTest, 10 );
+        assertThat( metricValuesProvider().timerCount( "Layer 1.Module 
1.AbstractTimingCaptureTest.Country.name" ), is( 0L ) );
+        assertThat( metricValuesProvider().timerCount( "Country3.updateName" 
), is( 10L ) );
+    }
+
+    private void updateName( Country underTest, int times )
+    {
+        for( int i = 0; i < times; i++ )
+        {
+            underTest.updateName( "Name" + i );
+        }
+    }
+
+    // START SNIPPET: complex-capture
+    public interface Country extends TransientComposite
+    {
+        @Optional
+        Property<String> name();
+
+        void updateName( String newName );
+    }
+
+    @Mixins( Country1Mixin.class )
+    public interface Country1 extends Country
+    {
+    }
+
+    public static abstract class Country1Mixin
+        implements Country1
+    {
+        @Override
+        public void updateName( String newName )
+        {
+            name().set( newName );
+        }
+    }
+
+    @Mixins( Country2Mixin.class )
+    public interface Country2 extends Country
+    {
+    }
+
+    public static abstract class Country2Mixin
+        implements Country2
+    {
+        @Override
+        public void updateName( String newName )
+        {
+            name().set( newName );
+        }
+    }
+
+    @Mixins( Country3Mixin.class )
+    public interface Country3 extends Country
+    {
+        @TimingCapture( "Country3.updateName" )
+        @Override
+        void updateName( String newName );
+    }
+
+    public static abstract class Country3Mixin
+        implements Country3
+    {
+        @Override
+        public void updateName( String newName )
+        {
+            name().set( newName );
+        }
+    }
+    // END SNIPPET: complex-capture
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java
----------------------------------------------------------------------
diff --git 
a/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java
 
b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java
index 4f16dd8..d7f9b99 100644
--- 
a/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java
+++ 
b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java
@@ -33,6 +33,6 @@ public class EmptyCassandraTableMixin
     @Override
     public void removeAll()
     {
-        cluster.session().execute( "TRUNCATE TABLE " + cluster.tableName() + 
";");
+        cluster.cassandraClientSession().execute( "TRUNCATE TABLE " + 
cluster.tableName() + ";");
     }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/extensions/metrics-codahale/build.gradle
----------------------------------------------------------------------
diff --git a/extensions/metrics-codahale/build.gradle 
b/extensions/metrics-codahale/build.gradle
index 2805c35..4b7fd20 100644
--- a/extensions/metrics-codahale/build.gradle
+++ b/extensions/metrics-codahale/build.gradle
@@ -32,7 +32,6 @@ dependencies {
 
   testImplementation polygene.core.testsupport
   testImplementation polygene.library( 'jmx' )
-  testImplementation polygene.library( 'metrics' )
 
   testRuntimeOnly libraries.logback
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsAssembler.java
----------------------------------------------------------------------
diff --git 
a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsAssembler.java
 
b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsAssembler.java
deleted file mode 100644
index cbacce5..0000000
--- 
a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsAssembler.java
+++ /dev/null
@@ -1,122 +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.polygene.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.polygene.bootstrap.Assemblers;
-import org.apache.polygene.bootstrap.AssemblyException;
-import org.apache.polygene.bootstrap.ModuleAssembly;
-import org.apache.polygene.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/polygene-java/blob/5b90154d/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsDeclaration.java
----------------------------------------------------------------------
diff --git 
a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsDeclaration.java
 
b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsDeclaration.java
deleted file mode 100644
index e666214..0000000
--- 
a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsDeclaration.java
+++ /dev/null
@@ -1,36 +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.polygene.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/polygene-java/blob/5b90154d/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsMixin.java
----------------------------------------------------------------------
diff --git 
a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsMixin.java
 
b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsMixin.java
index bf6b274..5ccfdfd 100644
--- 
a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsMixin.java
+++ 
b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsMixin.java
@@ -42,6 +42,7 @@ import org.apache.polygene.api.metrics.MetricsTimer;
 import org.apache.polygene.api.metrics.MetricsTimerFactory;
 import org.apache.polygene.api.service.ServiceDescriptor;
 import org.apache.polygene.api.structure.Application;
+import 
org.apache.polygene.metrics.codahale.assembly.CodahaleMetricsDeclaration;
 import org.apache.polygene.spi.metrics.MetricsProviderAdapter;
 
 import java.io.Closeable;
@@ -74,15 +75,15 @@ public class CodahaleMetricsMixin extends 
MetricsProviderAdapter
         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 )
+        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)
+        for( Function<MetricRegistry, Reporter> reporterFactory : 
declaration.reportersFactories())
         {
             reporters.add( reporterFactory.apply( metricRegistry ) );
         }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/assembly/CodahaleMetricsAssembler.java
----------------------------------------------------------------------
diff --git 
a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/assembly/CodahaleMetricsAssembler.java
 
b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/assembly/CodahaleMetricsAssembler.java
new file mode 100644
index 0000000..7e9b843
--- /dev/null
+++ 
b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/assembly/CodahaleMetricsAssembler.java
@@ -0,0 +1,124 @@
+/*
+ *  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.polygene.metrics.codahale.assembly;
+
+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 java.io.File;
+import java.io.PrintStream;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.metrics.codahale.CodahaleMetricsProvider;
+
+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()
+                  .identifiedBy( identity() )
+                  .visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+    }
+}

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

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleMetricsTest.java
----------------------------------------------------------------------
diff --git 
a/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleMetricsTest.java
 
b/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleMetricsTest.java
index 91044cf..35fa19b 100644
--- 
a/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleMetricsTest.java
+++ 
b/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleMetricsTest.java
@@ -23,7 +23,9 @@ import 
org.apache.polygene.api.activation.PassivationException;
 import org.apache.polygene.api.structure.Module;
 import org.apache.polygene.bootstrap.Assembler;
 import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.metrics.codahale.assembly.CodahaleMetricsAssembler;
 import org.apache.polygene.test.metrics.AbstractPolygeneMetricsTest;
+
 import org.apache.polygene.test.metrics.MetricValuesProvider;
 import org.junit.Test;
 

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleTimingCaptureTest.java
----------------------------------------------------------------------
diff --git 
a/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleTimingCaptureTest.java
 
b/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleTimingCaptureTest.java
new file mode 100644
index 0000000..fa88caa
--- /dev/null
+++ 
b/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleTimingCaptureTest.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.metrics.codahale;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.metrics.codahale.assembly.CodahaleMetricsAssembler;
+import org.apache.polygene.test.metrics.AbstractTimingCaptureTest;
+import org.apache.polygene.test.metrics.MetricValuesProvider;
+
+import java.util.Collection;
+
+import static org.apache.polygene.api.common.Visibility.application;
+
+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/polygene-java/blob/5b90154d/extensions/metrics-codahale/src/test/java/org/apache/polygene/test/metrics/AbstractPolygeneMetricsTest.java
----------------------------------------------------------------------
diff --git 
a/extensions/metrics-codahale/src/test/java/org/apache/polygene/test/metrics/AbstractPolygeneMetricsTest.java
 
b/extensions/metrics-codahale/src/test/java/org/apache/polygene/test/metrics/AbstractPolygeneMetricsTest.java
deleted file mode 100644
index 9616f91..0000000
--- 
a/extensions/metrics-codahale/src/test/java/org/apache/polygene/test/metrics/AbstractPolygeneMetricsTest.java
+++ /dev/null
@@ -1,338 +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.polygene.test.metrics;
-
-import org.apache.polygene.api.activation.ActivationException;
-import org.apache.polygene.api.activation.PassivationException;
-import org.apache.polygene.api.association.ManyAssociation;
-import org.apache.polygene.api.common.Visibility;
-import org.apache.polygene.api.concern.Concerns;
-import org.apache.polygene.api.entity.EntityBuilder;
-import org.apache.polygene.api.identity.Identity;
-import org.apache.polygene.api.identity.StringIdentity;
-import org.apache.polygene.api.injection.scope.Structure;
-import org.apache.polygene.api.mixin.Mixins;
-import org.apache.polygene.api.property.Property;
-import org.apache.polygene.api.service.ServiceActivation;
-import org.apache.polygene.api.structure.Module;
-import org.apache.polygene.api.unitofwork.NoSuchEntityException;
-import org.apache.polygene.api.unitofwork.UnitOfWork;
-import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
-import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
-import org.apache.polygene.bootstrap.ApplicationAssembly;
-import org.apache.polygene.bootstrap.Assembler;
-import org.apache.polygene.bootstrap.Assemblers;
-import org.apache.polygene.bootstrap.AssemblyException;
-import org.apache.polygene.bootstrap.LayerAssembly;
-import org.apache.polygene.bootstrap.ModuleAssembly;
-import org.apache.polygene.library.metrics.TimingCapture;
-import org.apache.polygene.library.metrics.TimingCaptureAllConcern;
-import org.apache.polygene.library.metrics.TimingCaptureConcern;
-import org.apache.polygene.test.AbstractPolygeneBaseTest;
-import org.apache.polygene.test.EntityTestAssembler;
-import org.apache.polygene.test.util.JmxFixture;
-import org.junit.Test;
-
-import java.util.Collection;
-
-import static java.util.stream.Collectors.toList;
-import static 
org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation.Propagation.MANDATORY;
-import static org.apache.polygene.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 AbstractPolygeneMetricsTest extends 
AbstractPolygeneBaseTest
-{
-    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.AbstractPolygeneMetricsTest.Queries.all";
-    protected static final String CREATE_NAME = 
"app.domain.services.AbstractPolygeneMetricsTest.Commands.create";
-    protected static final String RENAME_NAME = 
"app.domain.services.AbstractPolygeneMetricsTest.Commands.rename";
-    protected static final String DELETE_NAME = 
"app.domain.services.AbstractPolygeneMetricsTest.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/polygene-java/blob/5b90154d/libraries/metrics/build.gradle
----------------------------------------------------------------------
diff --git a/libraries/metrics/build.gradle b/libraries/metrics/build.gradle
deleted file mode 100644
index 5c52590..0000000
--- a/libraries/metrics/build.gradle
+++ /dev/null
@@ -1,36 +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.
- *
- *
- */
-
-apply plugin: 'polygene-library'
-
-description = "Apache Polygene™ Metrics Library."
-
-jar { manifest { name = "Apache Polygene™ Library - Metrics" } }
-
-dependencies {
-  api polygene.core.bootstrap
-
-  runtimeOnly polygene.core.runtime
-
-  testImplementation polygene.core.testsupport
-  testImplementation polygene.extension( 'metrics-codahale' )
-
-  testRuntimeOnly libraries.logback
-}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/libraries/metrics/dev-status.xml
----------------------------------------------------------------------
diff --git a/libraries/metrics/dev-status.xml b/libraries/metrics/dev-status.xml
deleted file mode 100644
index aeeb8e4..0000000
--- a/libraries/metrics/dev-status.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?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://polygene.apache.org/schemas/2008/dev-status/1";
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-        
xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
-        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd";>
-  <status>
-    <!--none,early,beta,stable,mature-->
-    <codebase>beta</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/polygene-java/blob/5b90154d/libraries/metrics/src/docs/metrics.txt
----------------------------------------------------------------------
diff --git a/libraries/metrics/src/docs/metrics.txt 
b/libraries/metrics/src/docs/metrics.txt
deleted file mode 100644
index d4b0f57..0000000
--- a/libraries/metrics/src/docs/metrics.txt
+++ /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.
-//////////////////////
-
-[[library-metrics,Metrics Library]]
-= Metrics Library =
-
-The Metrics library is available to application code to get production metrics 
from their applications. It allows
-applications to easily mark critical section for metrics gathering, without 
handling the details with the Metrics
-Extension.
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-== Usage ==
-There are currently the following possibilities available;
-
-    * @TimingCapture - capture timing on a single method
-    * TimingCaptureAll - capture timing on all methods of a composite
-
-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-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.
-
-== TimingCaptureAll ==
-There is a TimingCaptureAllConcern, which when added to a composite will 
install a _Timer_ for every method call
-in the composite.
-
-== @TimingCapture ==
-The +@TimingCapture+ annotation can be placed on any method of the composite, 
to indicate that
-a Timer is wanted on that method.
-
-Example;
-
-[snippet,java]
-----
-source=libraries/metrics/src/test/java/org/apache/polygene/library/metrics/DocumentationSupport.java
-tag=capture
-----
-
-== Which method? ==
-It is valid to annotate either the composite interface methods or the mixin 
implementation methods.
-Any of the method declarations should work. From the testcases we have the 
following example;
-
-[snippet,java]
-----
-source=libraries/metrics/src/test/java/org/apache/polygene/library/metrics/AbstractTimingCaptureTest.java
-tag=complex-capture
-----
-

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCapture.java
----------------------------------------------------------------------
diff --git 
a/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCapture.java
 
b/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCapture.java
deleted file mode 100644
index 1938afc..0000000
--- 
a/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCapture.java
+++ /dev/null
@@ -1,37 +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.polygene.library.metrics;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.apache.polygene.api.injection.InjectionScope;
-
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.METHOD } )
-@Documented
-@InjectionScope
-public @interface TimingCapture
-{
-    String value() default "";
-}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCaptureAllConcern.java
----------------------------------------------------------------------
diff --git 
a/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCaptureAllConcern.java
 
b/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCaptureAllConcern.java
deleted file mode 100644
index fd0ff13..0000000
--- 
a/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCaptureAllConcern.java
+++ /dev/null
@@ -1,88 +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.polygene.library.metrics;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.apache.polygene.api.common.Optional;
-import org.apache.polygene.api.concern.ConcernOf;
-import org.apache.polygene.api.injection.scope.Invocation;
-import org.apache.polygene.api.injection.scope.Service;
-import org.apache.polygene.api.injection.scope.Structure;
-import org.apache.polygene.api.metrics.MetricNames;
-import org.apache.polygene.api.metrics.MetricsProvider;
-import org.apache.polygene.api.metrics.MetricsTimer;
-import org.apache.polygene.api.metrics.MetricsTimerFactory;
-import org.apache.polygene.api.structure.Module;
-
-public class TimingCaptureAllConcern extends ConcernOf<InvocationHandler>
-    implements InvocationHandler
-{
-    private final MetricsTimer timer;
-
-    public TimingCaptureAllConcern( @Structure Module module,
-                                    @Service @Optional MetricsProvider metrics,
-                                    @Invocation Method method
-    )
-    {
-        if( metrics == null )
-        {
-            timer = null;
-        }
-        else
-        {
-            MetricsTimerFactory factory = metrics.createFactory( 
MetricsTimerFactory.class );
-            TimingCapture capture = method.getAnnotation( TimingCapture.class 
);
-            String timerName;
-            if( capture == null || "".equals( capture.value() ) )
-            {
-                timerName = MetricNames.nameFor( module, method );
-            }
-            else
-            {
-                timerName = capture.value();
-            }
-            timer = factory.createTimer( timerName );
-        }
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        MetricsTimer.Context timing = null;
-        if( timer != null )
-        {
-            timing = timer.start();
-        }
-        try
-        {
-            return next.invoke( proxy, method, args );
-        }
-        finally
-        {
-            if( timing != null )
-            {
-                timing.stop();
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCaptureConcern.java
----------------------------------------------------------------------
diff --git 
a/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCaptureConcern.java
 
b/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCaptureConcern.java
deleted file mode 100644
index e5bf2d7..0000000
--- 
a/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/TimingCaptureConcern.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.polygene.library.metrics;
-
-import java.lang.reflect.Method;
-import org.apache.polygene.api.common.AppliesTo;
-import org.apache.polygene.api.common.Optional;
-import org.apache.polygene.api.injection.scope.Invocation;
-import org.apache.polygene.api.injection.scope.Service;
-import org.apache.polygene.api.injection.scope.Structure;
-import org.apache.polygene.api.metrics.MetricsProvider;
-import org.apache.polygene.api.structure.Module;
-
-@AppliesTo( TimingCapture.class )
-public class TimingCaptureConcern extends TimingCaptureAllConcern
-{
-
-    public TimingCaptureConcern( @Structure Module module,
-                                 @Service @Optional MetricsProvider metrics,
-                                 @Invocation Method method
-    )
-    {
-        super( module, metrics, method );
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        return super.invoke( proxy, method, args );
-    }
-}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5b90154d/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/package.html
----------------------------------------------------------------------
diff --git 
a/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/package.html
 
b/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/package.html
deleted file mode 100644
index 4db8768..0000000
--- 
a/libraries/metrics/src/main/java/org/apache/polygene/library/metrics/package.html
+++ /dev/null
@@ -1,24 +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.
-  ~
-  ~
-  -->
-<html>
-    <body>
-        <h2>Metrics Library.</h2>
-    </body>
-</html>
\ No newline at end of file

Reply via email to