Author: chetanm
Date: Mon Nov 23 11:44:22 2015
New Revision: 1715773

URL: http://svn.apache.org/viewvc?rev=1715773&view=rev
Log:
OAK-3654 - Integrate with Metrics for various stats collection

Added:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStats.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricCounterStats.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricMeterStats.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricTimerStats.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactory.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/CounterStats.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProvider.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/MeterStats.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/NoopStats.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/SimpleStats.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/StatisticsProvider.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/TimerStats.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStatsTest.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactoryTest.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProviderTest.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/SimpleStatsTest.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/StatisticManagerTest.java
   (with props)
Modified:
    jackrabbit/oak/trunk/oak-core/pom.xml
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/package-info.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/StatisticManager.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/package-info.java
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/osgi/RepositoryManager.java
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryManagerImpl.java
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionImpl.java
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionStats.java

Modified: jackrabbit/oak/trunk/oak-core/pom.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/pom.xml?rev=1715773&r1=1715772&r2=1715773&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-core/pom.xml Mon Nov 23 11:44:22 2015
@@ -214,6 +214,12 @@
       <version>2.4</version>
     </dependency>
     <dependency>
+      <groupId>io.dropwizard.metrics</groupId>
+      <artifactId>metrics-core</artifactId>
+      <version>3.1.0</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
       <groupId>org.apache.jackrabbit</groupId>
       <artifactId>jackrabbit-aws-ext</artifactId>
       <version>${jackrabbit.version}</version>

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStats.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStats.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStats.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStats.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,106 @@
+/*
+ * 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.jackrabbit.oak.plugins.metric;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.jackrabbit.oak.stats.CounterStats;
+import org.apache.jackrabbit.oak.stats.MeterStats;
+import org.apache.jackrabbit.oak.stats.SimpleStats;
+import org.apache.jackrabbit.oak.stats.TimerStats;
+
+/**
+ * Stats instances which delegates to both TimeSeries based counter
+ * and Metrics based meters so as to allow both systems to collect
+ * stats
+ */
+class CompositeStats implements CounterStats, MeterStats, TimerStats {
+    private final SimpleStats delegate;
+    private final MetricCounterStats counter;
+    private final MetricTimerStats timer;
+    private final MetricMeterStats meter;
+
+    public CompositeStats(SimpleStats delegate, MetricCounterStats counter) {
+        this(delegate, counter, null, null);
+    }
+
+    public CompositeStats(SimpleStats delegate, MetricTimerStats timer) {
+        this(delegate, null, timer, null);
+    }
+
+    public CompositeStats(SimpleStats delegate, MetricMeterStats meter) {
+        this(delegate, null, null, meter);
+    }
+
+    private CompositeStats(SimpleStats delegate, MetricCounterStats counter,
+                           MetricTimerStats timer, MetricMeterStats meter) {
+        this.delegate = delegate;
+        this.counter = counter;
+        this.timer = timer;
+        this.meter = meter;
+    }
+
+    @Override
+    public long getCount() {
+        return delegate.getCount();
+    }
+
+    @Override
+    public void inc() {
+        delegate.inc();
+        counter.inc();
+    }
+
+    @Override
+    public void dec() {
+        delegate.dec();
+        counter.dec();
+    }
+
+    @Override
+    public void mark() {
+        delegate.mark();
+        meter.mark();
+    }
+
+    @Override
+    public void mark(long n) {
+        delegate.mark(n);
+        meter.mark(n);
+    }
+
+    @Override
+    public void update(long duration, TimeUnit unit) {
+        delegate.update(duration, unit);
+        timer.update(duration, unit);
+    }
+
+    boolean isMeter() {
+        return meter != null && timer == null && counter == null;
+    }
+
+    boolean isTimer() {
+        return meter == null && timer != null && counter == null;
+    }
+
+    boolean isCounter() {
+        return meter == null && timer == null && counter != null;
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStats.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricCounterStats.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricCounterStats.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricCounterStats.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricCounterStats.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,46 @@
+/*
+ * 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.jackrabbit.oak.plugins.metric;
+
+import com.codahale.metrics.Counter;
+import org.apache.jackrabbit.oak.stats.CounterStats;
+
+class MetricCounterStats implements CounterStats {
+    private final Counter counter;
+
+    public MetricCounterStats(Counter counter) {
+        this.counter = counter;
+    }
+
+    @Override
+    public long getCount() {
+        return counter.getCount();
+    }
+
+    @Override
+    public void inc() {
+        counter.inc();
+    }
+
+    @Override
+    public void dec() {
+        counter.dec();
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricCounterStats.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricMeterStats.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricMeterStats.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricMeterStats.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricMeterStats.java
 Mon Nov 23 11:44:22 2015
@@ -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.jackrabbit.oak.plugins.metric;
+
+import com.codahale.metrics.Meter;
+import org.apache.jackrabbit.oak.stats.MeterStats;
+
+class MetricMeterStats implements MeterStats {
+    private final Meter meter;
+
+    public MetricMeterStats(Meter meter) {
+        this.meter = meter;
+    }
+
+    @Override
+    public void mark() {
+        meter.mark();
+    }
+
+    @Override
+    public void mark(long n) {
+        meter.mark(n);
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricMeterStats.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,197 @@
+/*
+ * 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.jackrabbit.oak.plugins.metric;
+
+import java.io.Closeable;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.concurrent.ScheduledExecutorService;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import com.codahale.metrics.JmxReporter;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.ObjectNameFactory;
+import com.codahale.metrics.RatioGauge;
+import com.codahale.metrics.Timer;
+import com.google.common.collect.Maps;
+import org.apache.jackrabbit.api.stats.RepositoryStatistics;
+import org.apache.jackrabbit.api.stats.RepositoryStatistics.Type;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
+import org.apache.jackrabbit.oak.stats.CounterStats;
+import org.apache.jackrabbit.oak.stats.MeterStats;
+import org.apache.jackrabbit.oak.stats.SimpleStats;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.apache.jackrabbit.oak.stats.TimerStats;
+import org.apache.jackrabbit.stats.RepositoryStatisticsImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MetricStatisticsProvider implements StatisticsProvider, Closeable 
{
+    private static final Logger log = 
LoggerFactory.getLogger(MetricStatisticsProvider.class);
+
+    private static final String JMX_TYPE_METRICS = "Metrics";
+
+    private final Map<String, CompositeStats> statsRegistry = 
Maps.newHashMap();
+    private final MetricRegistry registry;
+    private final JmxReporter reporter;
+    private final RepositoryStatisticsImpl repoStats;
+
+    public MetricStatisticsProvider(MBeanServer server, 
ScheduledExecutorService executor) {
+        registry = new MetricRegistry();
+        repoStats = new RepositoryStatisticsImpl(executor);
+        reporter = JmxReporter.forRegistry(registry)
+                .inDomain(WhiteboardUtils.JMX_OAK_DOMAIN)
+                .registerWith(server)
+                .createsObjectNamesWith(new OakNameFactory())
+                .build();
+        reporter.start();
+
+        registerAverages();
+    }
+
+    static String typeToName(Type type) {
+        return type.name();
+    }
+
+    public void close() {
+        if (reporter != null) {
+            reporter.close();
+        }
+    }
+
+    @Override
+    public RepositoryStatistics getStats() {
+        return repoStats;
+    }
+
+    @Override
+    public MeterStats getMeter(String name) {
+        return getStats(name, StatsType.METER);
+    }
+
+    @Override
+    public CounterStats getCounterStats(String name) {
+        return getStats(name, StatsType.COUNTER);
+    }
+
+    @Override
+    public TimerStats getTimer(String name) {
+        return getStats(name, StatsType.TIMER);
+    }
+
+    MetricRegistry getRegistry() {
+        return registry;
+    }
+
+    RepositoryStatisticsImpl getRepoStats() {
+        return repoStats;
+    }
+
+    private synchronized CompositeStats getStats(String type, StatsType 
statsType) {
+        String name = type;
+        Type enumType = Type.getType(type);
+        CompositeStats stats = statsRegistry.get(type);
+        if (stats == null) {
+            SimpleStats delegate;
+            if (enumType != null) {
+                delegate = new SimpleStats(repoStats.getCounter(enumType));
+                name = typeToName(enumType);
+            } else {
+                boolean resetValueEachSecond = statsType != StatsType.COUNTER;
+                delegate = new SimpleStats(repoStats.getCounter(type, 
resetValueEachSecond));
+            }
+            stats = createStat(name, statsType, delegate);
+            statsRegistry.put(type, stats);
+        }
+        return stats;
+    }
+
+    private CompositeStats createStat(String name, StatsType statsType, 
SimpleStats delegate) {
+        switch (statsType) {
+            case COUNTER:
+                MetricCounterStats counter = new 
MetricCounterStats(registry.counter(name));
+                return new CompositeStats(delegate, counter);
+            case TIMER:
+                MetricTimerStats timer = new 
MetricTimerStats(registry.timer(name));
+                return new CompositeStats(delegate, timer);
+            case METER:
+                MetricMeterStats meter = new 
MetricMeterStats(registry.meter(name));
+                return new CompositeStats(delegate, meter);
+        }
+        throw new IllegalStateException();
+    }
+
+    private void registerAverages() {
+        registry.register(typeToName(Type.SESSION_READ_AVERAGE),
+                new 
AvgGauge(registry.meter(typeToName(Type.SESSION_READ_COUNTER)),
+                        
registry.timer(typeToName(Type.SESSION_READ_DURATION))));
+
+        registry.register(typeToName(Type.SESSION_WRITE_AVERAGE),
+                new 
AvgGauge(registry.meter(typeToName(Type.SESSION_WRITE_COUNTER)),
+                        
registry.timer(typeToName(Type.SESSION_WRITE_DURATION))));
+
+        registry.register(typeToName(Type.QUERY_AVERAGE),
+                new AvgGauge(registry.meter(typeToName(Type.QUERY_COUNT)),
+                        registry.timer(typeToName(Type.QUERY_DURATION))));
+
+        registry.register(typeToName(Type.OBSERVATION_EVENT_AVERAGE),
+                new 
AvgGauge(registry.meter(typeToName(Type.OBSERVATION_EVENT_COUNTER)),
+                        
registry.timer(typeToName(Type.OBSERVATION_EVENT_DURATION))));
+    }
+
+    private enum StatsType {METER, COUNTER, TIMER}
+
+    private static class AvgGauge extends RatioGauge {
+        private final Meter meter;
+        private final Timer timer;
+
+        private AvgGauge(Meter meter, Timer timer) {
+            this.meter = meter;
+            this.timer = timer;
+        }
+
+        @Override
+        protected Ratio getRatio() {
+            //TODO Should we use getMeanRate
+            return Ratio.of(meter.getFifteenMinuteRate(),
+                    timer.getFifteenMinuteRate());
+        }
+    }
+
+    private static class OakNameFactory implements ObjectNameFactory {
+        @Override
+        public ObjectName createName(String type, String domain, String name) {
+            Hashtable<String, String> table = new Hashtable<String, String>();
+            table.put("type", JMX_TYPE_METRICS);
+            table.put("name", name);
+            try {
+                return new ObjectName(domain, table);
+            } catch (MalformedObjectNameException e) {
+                log.warn("Unable to register {} {}", type, name, e);
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricTimerStats.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricTimerStats.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricTimerStats.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricTimerStats.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,38 @@
+/*
+ * 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.jackrabbit.oak.plugins.metric;
+
+import java.util.concurrent.TimeUnit;
+
+import com.codahale.metrics.Timer;
+import org.apache.jackrabbit.oak.stats.TimerStats;
+
+class MetricTimerStats implements TimerStats {
+    private final Timer timer;
+
+    public MetricTimerStats(Timer timer) {
+        this.timer = timer;
+    }
+
+    @Override
+    public void update(long duration, TimeUnit unit) {
+        timer.update(duration, unit);
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricTimerStats.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactory.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactory.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,144 @@
+/*
+ * 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.jackrabbit.oak.plugins.metric;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import javax.management.MBeanServer;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.PropertyOption;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.jackrabbit.oak.commons.PropertiesUtil;
+import org.apache.jackrabbit.oak.stats.DefaultStatisticsProvider;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Factory to create StatisticsProvider depending on setup. It detects if the
+ * {@link Metrics http://metrics.dropwizard.io} library is present or not. If 
present
+ * then it configures a MetricsStatisticsProvider otherwise fallbacks to 
DefaultStatisticsProvider
+ */
+@Component(metatype = true,
+        label = "Apache Jackrabbit Oak StatisticsProviderFactory",
+        description = "Creates a statistics providers used by Oak. By default 
if checks if Metrics (" +
+                "See http://metrics.dropwizard.io) library is present then 
that is used. Otherwise it fallbacks " +
+                "to default")
+public class StatisticsProviderFactory {
+    @Property(value = TYPE_AUTO, options = {
+            @PropertyOption(name = TYPE_DEFAULT, value = TYPE_DEFAULT),
+            @PropertyOption(name = TYPE_METRIC, value = TYPE_METRIC),
+            @PropertyOption(name = TYPE_NONE, value = TYPE_NONE)})
+    static final String PROVIDER_TYPE = "providerType";
+    private static final String TYPE_DEFAULT = "DEFAULT";
+    private static final String TYPE_METRIC = "METRIC";
+    private static final String TYPE_NONE = "NONE";
+    private static final String TYPE_AUTO = "AUTO";
+    private static final String METRIC_PROVIDER_CLASS =
+            "com.codahale.metrics.MetricRegistry";
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    /**
+     * Keeping this as optional as for default case MBeanServer is not required
+     * Further Metrics would bound to default platform MBeanServer is no 
explicit
+     * server is provided.
+     */
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY)
+    private MBeanServer server;
+    private StatisticsProvider statisticsProvider;
+    private ServiceRegistration registration;
+    private ScheduledExecutorService executor;
+
+    @Activate
+    private void activate(BundleContext context, Map<String, Object> config) {
+        String providerType = 
PropertiesUtil.toString(config.get(PROVIDER_TYPE), TYPE_AUTO);
+        statisticsProvider = createProvider(providerType);
+
+        if (statisticsProvider != null) {
+            registration = 
context.registerService(StatisticsProvider.class.getName(),
+                    statisticsProvider, null);
+        }
+    }
+
+    @Deactivate
+    private void deactivate() throws IOException {
+        if (registration != null) {
+            registration.unregister();
+        }
+
+        if (statisticsProvider instanceof Closeable) {
+            ((Closeable) statisticsProvider).close();
+        }
+
+        //TODO Refactor ExecutorCloser in Oak as a utility class and
+        //use that here
+        if (executor != null) {
+            executor.shutdown();
+        }
+    }
+
+    private StatisticsProvider createProvider(String providerType) {
+        if (TYPE_NONE.equals(providerType)) {
+            log.info("No statistics provider created as {} option is 
selected", TYPE_NONE);
+            return null;
+        }
+
+        executor = Executors.newSingleThreadScheduledExecutor();
+
+        String effectiveProviderType = providerType;
+        if (TYPE_AUTO.equals(providerType) && isMetricSupportPresent()) {
+            effectiveProviderType = TYPE_METRIC;
+        }
+
+        if (TYPE_METRIC.equals(effectiveProviderType)) {
+            log.info("Using MetricsStatisticsProvider");
+            return createMetricsProvider(executor);
+        }
+
+        log.info("Using DefaultStatisticsProvider");
+        return new DefaultStatisticsProvider(executor);
+    }
+
+    private StatisticsProvider createMetricsProvider(ScheduledExecutorService 
executor) {
+        return new 
org.apache.jackrabbit.oak.plugins.metric.MetricStatisticsProvider(server, 
executor);
+    }
+
+    private boolean isMetricSupportPresent() {
+        try {
+            
StatisticsProviderFactory.class.getClassLoader().loadClass(METRIC_PROVIDER_CLASS);
+        } catch (Throwable e) {
+            log.debug("Cannot load optional Metrics library support", e);
+            return false;
+        }
+        return true;
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java?rev=1715773&r1=1715772&r2=1715773&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java
 Mon Nov 23 11:44:22 2015
@@ -39,6 +39,11 @@ import com.google.common.collect.Iterabl
 
 public class WhiteboardUtils {
 
+    /**
+     * JMX Domain name under which Oak related JMX MBeans are registered
+     */
+    public static final String JMX_OAK_DOMAIN = "org.apache.jackrabbit.oak";
+
     public static Registration scheduleWithFixedDelay(
             Whiteboard whiteboard, Runnable runnable, long delayInSeconds) {
         return scheduleWithFixedDelay(whiteboard, runnable, delayInSeconds, 
false);
@@ -73,7 +78,7 @@ public class WhiteboardUtils {
             table.put("name", quoteIfRequired(name));
             return whiteboard.register(iface, bean, ImmutableMap.of(
                     "jmx.objectname",
-                    new ObjectName("org.apache.jackrabbit.oak", table)));
+                    new ObjectName(JMX_OAK_DOMAIN, table)));
         } catch (MalformedObjectNameException e) {
             throw new IllegalArgumentException(e);
         }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/package-info.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/package-info.java?rev=1715773&r1=1715772&r2=1715773&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/package-info.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/package-info.java
 Mon Nov 23 11:44:22 2015
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.0.1")
+@Version("1.1.0")
 @Export(optional = "provide:=true")
 package org.apache.jackrabbit.oak.spi.whiteboard;
 

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/CounterStats.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/CounterStats.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/CounterStats.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/CounterStats.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,42 @@
+/*
+ * 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.jackrabbit.oak.stats;
+
+import aQute.bnd.annotation.ProviderType;
+
+@ProviderType
+public interface CounterStats {
+    /**
+     * Returns the counter's current value.
+     *
+     * @return the counter's current value
+     */
+    long getCount();
+
+    /**
+     * Increment the counter by one.
+     */
+    void inc();
+
+    /**
+     * Decrement the counter by one.
+     */
+    void dec();
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/CounterStats.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProvider.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProvider.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProvider.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProvider.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,71 @@
+/*
+ * 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.jackrabbit.oak.stats;
+
+import java.util.Map;
+import java.util.concurrent.ScheduledExecutorService;
+
+import com.google.common.collect.Maps;
+import org.apache.jackrabbit.api.stats.RepositoryStatistics;
+import org.apache.jackrabbit.api.stats.RepositoryStatistics.Type;
+import org.apache.jackrabbit.stats.RepositoryStatisticsImpl;
+
+public final class DefaultStatisticsProvider implements StatisticsProvider {
+    private final RepositoryStatisticsImpl repoStats;
+    private final Map<String, SimpleStats> statsMeters = Maps.newHashMap();
+
+    public DefaultStatisticsProvider(ScheduledExecutorService executor){
+        this.repoStats = new RepositoryStatisticsImpl(executor);
+    }
+
+    @Override
+    public RepositoryStatistics getStats() {
+        return repoStats;
+    }
+
+    @Override
+    public MeterStats getMeter(String name) {
+        return getStats(name, true);
+    }
+
+    @Override
+    public CounterStats getCounterStats(String name) {
+        return getStats(name, false);
+    }
+
+    @Override
+    public TimerStats getTimer(String name) {
+        return getStats(name, true);
+    }
+
+    private synchronized SimpleStats getStats(String type, boolean 
resetValueEachSecond){
+        Type enumType = Type.getType(type);
+        SimpleStats stats = statsMeters.get(type);
+        if (stats == null){
+            if (enumType != null) {
+                stats = new SimpleStats(repoStats.getCounter(enumType));
+            } else {
+                stats = new SimpleStats(repoStats.getCounter(type, 
resetValueEachSecond));
+            }
+            statsMeters.put(type, stats);
+        }
+        return stats;
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/MeterStats.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/MeterStats.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/MeterStats.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/MeterStats.java
 Mon Nov 23 11:44:22 2015
@@ -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.jackrabbit.oak.stats;
+
+import aQute.bnd.annotation.ProviderType;
+
+@ProviderType
+public interface MeterStats {
+    /**
+     * Mark the occurrence of an event.
+     */
+    void mark();
+
+    /**
+     * Mark the occurrence of a given number of events.
+     *
+     * @param n the number of events
+     */
+    void mark(long n);
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/MeterStats.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/NoopStats.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/NoopStats.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/NoopStats.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/NoopStats.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,62 @@
+/*
+ * 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.jackrabbit.oak.stats;
+
+import java.util.concurrent.TimeUnit;
+
+final class NoopStats implements TimerStats, MeterStats, CounterStats {
+
+    public static final NoopStats INSTANCE = new NoopStats();
+
+    private NoopStats(){
+
+    }
+
+    @Override
+    public long getCount() {
+        return 0;
+    }
+
+    @Override
+    public void inc() {
+
+    }
+
+    @Override
+    public void dec() {
+
+    }
+
+    @Override
+    public void mark() {
+
+    }
+
+    @Override
+    public void mark(long n) {
+
+    }
+
+    @Override
+    public void update(long duration, TimeUnit unit) {
+
+    }
+
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/NoopStats.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/SimpleStats.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/SimpleStats.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/SimpleStats.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/SimpleStats.java
 Mon Nov 23 11:44:22 2015
@@ -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.jackrabbit.oak.stats;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+public final class SimpleStats implements TimerStats, MeterStats, CounterStats 
{
+    private final AtomicLong statsHolder;
+
+    public SimpleStats(AtomicLong statsHolder) {
+        this.statsHolder = statsHolder;
+    }
+
+    @Override
+    public long getCount() {
+        return statsHolder.get();
+    }
+
+    @Override
+    public void inc() {
+        statsHolder.getAndIncrement();
+    }
+
+    @Override
+    public void dec() {
+        statsHolder.getAndDecrement();
+    }
+
+    @Override
+    public void mark() {
+        inc();
+    }
+
+    @Override
+    public void mark(long n) {
+        statsHolder.getAndAdd(n);
+    }
+
+    @Override
+    public void update(long duration, TimeUnit unit) {
+        statsHolder.getAndAdd(unit.toMillis(duration));
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/SimpleStats.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/StatisticManager.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/StatisticManager.java?rev=1715773&r1=1715772&r2=1715773&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/StatisticManager.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/StatisticManager.java
 Mon Nov 23 11:44:22 2015
@@ -30,8 +30,8 @@ import org.apache.jackrabbit.api.stats.R
 import org.apache.jackrabbit.oak.api.jmx.RepositoryStatsMBean;
 import org.apache.jackrabbit.oak.spi.whiteboard.CompositeRegistration;
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
 import org.apache.jackrabbit.stats.QueryStatImpl;
-import org.apache.jackrabbit.stats.RepositoryStatisticsImpl;
 import org.apache.jackrabbit.stats.TimeSeriesMax;
 import org.apache.jackrabbit.stats.jmx.QueryStatManager;
 
@@ -42,7 +42,7 @@ import org.apache.jackrabbit.stats.jmx.Q
  */
 public class StatisticManager {
     private final QueryStatImpl queryStat = new QueryStatImpl();
-    private final RepositoryStatisticsImpl repoStats;
+    private final StatisticsProvider repoStats;
     private final TimeSeriesMax maxQueueLength;
     private final CompositeRegistration registration;
 
@@ -53,12 +53,12 @@ public class StatisticManager {
      */
     public StatisticManager(Whiteboard whiteboard, ScheduledExecutorService 
executor) {
         queryStat.setEnabled(true);
-        repoStats = new RepositoryStatisticsImpl(executor);
+        repoStats = getStatsProvider(whiteboard, executor);
         maxQueueLength = new TimeSeriesMax(-1);
         registration = new CompositeRegistration(
             registerMBean(whiteboard, QueryStatManagerMBean.class, new 
QueryStatManager(queryStat),
                     "QueryStat", "Oak Query Statistics"),
-            registerMBean(whiteboard, RepositoryStatsMBean.class, new 
RepositoryStats(repoStats, maxQueueLength),
+            registerMBean(whiteboard, RepositoryStatsMBean.class, new 
RepositoryStats(repoStats.getStats(), maxQueueLength),
                     RepositoryStats.TYPE, "Oak Repository Statistics"),
             scheduleWithFixedDelay(whiteboard, new Runnable() {
                     @Override
@@ -86,9 +86,22 @@ public class StatisticManager {
      * @see 
org.apache.jackrabbit.stats.RepositoryStatisticsImpl#getCounter(org.apache.jackrabbit.api.stats.RepositoryStatistics.Type)
      */
     public AtomicLong getCounter(Type type) {
-        return repoStats.getCounter(type);
+        throw new UnsupportedOperationException();
     }
 
+    public MeterStats getMeter(Type type){
+        return repoStats.getMeter(type.name());
+    }
+
+    public CounterStats getStatsCounter(Type type){
+        return repoStats.getCounterStats(type.name());
+    }
+
+    public TimerStats getTimer(Type type){
+        return repoStats.getTimer(type.name());
+    }
+
+
     public TimeSeriesMax maxQueLengthRecorder() {
         return maxQueueLength;
     }
@@ -101,4 +114,13 @@ public class StatisticManager {
         registration.unregister();
     }
 
+    private StatisticsProvider getStatsProvider(Whiteboard wb,
+                                                ScheduledExecutorService 
executor) {
+        StatisticsProvider provider = WhiteboardUtils.getService(wb, 
StatisticsProvider.class);
+        if (provider == null){
+            provider = new DefaultStatisticsProvider(executor);
+        }
+        return provider;
+    }
+
 }

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/StatisticsProvider.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/StatisticsProvider.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/StatisticsProvider.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/StatisticsProvider.java
 Mon Nov 23 11:44:22 2015
@@ -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.jackrabbit.oak.stats;
+
+import javax.annotation.CheckForNull;
+
+import aQute.bnd.annotation.ProviderType;
+import org.apache.jackrabbit.api.stats.RepositoryStatistics;
+
+@ProviderType
+public interface StatisticsProvider {
+
+    StatisticsProvider NOOP = new StatisticsProvider() {
+        @Override
+        public RepositoryStatistics getStats() {
+            return null;
+        }
+
+        @Override
+        public MeterStats getMeter(String name) {
+            return NoopStats.INSTANCE;
+        }
+
+        @Override
+        public CounterStats getCounterStats(String name) {
+            return NoopStats.INSTANCE;
+        }
+
+        @Override
+        public TimerStats getTimer(String name) {
+            return NoopStats.INSTANCE;
+        }
+    };
+
+
+    @CheckForNull
+    RepositoryStatistics getStats();
+
+    MeterStats getMeter(String name);
+
+    CounterStats getCounterStats(String name);
+
+    TimerStats getTimer(String name);
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/StatisticsProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/TimerStats.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/TimerStats.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/TimerStats.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/TimerStats.java
 Mon Nov 23 11:44:22 2015
@@ -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.jackrabbit.oak.stats;
+
+import java.util.concurrent.TimeUnit;
+
+import aQute.bnd.annotation.ProviderType;
+
+@ProviderType
+public interface TimerStats {
+    /**
+     * Adds a recorded duration.
+     *
+     * @param duration the length of the duration
+     * @param unit     the scale unit of {@code duration}
+     */
+    void update(long duration, TimeUnit unit);
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/TimerStats.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/package-info.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/package-info.java?rev=1715773&r1=1715772&r2=1715773&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/package-info.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/stats/package-info.java
 Mon Nov 23 11:44:22 2015
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.1")
+@Version("1.2.0")
 @Export(optional = "provide:=true")
 package org.apache.jackrabbit.oak.stats;
 

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStatsTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStatsTest.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStatsTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStatsTest.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,82 @@
+/*
+ * 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.jackrabbit.oak.plugins.metric;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Timer;
+import org.apache.jackrabbit.oak.stats.CounterStats;
+import org.apache.jackrabbit.oak.stats.MeterStats;
+import org.apache.jackrabbit.oak.stats.SimpleStats;
+import org.apache.jackrabbit.oak.stats.TimerStats;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class CompositeStatsTest {
+    private MetricRegistry registry = new MetricRegistry();
+    private SimpleStats simpleStats = new SimpleStats(new AtomicLong());
+
+    @Test
+    public void counter() throws Exception {
+        MetricCounterStats counter = new 
MetricCounterStats(registry.counter("test"));
+        CounterStats counterStats = new CompositeStats(simpleStats, counter);
+
+        counterStats.inc();
+        assertEquals(1, simpleStats.getCount());
+        assertEquals(1, counter.getCount());
+        assertEquals(1, counterStats.getCount());
+
+        counterStats.inc();
+        counterStats.inc();
+        assertEquals(3, simpleStats.getCount());
+
+        counterStats.dec();
+        assertEquals(2, simpleStats.getCount());
+        assertEquals(2, counter.getCount());
+    }
+
+    @Test
+    public void meter() throws Exception {
+        Meter meter = registry.meter("test");
+        MeterStats meterStats = new CompositeStats(simpleStats, new 
MetricMeterStats(meter));
+
+        meterStats.mark();
+        assertEquals(1, simpleStats.getCount());
+        assertEquals(1, meter.getCount());
+
+        meterStats.mark(5);
+        assertEquals(6, simpleStats.getCount());
+        assertEquals(6, meter.getCount());
+    }
+
+    @Test
+    public void timer() throws Exception {
+        Timer time = registry.timer("test");
+        TimerStats timerStats = new CompositeStats(simpleStats, new 
MetricTimerStats(time));
+
+        timerStats.update(100, TimeUnit.SECONDS);
+        assertEquals(1, time.getCount());
+        assertEquals(TimeUnit.SECONDS.toMillis(100), simpleStats.getCount());
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/CompositeStatsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,121 @@
+/*
+ * 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.jackrabbit.oak.plugins.metric;
+
+import java.lang.management.ManagementFactory;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.Query;
+import javax.management.QueryExp;
+
+import com.codahale.metrics.JmxReporter;
+import org.apache.jackrabbit.api.stats.RepositoryStatistics;
+import org.apache.jackrabbit.oak.stats.CounterStats;
+import org.apache.jackrabbit.oak.stats.MeterStats;
+import org.apache.jackrabbit.oak.stats.TimerStats;
+import org.junit.After;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class MetricStatisticsProviderTest {
+    private MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+    private ScheduledExecutorService executorService = 
Executors.newSingleThreadScheduledExecutor();
+    private MetricStatisticsProvider statsProvider;
+
+    @Test
+    public void basicSetup() throws Exception {
+        statsProvider = new MetricStatisticsProvider(server, executorService);
+        assertEquals(4, statsProvider.getRegistry().getMeters().size());
+        assertEquals(4, statsProvider.getRegistry().getTimers().size());
+
+        assertNotNull(statsProvider.getStats());
+        assertEquals(statsProvider.getRegistry().getMetrics().size(), 
getMetricMbeans().size());
+        statsProvider.close();
+
+        assertEquals(0, getMetricMbeans().size());
+    }
+
+    @Test
+    public void meter() throws Exception {
+        statsProvider = new MetricStatisticsProvider(server, executorService);
+        MeterStats meterStats = statsProvider.getMeter("test");
+
+        assertNotNull(meterStats);
+        
assertNotNull(statsProvider.getRegistry().getMeters().containsKey("test"));
+        assertTrue(((CompositeStats) meterStats).isMeter());
+    }
+
+    @Test
+    public void counter() throws Exception {
+        statsProvider = new MetricStatisticsProvider(server, executorService);
+        CounterStats counterStats = statsProvider.getCounterStats("test");
+
+        assertNotNull(counterStats);
+        
assertNotNull(statsProvider.getRegistry().getCounters().containsKey("test"));
+        assertTrue(((CompositeStats) counterStats).isCounter());
+    }
+
+    @Test
+    public void timer() throws Exception {
+        statsProvider = new MetricStatisticsProvider(server, executorService);
+        TimerStats timerStats = statsProvider.getTimer("test");
+
+        assertNotNull(timerStats);
+        
assertNotNull(statsProvider.getRegistry().getTimers().containsKey("test"));
+        assertTrue(((CompositeStats) timerStats).isTimer());
+    }
+
+    @Test
+    public void timeSeriesIntegration() throws Exception {
+        statsProvider = new MetricStatisticsProvider(server, executorService);
+        MeterStats meterStats = 
statsProvider.getMeter(RepositoryStatistics.Type.QUERY_COUNT.name());
+
+        meterStats.mark(5);
+        assertEquals(5, 
statsProvider.getRepoStats().getCounter(RepositoryStatistics.Type.QUERY_COUNT).get());
+    }
+
+    @Test
+    public void jmxNaming() throws Exception {
+        statsProvider = new MetricStatisticsProvider(server, executorService);
+        TimerStats timerStats = statsProvider.getTimer("hello");
+        assertNotNull(server.getObjectInstance(new 
ObjectName("org.apache.jackrabbit.oak:type=Metrics,name=hello")));
+    }
+
+    @After
+    public void cleanup() {
+        statsProvider.close();
+        executorService.shutdownNow();
+    }
+
+    private Set<ObjectInstance> getMetricMbeans() throws 
MalformedObjectNameException {
+        QueryExp q = 
Query.isInstanceOf(Query.value(JmxReporter.MetricMBean.class.getName()));
+        return server.queryMBeans(new 
ObjectName("org.apache.jackrabbit.oak:*"), q);
+    }
+
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactoryTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactoryTest.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactoryTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactoryTest.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,70 @@
+/*
+ * 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.jackrabbit.oak.plugins.metric;
+
+import java.lang.management.ManagementFactory;
+import java.util.Collections;
+
+import javax.management.MBeanServer;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.jackrabbit.oak.stats.DefaultStatisticsProvider;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.apache.sling.testing.mock.osgi.MockOsgi;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.junit.After;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class StatisticsProviderFactoryTest {
+
+    @Rule
+    public final OsgiContext context = new OsgiContext();
+    private StatisticsProviderFactory service = new 
StatisticsProviderFactory();
+
+    @After
+    public void registerMBeanServer() {
+        context.registerService(MBeanServer.class, 
ManagementFactory.getPlatformMBeanServer());
+    }
+
+    @Test
+    public void autoMode() throws Exception {
+        MockOsgi.activate(service, context.bundleContext(), 
Collections.<String, Object>emptyMap());
+        assertTrue(context.getService(StatisticsProvider.class) instanceof 
MetricStatisticsProvider);
+
+        MockOsgi.deactivate(service);
+        assertNull(context.getService(StatisticsProvider.class));
+    }
+
+    @Test
+    public void noneMode() throws Exception {
+        MockOsgi.activate(service, context.bundleContext(), 
ImmutableMap.<String, Object>of("providerType", "NONE"));
+        assertNull(context.getService(StatisticsProvider.class));
+    }
+
+    @Test
+    public void defaultMode() throws Exception {
+        MockOsgi.activate(service, context.bundleContext(), 
ImmutableMap.<String, Object>of("providerType", "DEFAULT"));
+        assertTrue(context.getService(StatisticsProvider.class) instanceof 
DefaultStatisticsProvider);
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/StatisticsProviderFactoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProviderTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProviderTest.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProviderTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProviderTest.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.stats;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.jackrabbit.api.stats.RepositoryStatistics;
+import org.apache.jackrabbit.stats.RepositoryStatisticsImpl;
+import org.junit.After;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class DefaultStatisticsProviderTest {
+    private ScheduledExecutorService executorService = 
Executors.newSingleThreadScheduledExecutor();
+
+    @Test
+    public void basicSetup() throws Exception {
+        DefaultStatisticsProvider statsProvider = new 
DefaultStatisticsProvider(executorService);
+        assertNotNull(statsProvider.getStats());
+
+        CounterStats stats = 
statsProvider.getCounterStats(RepositoryStatistics.Type.SESSION_COUNT.name());
+        stats.inc();
+        assertEquals(1, 
statsImpl(statsProvider).getCounter(RepositoryStatistics.Type.SESSION_COUNT).get());
+    }
+
+    @Test
+    public void meter() throws Exception {
+        DefaultStatisticsProvider statsProvider = new 
DefaultStatisticsProvider(executorService);
+        MeterStats meterStats = statsProvider.getMeter("test");
+
+        assertNotNull(meterStats);
+        meterStats.mark();
+        assertEquals(1, statsImpl(statsProvider).getCounter("test", 
true).get());
+    }
+
+    @Test
+    public void counter() throws Exception {
+        DefaultStatisticsProvider statsProvider = new 
DefaultStatisticsProvider(executorService);
+        CounterStats counterStats = statsProvider.getCounterStats("test");
+
+        assertNotNull(counterStats);
+        counterStats.inc();
+        assertEquals(1, statsImpl(statsProvider).getCounter("test", 
false).get());
+    }
+
+    @Test
+    public void timer() throws Exception {
+        DefaultStatisticsProvider statsProvider = new 
DefaultStatisticsProvider(executorService);
+        TimerStats timerStats = statsProvider.getTimer("test");
+
+        assertNotNull(timerStats);
+        timerStats.update(100, TimeUnit.SECONDS);
+        assertEquals(TimeUnit.SECONDS.toMillis(100), 
statsImpl(statsProvider).getCounter("test", false).get());
+    }
+
+    @After
+    public void cleanup() {
+        executorService.shutdownNow();
+    }
+
+    private RepositoryStatisticsImpl statsImpl(DefaultStatisticsProvider 
statsProvider) {
+        return (RepositoryStatisticsImpl) statsProvider.getStats();
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/DefaultStatisticsProviderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/SimpleStatsTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/SimpleStatsTest.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/SimpleStatsTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/SimpleStatsTest.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,74 @@
+/*
+ * 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.jackrabbit.oak.stats;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class SimpleStatsTest {
+
+    @Test
+    public void usageTest() throws Exception {
+        AtomicLong counter = new AtomicLong();
+        SimpleStats stats = new SimpleStats(counter);
+
+        stats.mark();
+        assertEquals(1, counter.get());
+        assertEquals(1, stats.getCount());
+
+        stats.inc();
+        assertEquals(2, counter.get());
+
+        stats.dec();
+        assertEquals(1, counter.get());
+
+        stats.mark(2);
+        assertEquals(3, counter.get());
+
+        counter.set(0);
+        stats.update(100, TimeUnit.SECONDS);
+        assertEquals(TimeUnit.MILLISECONDS.convert(100, TimeUnit.SECONDS), 
counter.get());
+    }
+
+    @Test
+    public void noopTest() throws Exception {
+        NoopStats noop = NoopStats.INSTANCE;
+        assertEquals(0, noop.getCount());
+
+        noop.mark();
+        assertEquals(0, noop.getCount());
+
+        noop.mark(10);
+        assertEquals(0, noop.getCount());
+
+        noop.dec();
+        assertEquals(0, noop.getCount());
+
+        noop.inc();
+        assertEquals(0, noop.getCount());
+
+        noop.update(100, TimeUnit.SECONDS);
+        assertEquals(0, noop.getCount());
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/SimpleStatsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/StatisticManagerTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/StatisticManagerTest.java?rev=1715773&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/StatisticManagerTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/StatisticManagerTest.java
 Mon Nov 23 11:44:22 2015
@@ -0,0 +1,67 @@
+/*
+ * 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.jackrabbit.oak.stats;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.apache.jackrabbit.api.jmx.QueryStatManagerMBean;
+import org.apache.jackrabbit.api.stats.RepositoryStatistics;
+import org.apache.jackrabbit.oak.api.jmx.RepositoryStatsMBean;
+import org.apache.jackrabbit.oak.spi.whiteboard.DefaultWhiteboard;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
+import org.junit.After;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+
+public class StatisticManagerTest {
+    private ScheduledExecutorService executorService = 
Executors.newSingleThreadScheduledExecutor();
+
+    @Test
+    public void defaultSetup() throws Exception {
+        Whiteboard wb = new DefaultWhiteboard();
+        StatisticManager mgr = new StatisticManager(wb, executorService);
+
+        MeterStats meterStats = 
mgr.getMeter(RepositoryStatistics.Type.QUERY_COUNT);
+        meterStats.mark(5);
+
+        assertNotNull(WhiteboardUtils.getServices(wb, 
RepositoryStatsMBean.class));
+        assertNotNull(WhiteboardUtils.getServices(wb, 
QueryStatManagerMBean.class));
+    }
+
+    @Test
+    public void setupWithCustom() throws Exception {
+        Whiteboard wb = new DefaultWhiteboard();
+        wb.register(StatisticsProvider.class, StatisticsProvider.NOOP, null);
+        StatisticManager mgr = new StatisticManager(wb, executorService);
+
+        MeterStats meterStats = 
mgr.getMeter(RepositoryStatistics.Type.QUERY_COUNT);
+        meterStats.mark(5);
+
+        //TODO Not easy to do any asserts on call. Need to figure out a way
+    }
+
+    @After
+    public void cleanup() {
+        executorService.shutdownNow();
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/stats/StatisticManagerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java?rev=1715773&r1=1715772&r2=1715773&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
 Mon Nov 23 11:44:22 2015
@@ -29,7 +29,6 @@ import static org.apache.jackrabbit.oak.
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
@@ -64,6 +63,8 @@ import org.apache.jackrabbit.oak.spi.sec
 import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
 import org.apache.jackrabbit.oak.stats.Clock;
 import org.apache.jackrabbit.oak.stats.StatisticManager;
+import org.apache.jackrabbit.oak.stats.MeterStats;
+import org.apache.jackrabbit.oak.stats.TimerStats;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -92,10 +93,10 @@ public class SessionDelegate {
     private final Counters sessionCounters;
 
     // repository-wide counters for statistics about all sessions
-    private final AtomicLong readCounter;
-    private final AtomicLong readDuration;
-    private final AtomicLong writeCounter;
-    private final AtomicLong writeDuration;
+    private final MeterStats readCounter;
+    private final TimerStats readDuration;
+    private final MeterStats writeCounter;
+    private final TimerStats writeDuration;
 
     private boolean isAlive = true;
     private int sessionOpCount;
@@ -149,10 +150,10 @@ public class SessionDelegate {
         this.sessionStats = new SessionStats(contentSession.toString(),
                 contentSession.getAuthInfo(), clock, refreshStrategy, this, 
statisticManager);
         this.sessionCounters = sessionStats.getCounters();
-        readCounter = statisticManager.getCounter(SESSION_READ_COUNTER);
-        readDuration = statisticManager.getCounter(SESSION_READ_DURATION);
-        writeCounter = statisticManager.getCounter(SESSION_WRITE_COUNTER);
-        writeDuration = statisticManager.getCounter(SESSION_WRITE_DURATION);
+        readCounter = statisticManager.getMeter(SESSION_READ_COUNTER);
+        readDuration = statisticManager.getTimer(SESSION_READ_DURATION);
+        writeCounter = statisticManager.getMeter(SESSION_WRITE_COUNTER);
+        writeDuration = statisticManager.getTimer(SESSION_WRITE_DURATION);
     }
 
     @Nonnull
@@ -622,14 +623,14 @@ public class SessionDelegate {
         if (op.isUpdate()) {
             sessionCounters.writeTime = t0;
             sessionCounters.writeCount++;
-            writeCounter.incrementAndGet();
-            writeDuration.addAndGet(dt);
+            writeCounter.mark();
+            writeDuration.update(dt, TimeUnit.MILLISECONDS);
             updateCount++;
         } else {
             sessionCounters.readTime = t0;
             sessionCounters.readCount++;
-            readCounter.incrementAndGet();
-            readDuration.addAndGet(dt);
+            readCounter.mark();
+            readDuration.update(dt, TimeUnit.MILLISECONDS);
         }
         if (op.isSave()) {
             refreshAtNextAccess.refreshAtNextAccess(false);

Modified: 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java?rev=1715773&r1=1715772&r2=1715773&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java
 Mon Nov 23 11:44:22 2015
@@ -29,7 +29,6 @@ import static org.apache.jackrabbit.oak.
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 
 import javax.annotation.Nonnull;
@@ -60,6 +59,8 @@ import org.apache.jackrabbit.oak.spi.whi
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
 import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardExecutor;
 import org.apache.jackrabbit.oak.stats.StatisticManager;
+import org.apache.jackrabbit.oak.stats.MeterStats;
+import org.apache.jackrabbit.oak.stats.TimerStats;
 import org.apache.jackrabbit.oak.util.PerfLogger;
 import org.apache.jackrabbit.stats.TimeSeriesMax;
 import org.slf4j.Logger;
@@ -102,8 +103,8 @@ class ChangeProcessor implements Observe
     private final ListenerTracker tracker;
     private final EventListener eventListener;
     private final AtomicReference<FilterProvider> filterProvider;
-    private final AtomicLong eventCount;
-    private final AtomicLong eventDuration;
+    private final MeterStats eventCount;
+    private final TimerStats eventDuration;
     private final TimeSeriesMax maxQueueLength;
     private final int queueLength;
     private final CommitRateLimiter commitRateLimiter;
@@ -133,8 +134,8 @@ class ChangeProcessor implements Observe
         this.tracker = tracker;
         eventListener = tracker.getTrackedListener();
         filterProvider = new AtomicReference<FilterProvider>(filter);
-        this.eventCount = 
statisticManager.getCounter(OBSERVATION_EVENT_COUNTER);
-        this.eventDuration = 
statisticManager.getCounter(OBSERVATION_EVENT_DURATION);
+        this.eventCount = statisticManager.getMeter(OBSERVATION_EVENT_COUNTER);
+        this.eventDuration = 
statisticManager.getTimer(OBSERVATION_EVENT_DURATION);
         this.maxQueueLength = statisticManager.maxQueLengthRecorder();
         this.queueLength = queueLength;
         this.commitRateLimiter = commitRateLimiter;
@@ -340,10 +341,10 @@ class ChangeProcessor implements Observe
             this.events = events;
         }
 
-        public void updateCounters(AtomicLong eventCount, AtomicLong 
eventDuration) {
+        public void updateCounters(MeterStats eventCount, TimerStats 
eventDuration) {
             checkState(this.eventCount >= 0);
-            eventCount.addAndGet(this.eventCount);
-            eventDuration.addAndGet(System.nanoTime() - t0 - sysTime);
+            eventCount.mark(this.eventCount);
+            eventDuration.update(System.nanoTime() - t0 - sysTime, 
TimeUnit.NANOSECONDS);
             this.eventCount = -1;
         }
 

Modified: 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/osgi/RepositoryManager.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/osgi/RepositoryManager.java?rev=1715773&r1=1715772&r2=1715773&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/osgi/RepositoryManager.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/osgi/RepositoryManager.java
 Mon Nov 23 11:44:22 2015
@@ -30,6 +30,7 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceStrategy;
+import org.apache.felix.scr.annotations.References;
 import org.apache.jackrabbit.oak.Oak;
 import org.apache.jackrabbit.oak.commons.PropertiesUtil;
 import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
@@ -45,6 +46,7 @@ import org.apache.jackrabbit.oak.spi.whi
 import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardEditorProvider;
 import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardIndexEditorProvider;
 import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardIndexProvider;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
@@ -55,10 +57,15 @@ import org.osgi.framework.ServiceRegistr
  * to be configured in a custom way
  */
 @Component(policy = ConfigurationPolicy.REQUIRE)
-@Reference(referenceInterface = IndexEditorProvider.class,
-        target = "(type=property)",
-        strategy = ReferenceStrategy.LOOKUP
-)
+@References({
+        @Reference(referenceInterface = IndexEditorProvider.class,
+                target = "(type=property)",
+                strategy = ReferenceStrategy.LOOKUP
+        ),
+        @Reference(referenceInterface = StatisticsProvider.class,
+                strategy = ReferenceStrategy.LOOKUP
+        )
+})
 public class RepositoryManager {
     private static final int DEFAULT_OBSERVATION_QUEUE_LENGTH = 1000;
     private static final boolean DEFAULT_COMMIT_RATE_LIMIT = false;


Reply via email to