You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ud...@apache.org on 2018/09/10 22:42:54 UTC

[geode] 03/03: Further refactor Metrics to have cleaner abstraction of current metrics + micrometer

This is an automated email from the ASF dual-hosted git repository.

udo pushed a commit to branch feature/Micrometer
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 4fc468e19c917e68e188509c8bca548716017b6f
Author: Udo Kohlmeyer <uk...@pivotal.io>
AuthorDate: Mon Sep 10 15:42:14 2018 -0700

    Further refactor Metrics to have cleaner abstraction of current metrics + micrometer
---
 .../distributed/internal/InternalLocator.java      |   7 +-
 .../distributed/internal/LocatorStatsImpl.java     |   5 +-
 ...temStats.java => GFSStatisticsFactoryImpl.java} | 312 +++++++--------------
 .../statistics/InternalDistributedSystemStats.java | 306 ++------------------
 geode-core/src/main/kotlin/Locator.kt              |   1 +
 ...geode.stats.common.statistics.StatisticsFactory |   1 +
 .../micrometer/impl/MicrometerMeterGroup.kt        |   5 +
 .../micrometer/MicrometerStatisticsFactoryImpl.kt  |   3 +
 ...geode.stats.common.statistics.StatisticsFactory |   1 +
 geode-old-versions/build.gradle                    |  16 +-
 .../internal/statistics/StatisticsManager.java     |   0
 .../stats/common/statistics/StatisticsFactory.java |   4 +
 .../common/statistics/factory/StatsFactory.java    | 149 +++++-----
 13 files changed, 214 insertions(+), 596 deletions(-)

diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
index 982129f..cc84b67 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
@@ -311,10 +311,6 @@ public class InternalLocator extends Locator implements ConnectListener {
       newLocator = createLocator(port, logFile, logger, securityLogger, bindAddress,
           hostnameForClients, dsProperties, startDistributedSystem);
 
-      // newLocator.stats =
-      // StatsFactory.createLocatorStatsImpl(null,
-      // (newLocator.getHostnameForClients() + newLocator.getPort()));
-
       try {
         newLocator.startPeerLocation();
 
@@ -348,6 +344,8 @@ public class InternalLocator extends Locator implements ConnectListener {
 
       newLocator.endStartLocator(null);
       startedLocator = true;
+
+
       return newLocator;
 
     } finally {
@@ -1314,7 +1312,6 @@ public class InternalLocator extends Locator implements ConnectListener {
     @Override
     public void startJob() {
       stats.incRequestInProgress(1);
-
     }
 
     @Override
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/LocatorStatsImpl.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/LocatorStatsImpl.java
index de47b50..8039d3f 100755
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/LocatorStatsImpl.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/LocatorStatsImpl.java
@@ -20,6 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.geode.stats.common.distributed.internal.LocatorStats;
+import org.apache.geode.stats.common.statistics.GFSStatsImplementer;
 import org.apache.geode.stats.common.statistics.StatisticDescriptor;
 import org.apache.geode.stats.common.statistics.Statistics;
 import org.apache.geode.stats.common.statistics.StatisticsFactory;
@@ -30,7 +31,7 @@ import org.apache.geode.stats.common.statistics.StatisticsType;
  *
  * @since GemFire 5.7
  */
-public class LocatorStatsImpl implements LocatorStats {
+public class LocatorStatsImpl implements LocatorStats, GFSStatsImplementer {
   private static StatisticsType type;
 
   private static final String KNOWN_LOCATORS = LOCATORS; // gauge
@@ -100,7 +101,7 @@ public class LocatorStatsImpl implements LocatorStats {
   /**
    * Creates a new <code>LocatorStats</code> and registers itself with the given statistics factory.
    */
-  public LocatorStatsImpl(StatisticsFactory factory) {
+  public LocatorStatsImpl(StatisticsFactory factory, String identifier) {
     initializeStats(factory);
   }
 
diff --git a/geode-core/src/main/java/org/apache/geode/internal/statistics/InternalDistributedSystemStats.java b/geode-core/src/main/java/org/apache/geode/internal/statistics/GFSStatisticsFactoryImpl.java
similarity index 60%
copy from geode-core/src/main/java/org/apache/geode/internal/statistics/InternalDistributedSystemStats.java
copy to geode-core/src/main/java/org/apache/geode/internal/statistics/GFSStatisticsFactoryImpl.java
index a3b578d..fcfaaf4 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/statistics/InternalDistributedSystemStats.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/statistics/GFSStatisticsFactoryImpl.java
@@ -1,110 +1,28 @@
-/*
- * 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.geode.internal.statistics;
 
 import java.io.IOException;
 import java.io.Reader;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.LongAdder;
 
-import org.apache.geode.distributed.internal.DistributionConfig;
 import org.apache.geode.distributed.internal.InternalDistributedSystem;
-import org.apache.geode.internal.cache.execute.FunctionServiceStats;
 import org.apache.geode.internal.i18n.LocalizedStrings;
-import org.apache.geode.internal.statistics.platform.OsStatisticsFactory;
-import org.apache.geode.statistics.micrometer.MicrometerStatisticsFactoryImpl;
-import org.apache.geode.stats.common.internal.cache.execute.FunctionStats;
 import org.apache.geode.stats.common.statistics.StatisticDescriptor;
 import org.apache.geode.stats.common.statistics.Statistics;
 import org.apache.geode.stats.common.statistics.StatisticsFactory;
 import org.apache.geode.stats.common.statistics.StatisticsType;
 import org.apache.geode.stats.common.statistics.StatisticsTypeFactory;
-import org.apache.geode.stats.common.statistics.factory.StatsFactory;
 
-public class InternalDistributedSystemStats
-    implements StatisticsFactory, StatisticsManager, OsStatisticsFactory {
-
-  /**
-   * The sampler for this DistributedSystem.
-   */
-  private GemFireStatSampler sampler = null;
+public class GFSStatisticsFactoryImpl implements StatisticsFactory, StatisticsManager {
 
   private final CopyOnWriteArrayList<Statistics> statsList = new CopyOnWriteArrayList<>();
   private int statsListModCount = 0;
   private LongAdder statsListUniqueId = new LongAdder();
 
-  // As the function execution stats can be lot in number, its better to put
-  // them in a map so that it will be accessible immediately
-  private final ConcurrentHashMap<String, FunctionStats> functionExecutionStatsMap =
-      new ConcurrentHashMap<>();
-  private FunctionServiceStats functionServiceStats;
-
-  private boolean statsDisabled;
-
   // StatisticsTypeFactory methods
-  private StatisticsFactory statisticsTypeFactory;
-
-  // TODO, sorry another singleton... BLECH!!
-  private static final InternalDistributedSystemStats singleton =
-      new InternalDistributedSystemStats();
-
-  private InternalDistributedSystemStats() {}
-
-  // TODO Udo: We need to fix the bootstrapping to have DS's and DM's created in order to get the
-  // statsfactory created
-  public InternalDistributedSystemStats(boolean statsDisabled,
-      DistributionConfig distributionConfig,
-      InternalDistributedSystem internalDistributedSystem,
-      StatisticsTypeFactory statisticsTypeFactory) {
-    this.statisticsTypeFactory = (StatisticsFactory) statisticsTypeFactory;
-    this.statsDisabled = statsDisabled;
-    this.functionServiceStats = new FunctionServiceStats(this, "FunctionExecution");
-    if (!statsDisabled && !(statisticsTypeFactory instanceof MicrometerStatisticsFactoryImpl)) {
-      this.sampler = new GemFireStatSampler(internalDistributedSystem.getId(), distributionConfig,
-          internalDistributedSystem.getCancelCriterion(), this,
-          internalDistributedSystem.getDistributionManager());
-      this.sampler.start();
-
-    }
-  }
-
-  public static InternalDistributedSystemStats createInstance(boolean statsDisabled,
-      DistributionConfig distributionConfig,
-      InternalDistributedSystem distributedSystem,
-      MicrometerStatisticsFactoryImpl statisticsTypeFactory) {
-
-    singleton.statisticsTypeFactory = statisticsTypeFactory;
-    singleton.statsDisabled = statsDisabled;
-    singleton.functionServiceStats = new FunctionServiceStats(singleton, "FunctionExecution");
-    if (!statsDisabled && !(statisticsTypeFactory instanceof MicrometerStatisticsFactoryImpl)) {
-      singleton.sampler = new GemFireStatSampler(distributedSystem.getId(), distributionConfig,
-          distributedSystem.getCancelCriterion(), singleton,
-          distributedSystem.getDistributionManager());
-      singleton.sampler.start();
-
-    }
-    return singleton;
-  }
-
-  public static InternalDistributedSystemStats getSingleton() {
-    return singleton;
-  }
+  private StatisticsTypeFactory statisticsTypeFactory = new StatisticsTypeFactoryImpl();
 
   @Override
   public int getStatListModCount() {
@@ -165,84 +83,6 @@ public class InternalDistributedSystemStats
     return statsList.toArray(new Statistics[0]);
   }
 
-  // StatisticsFactory methods
-  public Statistics createStatistics(StatisticsType type) {
-    return createOsStatistics(type, null, 0, 0);
-  }
-
-  public Statistics createStatistics(StatisticsType type, String textId) {
-    return statisticsTypeFactory.createOsStatistics(type, textId, 0, 0);
-  }
-
-  public Statistics createStatistics(StatisticsType type, String textId, long numericId) {
-    return createOsStatistics(type, textId, numericId, 0);
-  }
-
-  public Statistics[] findStatisticsByType(final StatisticsType type) {
-    final ArrayList<Statistics> hits = new ArrayList<>();
-    visitStatistics(vistorStatistic -> {
-      if (type == vistorStatistic.getType()) {
-        hits.add(vistorStatistic);
-      }
-    });
-    Statistics[] result = new Statistics[hits.size()];
-    return hits.toArray(result);
-  }
-
-  public Statistics[] findStatisticsByTextId(final String textId) {
-    final ArrayList<Statistics> hits = new ArrayList<>();
-    visitStatistics(vistorStatistic -> {
-      if (vistorStatistic.getTextId().equals(textId)) {
-        hits.add(vistorStatistic);
-      }
-    });
-    Statistics[] result = new Statistics[hits.size()];
-    return hits.toArray(result);
-  }
-
-  public Statistics[] findStatisticsByNumericId(final long numericId) {
-    final ArrayList<Statistics> hits = new ArrayList<>();
-    visitStatistics(vistorStatistic -> {
-      if (numericId == vistorStatistic.getNumericId()) {
-        hits.add(vistorStatistic);
-      }
-    });
-    Statistics[] result = new Statistics[hits.size()];
-    return hits.toArray(result);
-  }
-
-  public Statistics findStatisticsByUniqueId(final long uniqueId) {
-    for (Statistics statistics : this.statsList) {
-      if (uniqueId == statistics.getUniqueId()) {
-        return statistics;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * for internal use only. Its called by {@link LocalStatisticsImpl#close}.
-   */
-  public void destroyStatistics(Statistics stats) {
-    synchronized (statsList) {
-      if (statsList.remove(stats)) {
-        statsListModCount++;
-      }
-    }
-  }
-
-  public Statistics createAtomicStatistics(StatisticsType type) {
-    return createAtomicStatistics(type, null, 0);
-  }
-
-  public Statistics createAtomicStatistics(StatisticsType type, String textId) {
-    return createAtomicStatistics(type, textId, 0);
-  }
-
-  public Statistics createAtomicStatistics(StatisticsType type, String textId, long numericId) {
-    return statisticsTypeFactory.createAtomicStatistics(type, textId, numericId);
-  }
-
   /**
    * Creates or finds a StatisticType for the given shared class.
    */
@@ -262,23 +102,6 @@ public class InternalDistributedSystemStats
   }
 
   @Override
-  public Statistics createOsStatistics(StatisticsType type, String textId, long numericId,
-      int osStatFlags) {
-    if (this.statsDisabled) {
-      return new DummyStatisticsImpl(type, textId, numericId);
-    }
-    statsListUniqueId.increment();
-    Statistics result =
-        new LocalStatisticsImpl(type, textId, numericId, statsListUniqueId.longValue(), false,
-            osStatFlags, this);
-    synchronized (statsList) {
-      statsList.add(result);
-      statsListModCount++;
-    }
-    return result;
-  }
-
-  @Override
   public StatisticDescriptor createIntCounter(String name, String description, String units) {
     return statisticsTypeFactory.createIntCounter(name, description, units);
   }
@@ -310,56 +133,125 @@ public class InternalDistributedSystemStats
 
   @Override
   public StatisticDescriptor createIntCounter(String name, String description, String units,
-      boolean largerBetter) {
+                                              boolean largerBetter) {
     return statisticsTypeFactory.createIntCounter(name, description, units, largerBetter);
   }
 
   @Override
   public StatisticDescriptor createLongCounter(String name, String description, String units,
-      boolean largerBetter) {
+                                               boolean largerBetter) {
     return statisticsTypeFactory.createLongCounter(name, description, units, largerBetter);
   }
 
   @Override
   public StatisticDescriptor createDoubleCounter(String name, String description, String units,
-      boolean largerBetter) {
+                                                 boolean largerBetter) {
     return statisticsTypeFactory.createDoubleCounter(name, description, units, largerBetter);
   }
 
   @Override
   public StatisticDescriptor createIntGauge(String name, String description, String units,
-      boolean largerBetter) {
+                                            boolean largerBetter) {
     return statisticsTypeFactory.createIntGauge(name, description, units, largerBetter);
   }
 
   @Override
   public StatisticDescriptor createLongGauge(String name, String description, String units,
-      boolean largerBetter) {
+                                             boolean largerBetter) {
     return statisticsTypeFactory.createLongGauge(name, description, units, largerBetter);
   }
 
   @Override
   public StatisticDescriptor createDoubleGauge(String name, String description, String units,
-      boolean largerBetter) {
+                                               boolean largerBetter) {
     return statisticsTypeFactory.createDoubleGauge(name, description, units, largerBetter);
   }
 
-  public FunctionStats getFunctionStats(String textId) {
-    FunctionStats stats = functionExecutionStatsMap.get(textId);
-    if (stats == null) {
-      stats = StatsFactory.createStatsImpl(FunctionStats.class, this, textId);
-      FunctionStats oldStats = functionExecutionStatsMap.putIfAbsent(textId, stats);
-      if (oldStats != null) {
-        stats.close();
-        stats = oldStats;
+  // StatisticsFactory methods
+  @Override
+  public Statistics createStatistics(StatisticsType type) {
+    return createOsStatistics(type, null, 0, 0);
+  }
+
+  @Override
+  public Statistics createStatistics(StatisticsType type, String textId) {
+    return statisticsTypeFactory.createOsStatistics(type, textId, 0, 0);
+  }
+
+  @Override
+  public Statistics createStatistics(StatisticsType type, String textId, long numericId) {
+    return createOsStatistics(type, textId, numericId, 0);
+  }
+
+  @Override
+  public Statistics[] findStatisticsByType(final StatisticsType type) {
+    final ArrayList<Statistics> hits = new ArrayList<>();
+    visitStatistics(vistorStatistic -> {
+      if (type == vistorStatistic.getType()) {
+        hits.add(vistorStatistic);
+      }
+    });
+    Statistics[] result = new Statistics[hits.size()];
+    return hits.toArray(result);
+  }
+
+  @Override
+  public Statistics[] findStatisticsByTextId(final String textId) {
+    final ArrayList<Statistics> hits = new ArrayList<>();
+    visitStatistics(vistorStatistic -> {
+      if (vistorStatistic.getTextId().equals(textId)) {
+        hits.add(vistorStatistic);
+      }
+    });
+    Statistics[] result = new Statistics[hits.size()];
+    return hits.toArray(result);
+  }
+
+  @Override
+  public Statistics[] findStatisticsByNumericId(final long numericId) {
+    final ArrayList<Statistics> hits = new ArrayList<>();
+    visitStatistics(vistorStatistic -> {
+      if (numericId == vistorStatistic.getNumericId()) {
+        hits.add(vistorStatistic);
+      }
+    });
+    Statistics[] result = new Statistics[hits.size()];
+    return hits.toArray(result);
+  }
+
+  public Statistics findStatisticsByUniqueId(final long uniqueId) {
+    for (Statistics statistics : this.statsList) {
+      if (uniqueId == statistics.getUniqueId()) {
+        return statistics;
       }
     }
-    return stats;
+    return null;
   }
 
+  /**
+   * for internal use only. Its called by {@link LocalStatisticsImpl#close}.
+   */
+  @Override
+  public void destroyStatistics(Statistics stats) {
+    synchronized (statsList) {
+      if (statsList.remove(stats)) {
+        statsListModCount++;
+      }
+    }
+  }
 
-  public FunctionServiceStats getFunctionServiceStats() {
-    return functionServiceStats;
+  @Override
+  public Statistics createOsStatistics(StatisticsType type, String textId, long numericId,
+                                       int osStatFlags) {
+    statsListUniqueId.increment();
+    Statistics result =
+        new LocalStatisticsImpl(type, textId, numericId, statsListUniqueId.longValue(), false,
+            osStatFlags, this);
+    synchronized (statsList) {
+      statsList.add(result);
+      statsListModCount++;
+    }
+    return result;
   }
 
   /**
@@ -372,26 +264,20 @@ public class InternalDistributedSystemStats
     }
   }
 
-  public Set<String> getAllFunctionExecutionIds() {
-    return functionExecutionStatsMap.keySet();
+  @Override
+  public Statistics createAtomicStatistics(StatisticsType type) {
+    return createAtomicStatistics(type, null, 0);
   }
 
-  public void closeStats() {
-    // closing the Aggregate stats
-    if (functionServiceStats != null) {
-      functionServiceStats.close();
-    }
-    // closing individual function stats
-    for (FunctionStats functionstats : functionExecutionStatsMap.values()) {
-      functionstats.close();
-    }
-
-    if (sampler != null) {
-      this.sampler.stop();
-    }
+  @Override
+  public Statistics createAtomicStatistics(StatisticsType type, String textId) {
+    return createAtomicStatistics(type, textId, 0);
   }
 
-  public GemFireStatSampler getStatSampler() {
-    return this.sampler;
+  @Override
+  public Statistics createAtomicStatistics(StatisticsType type, String textId, long numericId) {
+    statsListUniqueId.increment();
+    return StatisticsImpl
+        .createAtomicNoOS(type, textId, numericId, statsListUniqueId.longValue(), this);
   }
 }
diff --git a/geode-core/src/main/java/org/apache/geode/internal/statistics/InternalDistributedSystemStats.java b/geode-core/src/main/java/org/apache/geode/internal/statistics/InternalDistributedSystemStats.java
index a3b578d..9452512 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/statistics/InternalDistributedSystemStats.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/statistics/InternalDistributedSystemStats.java
@@ -14,67 +14,43 @@
  */
 package org.apache.geode.internal.statistics;
 
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.atomic.LongAdder;
 
 import org.apache.geode.distributed.internal.DistributionConfig;
 import org.apache.geode.distributed.internal.InternalDistributedSystem;
 import org.apache.geode.internal.cache.execute.FunctionServiceStats;
-import org.apache.geode.internal.i18n.LocalizedStrings;
-import org.apache.geode.internal.statistics.platform.OsStatisticsFactory;
 import org.apache.geode.statistics.micrometer.MicrometerStatisticsFactoryImpl;
 import org.apache.geode.stats.common.internal.cache.execute.FunctionStats;
-import org.apache.geode.stats.common.statistics.StatisticDescriptor;
-import org.apache.geode.stats.common.statistics.Statistics;
-import org.apache.geode.stats.common.statistics.StatisticsFactory;
-import org.apache.geode.stats.common.statistics.StatisticsType;
-import org.apache.geode.stats.common.statistics.StatisticsTypeFactory;
 import org.apache.geode.stats.common.statistics.factory.StatsFactory;
 
-public class InternalDistributedSystemStats
-    implements StatisticsFactory, StatisticsManager, OsStatisticsFactory {
-
-  /**
-   * The sampler for this DistributedSystem.
-   */
-  private GemFireStatSampler sampler = null;
-
-  private final CopyOnWriteArrayList<Statistics> statsList = new CopyOnWriteArrayList<>();
-  private int statsListModCount = 0;
-  private LongAdder statsListUniqueId = new LongAdder();
+public class InternalDistributedSystemStats {
+  // implements OsStatisticsFactory {
 
+  // TODO, sorry another singleton... BLECH!!
+  private static final InternalDistributedSystemStats singleton =
+      new InternalDistributedSystemStats();
   // As the function execution stats can be lot in number, its better to put
   // them in a map so that it will be accessible immediately
   private final ConcurrentHashMap<String, FunctionStats> functionExecutionStatsMap =
       new ConcurrentHashMap<>();
+  /**
+   * The sampler for this DistributedSystem.
+   */
+  private GemFireStatSampler sampler = null;
   private FunctionServiceStats functionServiceStats;
-
   private boolean statsDisabled;
 
-  // StatisticsTypeFactory methods
-  private StatisticsFactory statisticsTypeFactory;
-
-  // TODO, sorry another singleton... BLECH!!
-  private static final InternalDistributedSystemStats singleton =
-      new InternalDistributedSystemStats();
-
   private InternalDistributedSystemStats() {}
 
   // TODO Udo: We need to fix the bootstrapping to have DS's and DM's created in order to get the
   // statsfactory created
   public InternalDistributedSystemStats(boolean statsDisabled,
       DistributionConfig distributionConfig,
-      InternalDistributedSystem internalDistributedSystem,
-      StatisticsTypeFactory statisticsTypeFactory) {
-    this.statisticsTypeFactory = (StatisticsFactory) statisticsTypeFactory;
+      InternalDistributedSystem internalDistributedSystem) {
     this.statsDisabled = statsDisabled;
-    this.functionServiceStats = new FunctionServiceStats(this, "FunctionExecution");
+    this.functionServiceStats =
+        StatsFactory.createStatsImpl(FunctionServiceStats.class, "FunctionExecution");
     if (!statsDisabled && !(statisticsTypeFactory instanceof MicrometerStatisticsFactoryImpl)) {
       this.sampler = new GemFireStatSampler(internalDistributedSystem.getId(), distributionConfig,
           internalDistributedSystem.getCancelCriterion(), this,
@@ -86,12 +62,11 @@ public class InternalDistributedSystemStats
 
   public static InternalDistributedSystemStats createInstance(boolean statsDisabled,
       DistributionConfig distributionConfig,
-      InternalDistributedSystem distributedSystem,
-      MicrometerStatisticsFactoryImpl statisticsTypeFactory) {
+      InternalDistributedSystem distributedSystem) {
 
-    singleton.statisticsTypeFactory = statisticsTypeFactory;
     singleton.statsDisabled = statsDisabled;
-    singleton.functionServiceStats = new FunctionServiceStats(singleton, "FunctionExecution");
+    singleton.functionServiceStats =
+        StatsFactory.createStatsImpl(FunctionServiceStats.class, "FunctionExecution");
     if (!statsDisabled && !(statisticsTypeFactory instanceof MicrometerStatisticsFactoryImpl)) {
       singleton.sampler = new GemFireStatSampler(distributedSystem.getId(), distributionConfig,
           distributedSystem.getCancelCriterion(), singleton,
@@ -106,248 +81,10 @@ public class InternalDistributedSystemStats
     return singleton;
   }
 
-  @Override
-  public int getStatListModCount() {
-    return this.statsListModCount;
-  }
-
-  @Override
-  public List<Statistics> getStatsList() {
-    return this.statsList;
-  }
-
-  @Override
-  public String getName() {
-    return null;
-  }
-
-  @Override
-  public long getId() {
-    return 0;
-  }
-
-  @Override
-  public long getStartTime() {
-    return 0;
-  }
-
-  @Override
-  public int getStatisticsCount() {
-    return ((List<Statistics>) this.statsList).size();
-  }
-
-  @Override
-  public Statistics findStatistics(long id) {
-    List<Statistics> statsList = this.statsList;
-    for (Statistics statistics : statsList) {
-      if (statistics.getUniqueId() == id) {
-        return statistics;
-      }
-    }
-    throw new RuntimeException(
-        LocalizedStrings.PureStatSampler_COULD_NOT_FIND_STATISTICS_INSTANCE.toLocalizedString());
-  }
-
-  @Override
-  public boolean statisticsExists(long id) {
-    List<Statistics> statsList = this.statsList;
-    for (Statistics statistics : statsList) {
-      if (statistics.getUniqueId() == id) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @Override
-  public Statistics[] getStatistics() {
-    List<Statistics> statsList = this.statsList;
-    return statsList.toArray(new Statistics[0]);
-  }
-
-  // StatisticsFactory methods
-  public Statistics createStatistics(StatisticsType type) {
-    return createOsStatistics(type, null, 0, 0);
-  }
-
-  public Statistics createStatistics(StatisticsType type, String textId) {
-    return statisticsTypeFactory.createOsStatistics(type, textId, 0, 0);
-  }
-
-  public Statistics createStatistics(StatisticsType type, String textId, long numericId) {
-    return createOsStatistics(type, textId, numericId, 0);
-  }
-
-  public Statistics[] findStatisticsByType(final StatisticsType type) {
-    final ArrayList<Statistics> hits = new ArrayList<>();
-    visitStatistics(vistorStatistic -> {
-      if (type == vistorStatistic.getType()) {
-        hits.add(vistorStatistic);
-      }
-    });
-    Statistics[] result = new Statistics[hits.size()];
-    return hits.toArray(result);
-  }
-
-  public Statistics[] findStatisticsByTextId(final String textId) {
-    final ArrayList<Statistics> hits = new ArrayList<>();
-    visitStatistics(vistorStatistic -> {
-      if (vistorStatistic.getTextId().equals(textId)) {
-        hits.add(vistorStatistic);
-      }
-    });
-    Statistics[] result = new Statistics[hits.size()];
-    return hits.toArray(result);
-  }
-
-  public Statistics[] findStatisticsByNumericId(final long numericId) {
-    final ArrayList<Statistics> hits = new ArrayList<>();
-    visitStatistics(vistorStatistic -> {
-      if (numericId == vistorStatistic.getNumericId()) {
-        hits.add(vistorStatistic);
-      }
-    });
-    Statistics[] result = new Statistics[hits.size()];
-    return hits.toArray(result);
-  }
-
-  public Statistics findStatisticsByUniqueId(final long uniqueId) {
-    for (Statistics statistics : this.statsList) {
-      if (uniqueId == statistics.getUniqueId()) {
-        return statistics;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * for internal use only. Its called by {@link LocalStatisticsImpl#close}.
-   */
-  public void destroyStatistics(Statistics stats) {
-    synchronized (statsList) {
-      if (statsList.remove(stats)) {
-        statsListModCount++;
-      }
-    }
-  }
-
-  public Statistics createAtomicStatistics(StatisticsType type) {
-    return createAtomicStatistics(type, null, 0);
-  }
-
-  public Statistics createAtomicStatistics(StatisticsType type, String textId) {
-    return createAtomicStatistics(type, textId, 0);
-  }
-
-  public Statistics createAtomicStatistics(StatisticsType type, String textId, long numericId) {
-    return statisticsTypeFactory.createAtomicStatistics(type, textId, numericId);
-  }
-
-  /**
-   * Creates or finds a StatisticType for the given shared class.
-   */
-  @Override
-  public StatisticsType createType(String name, String description, StatisticDescriptor[] stats) {
-    return statisticsTypeFactory.createType(name, description, stats);
-  }
-
-  @Override
-  public StatisticsType findType(String name) {
-    return statisticsTypeFactory.findType(name);
-  }
-
-  @Override
-  public StatisticsType[] createTypesFromXml(Reader reader) throws IOException {
-    return statisticsTypeFactory.createTypesFromXml(reader);
-  }
-
-  @Override
-  public Statistics createOsStatistics(StatisticsType type, String textId, long numericId,
-      int osStatFlags) {
-    if (this.statsDisabled) {
-      return new DummyStatisticsImpl(type, textId, numericId);
-    }
-    statsListUniqueId.increment();
-    Statistics result =
-        new LocalStatisticsImpl(type, textId, numericId, statsListUniqueId.longValue(), false,
-            osStatFlags, this);
-    synchronized (statsList) {
-      statsList.add(result);
-      statsListModCount++;
-    }
-    return result;
-  }
-
-  @Override
-  public StatisticDescriptor createIntCounter(String name, String description, String units) {
-    return statisticsTypeFactory.createIntCounter(name, description, units);
-  }
-
-  @Override
-  public StatisticDescriptor createLongCounter(String name, String description, String units) {
-    return statisticsTypeFactory.createLongCounter(name, description, units);
-  }
-
-  @Override
-  public StatisticDescriptor createDoubleCounter(String name, String description, String units) {
-    return statisticsTypeFactory.createDoubleCounter(name, description, units);
-  }
-
-  @Override
-  public StatisticDescriptor createIntGauge(String name, String description, String units) {
-    return statisticsTypeFactory.createIntGauge(name, description, units);
-  }
-
-  @Override
-  public StatisticDescriptor createLongGauge(String name, String description, String units) {
-    return statisticsTypeFactory.createLongGauge(name, description, units);
-  }
-
-  @Override
-  public StatisticDescriptor createDoubleGauge(String name, String description, String units) {
-    return statisticsTypeFactory.createDoubleGauge(name, description, units);
-  }
-
-  @Override
-  public StatisticDescriptor createIntCounter(String name, String description, String units,
-      boolean largerBetter) {
-    return statisticsTypeFactory.createIntCounter(name, description, units, largerBetter);
-  }
-
-  @Override
-  public StatisticDescriptor createLongCounter(String name, String description, String units,
-      boolean largerBetter) {
-    return statisticsTypeFactory.createLongCounter(name, description, units, largerBetter);
-  }
-
-  @Override
-  public StatisticDescriptor createDoubleCounter(String name, String description, String units,
-      boolean largerBetter) {
-    return statisticsTypeFactory.createDoubleCounter(name, description, units, largerBetter);
-  }
-
-  @Override
-  public StatisticDescriptor createIntGauge(String name, String description, String units,
-      boolean largerBetter) {
-    return statisticsTypeFactory.createIntGauge(name, description, units, largerBetter);
-  }
-
-  @Override
-  public StatisticDescriptor createLongGauge(String name, String description, String units,
-      boolean largerBetter) {
-    return statisticsTypeFactory.createLongGauge(name, description, units, largerBetter);
-  }
-
-  @Override
-  public StatisticDescriptor createDoubleGauge(String name, String description, String units,
-      boolean largerBetter) {
-    return statisticsTypeFactory.createDoubleGauge(name, description, units, largerBetter);
-  }
-
   public FunctionStats getFunctionStats(String textId) {
     FunctionStats stats = functionExecutionStatsMap.get(textId);
     if (stats == null) {
-      stats = StatsFactory.createStatsImpl(FunctionStats.class, this, textId);
+      stats = StatsFactory.createStatsImpl(FunctionStats.class, textId);
       FunctionStats oldStats = functionExecutionStatsMap.putIfAbsent(textId, stats);
       if (oldStats != null) {
         stats.close();
@@ -357,21 +94,10 @@ public class InternalDistributedSystemStats
     return stats;
   }
 
-
   public FunctionServiceStats getFunctionServiceStats() {
     return functionServiceStats;
   }
 
-  /**
-   * For every registered statistic instance call the specified visitor. This method was added to
-   * fix bug 40358
-   */
-  public void visitStatistics(InternalDistributedSystem.StatisticsVisitor visitor) {
-    for (Statistics s : this.statsList) {
-      visitor.visit(s);
-    }
-  }
-
   public Set<String> getAllFunctionExecutionIds() {
     return functionExecutionStatsMap.keySet();
   }
diff --git a/geode-core/src/main/kotlin/Locator.kt b/geode-core/src/main/kotlin/Locator.kt
index d1da1ff..665cbed 100644
--- a/geode-core/src/main/kotlin/Locator.kt
+++ b/geode-core/src/main/kotlin/Locator.kt
@@ -5,6 +5,7 @@ fun main(args: Array<String>) {
     val build = LocatorLauncher.Builder().apply {
         port = 44550
         set("statistic-sampling-enabled", "true")
+        set(ConfigurationProperties.ENABLE_TIME_STATISTICS, "true")
         set(ConfigurationProperties.JMX_MANAGER, "false")
         set(ConfigurationProperties.JMX_MANAGER_START, "false")
         set(ConfigurationProperties.ENABLE_CLUSTER_CONFIGURATION, "false")
diff --git a/geode-core/src/main/resources/META-INF/services/org.apache.geode.stats.common.statistics.StatisticsFactory b/geode-core/src/main/resources/META-INF/services/org.apache.geode.stats.common.statistics.StatisticsFactory
new file mode 100644
index 0000000..db19fd9
--- /dev/null
+++ b/geode-core/src/main/resources/META-INF/services/org.apache.geode.stats.common.statistics.StatisticsFactory
@@ -0,0 +1 @@
+org.apache.geode.internal.statistics.GFSStatisticFactoryImpl
\ No newline at end of file
diff --git a/geode-micrometer-stats/src/main/kotlin/org/apache/geode/statistics/internal/micrometer/impl/MicrometerMeterGroup.kt b/geode-micrometer-stats/src/main/kotlin/org/apache/geode/statistics/internal/micrometer/impl/MicrometerMeterGroup.kt
index 9cf1499..44d2c28 100644
--- a/geode-micrometer-stats/src/main/kotlin/org/apache/geode/statistics/internal/micrometer/impl/MicrometerMeterGroup.kt
+++ b/geode-micrometer-stats/src/main/kotlin/org/apache/geode/statistics/internal/micrometer/impl/MicrometerMeterGroup.kt
@@ -22,6 +22,10 @@ import org.apache.geode.statistics.micrometer.MicrometerStatsImplementer
 
 abstract class MicrometerMeterGroup(private val statisticsFactory: StatisticsFactory?, private val groupName: String) : StatisticsMeterGroup, MeterBinder,
         MicrometerStatsImplementer {
+    init{
+        initializeImplementer(statisticsFactory)
+        registerStatsImplementer(statisticsFactory)
+    }
     private val registeredMeters = mutableListOf<MicrometerStatisticMeter>()
     private val registeredMeterGroups = mutableListOf<MicrometerMeterGroup>()
 
@@ -40,6 +44,7 @@ abstract class MicrometerMeterGroup(private val statisticsFactory: StatisticsFac
     }
 
     override fun getMeterGroupName(): String = groupName
+
     override fun bindTo(registry: MeterRegistry) {
         registeredMeters.forEach {it.register(registry, commonGroupTags) }
         registeredMeterGroups.forEach { micrometerMeterGroup -> micrometerMeterGroup.registeredMeters.forEach { it.register(registry, commonGroupTags) } }
diff --git a/geode-micrometer-stats/src/main/kotlin/org/apache/geode/statistics/micrometer/MicrometerStatisticsFactoryImpl.kt b/geode-micrometer-stats/src/main/kotlin/org/apache/geode/statistics/micrometer/MicrometerStatisticsFactoryImpl.kt
index 5bbfa79..5c44415 100644
--- a/geode-micrometer-stats/src/main/kotlin/org/apache/geode/statistics/micrometer/MicrometerStatisticsFactoryImpl.kt
+++ b/geode-micrometer-stats/src/main/kotlin/org/apache/geode/statistics/micrometer/MicrometerStatisticsFactoryImpl.kt
@@ -30,6 +30,9 @@ class MicrometerStatisticsFactoryImpl(vararg meterRegistries: MeterRegistry = ar
     private val micrometerStatisticsManager = MicrometerStatisticsManager.createWithRegistries(meterRegistries)
     private val meterGroupMap = hashMapOf<String, StatisticsType>()
 
+    override fun getType(): String = "Micrometer"
+
+
     override fun createOsStatistics(type: StatisticsType?, textId: String, numericId: Long, osStatFlags: Int): Statistics =
             MicrometerStatisticsImpl(0, type as MicrometerStatisticsType, textId, numericId)
 
diff --git a/geode-micrometer-stats/src/main/resources/META-INF/services/org.apache.geode.stats.common.statistics.StatisticsFactory b/geode-micrometer-stats/src/main/resources/META-INF/services/org.apache.geode.stats.common.statistics.StatisticsFactory
new file mode 100644
index 0000000..1830ba1
--- /dev/null
+++ b/geode-micrometer-stats/src/main/resources/META-INF/services/org.apache.geode.stats.common.statistics.StatisticsFactory
@@ -0,0 +1 @@
+org.apache.geode.statistics.micrometer.MicrometerStatisticsFactoryImpl
\ No newline at end of file
diff --git a/geode-old-versions/build.gradle b/geode-old-versions/build.gradle
index 06de76f..791909d 100644
--- a/geode-old-versions/build.gradle
+++ b/geode-old-versions/build.gradle
@@ -28,14 +28,14 @@ task createGeodeClasspathsFile {
 
   // Add sourceSets for backwards compatibility, rolling upgrade, and
   // pdx testing.
-  addOldVersion('test100', '1.0.0-incubating', false)
-  addOldVersion('test110', '1.1.0', false)
-  addOldVersion('test111', '1.1.1', false)
-  addOldVersion('test120', '1.2.0', true)
-  addOldVersion('test130', '1.3.0', true)
-  addOldVersion('test140', '1.4.0', true)
-  addOldVersion('test150', '1.5.0', true)
-  addOldVersion('test160', '1.6.0', true)
+//  addOldVersion('test100', '1.0.0-incubating', false)
+//  addOldVersion('test110', '1.1.0', false)
+//  addOldVersion('test111', '1.1.1', false)
+//  addOldVersion('test120', '1.2.0', true)
+//  addOldVersion('test130', '1.3.0', true)
+//  addOldVersion('test140', '1.4.0', true)
+//  addOldVersion('test150', '1.5.0', true)
+//  addOldVersion('test160', '1.6.0', true)
 
   doLast {
     Properties versions = new Properties();
diff --git a/geode-core/src/main/java/org/apache/geode/internal/statistics/StatisticsManager.java b/geode-stats-common/src/main/java/org/apache/geode/internal/statistics/StatisticsManager.java
similarity index 100%
rename from geode-core/src/main/java/org/apache/geode/internal/statistics/StatisticsManager.java
rename to geode-stats-common/src/main/java/org/apache/geode/internal/statistics/StatisticsManager.java
diff --git a/geode-stats-common/src/main/java/org/apache/geode/stats/common/statistics/StatisticsFactory.java b/geode-stats-common/src/main/java/org/apache/geode/stats/common/statistics/StatisticsFactory.java
index c8452d2..f037c5b 100644
--- a/geode-stats-common/src/main/java/org/apache/geode/stats/common/statistics/StatisticsFactory.java
+++ b/geode-stats-common/src/main/java/org/apache/geode/stats/common/statistics/StatisticsFactory.java
@@ -158,4 +158,8 @@ public interface StatisticsFactory extends StatisticsTypeFactory {
    * Returns an array of all the existing statistics with the given numericId.
    */
   Statistics[] findStatisticsByNumericId(long numericId);
+
+  default String getType() {
+    return "GeodeStats";
+  }
 }
diff --git a/geode-stats-common/src/main/java/org/apache/geode/stats/common/statistics/factory/StatsFactory.java b/geode-stats-common/src/main/java/org/apache/geode/stats/common/statistics/factory/StatsFactory.java
index 582a720..04aa928 100644
--- a/geode-stats-common/src/main/java/org/apache/geode/stats/common/statistics/factory/StatsFactory.java
+++ b/geode-stats-common/src/main/java/org/apache/geode/stats/common/statistics/factory/StatsFactory.java
@@ -19,6 +19,7 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.ServiceLoader;
 
 import org.reflections.Reflections;
 import org.reflections.scanners.ResourcesScanner;
@@ -38,51 +39,36 @@ import org.apache.geode.stats.common.statistics.StatsImplementer;
 
 public class StatsFactory {
 
-  private static final StatsFactory statsFactory = new StatsFactory(getStatsImplementor());
-
-
+  private static final boolean isExperimentalEnabled =
+      Boolean.getBoolean("geode.experimental.stats.micrometer");
+  private static final StatsFactory statsFactory =
+      new StatsFactory(getStatsImplementor(), getStatisticsTypeFactory());
   private final Class<? extends StatsImplementer> selectedStatsImplementor;
   private final Map<Class<?>, Class<? extends StatsImplementer>> resolvedStatsImplForClass =
       new HashMap<>();
-  private final Reflections reflections;
+  private final StatisticsFactory statisticsFactory;
 
-  private StatsFactory(Class<? extends StatsImplementer> selectedStatsImplementor) {
+  private StatsFactory(Class<? extends StatsImplementer> selectedStatsImplementor,
+      StatisticsFactory statisticsFactory) {
     List<ClassLoader> classLoadersList = new LinkedList<>();
     classLoadersList.add(ClasspathHelper.contextClassLoader());
     classLoadersList.add(ClasspathHelper.staticClassLoader());
 
-    reflections = new Reflections(new ConfigurationBuilder()
+    /* don't exclude Object.class */
+    Reflections reflections = new Reflections(new ConfigurationBuilder()
         .setScanners(new SubTypesScanner(false /* don't exclude Object.class */),
             new ResourcesScanner())
         .setUrls(ClasspathHelper.forClassLoader(classLoadersList.toArray(new ClassLoader[0])))
         .filterInputsBy(new FilterBuilder()
             .includePackage("org.apache.geode..*").excludePackage("org.springframework..*")));
     this.selectedStatsImplementor = selectedStatsImplementor;
+    this.statisticsFactory = statisticsFactory;
     initializeStatsImplementations(reflections);
-    System.out.println("StatsFactory.StatsFactory");
-  }
-
-  private void initializeStatsImplementations(Reflections reflections) {
-    reflections.getSubTypesOf(Stats.class)
-        .stream().filter(Class::isInterface)
-        .forEach(interfaze -> reflections.getSubTypesOf(interfaze).stream()
-            .filter(selectedStatsImplementor::isAssignableFrom)
-            .forEach(aClass -> resolvedStatsImplForClass
-                .put(interfaze, (Class<? extends StatsImplementer>) aClass)));
-    // The loading of CachePerfStats implementations needs to be special cased,
-    // as RegionPerfStats is also of type CachePerfStats, which causes problems when you
-    // want to find the direct implementation of CachePerfStats
-    reflections.getSubTypesOf(CachePerfStats.class).stream()
-        .filter(clazz -> selectedStatsImplementor.isAssignableFrom(clazz)
-            && !RegionPerfStats.class.isAssignableFrom(clazz) && !clazz.getName()
-                .contains("DummyCachePerfStats"))
-        .forEach(aClass -> resolvedStatsImplForClass
-            .put(CachePerfStats.class, (Class<? extends StatsImplementer>) aClass));
   }
 
   private static Class<? extends StatsImplementer> getStatsImplementor() {
     try {
-      return Boolean.getBoolean("geode.experimental.stats.micrometer")
+      return isExperimentalEnabled
           ? (Class<? extends StatsImplementer>) Class
               .forName("org.apache.geode.statistics.micrometer.MicrometerStatsImplementer")
           : GFSStatsImplementer.class;
@@ -92,58 +78,54 @@ public class StatsFactory {
     }
   }
 
+  private static StatisticsFactory getStatisticsTypeFactory() {
+    final ServiceLoader<StatisticsFactory> services = ServiceLoader.load(StatisticsFactory.class);
+    for (StatisticsFactory statisticsFactory : services) {
+      if (isExperimentalEnabled && statisticsFactory.getType().equals("Micrometer")) {
+        return statisticsFactory;
+      } else if (statisticsFactory.getType().equals("GeodeStats")) {
+        return statisticsFactory;
+      }
+    }
+    throw new IllegalStateException(
+        "There should have been a statsfactory found. Please check your settings");
+  }
+
   public static <V extends StatsImplementer> V createStatsImpl(Class<?> interfaceClazz,
-      StatisticsFactory statisticsFactory,
       String identifier) {
-    return (V) resolveInstanceFromClass(interfaceClazz, statisticsFactory, identifier);
+    return (V) resolveInstanceFromClass(interfaceClazz, identifier);
   }
 
-  public static ConnectionStats createConnectionStatsImpl(StatisticsFactory dummyStatisticsFactory,
+  public static ConnectionStats createConnectionStatsImpl(
       String statName, PoolStats poolStats) {
-    return (ConnectionStats) resolveConnectionStatInstanceFromClass(ConnectionStats.class,
-        dummyStatisticsFactory,
-        statName, poolStats);
+    return (ConnectionStats) resolveConnectionStatInstanceFromClass(statName, poolStats);
   }
 
-  public static CachePerfStats createCachePerfStatsImpl(StatisticsFactory statisticsFactory,
-      String name) {
-    return (CachePerfStats) resolveCachePerfInstanceFromClass(
-        statisticsFactory, name);
+  public static CachePerfStats createCachePerfStatsImpl(String name) {
+    return (CachePerfStats) resolveCachePerfInstanceFromClass(name);
   }
 
-
-  private static StatsImplementer resolveInstanceFromClass(Class<?> interfaceClazz,
-      StatisticsFactory statisticsFactory,
-      String name) {
-    return statsFactory.createInstanceFromClass(interfaceClazz, statisticsFactory, name);
+  private static StatsImplementer resolveInstanceFromClass(Class<?> interfaceClazz, String name) {
+    return statsFactory.createInstanceFromClass(interfaceClazz, name);
   }
 
-  private static StatsImplementer resolveCachePerfInstanceFromClass(
-      StatisticsFactory statisticsFactory,
-      String name) {
-    return statsFactory.createInstanceFromClass(CachePerfStats.class, statisticsFactory, name);
+  private static StatsImplementer resolveCachePerfInstanceFromClass(String name) {
+    return statsFactory.createInstanceFromClass(CachePerfStats.class, name);
   }
 
-  private static StatsImplementer resolveConnectionStatInstanceFromClass(Class<?> interfaceClazz,
-      StatisticsFactory statisticsFactory,
-      String name,
+  private static StatsImplementer resolveConnectionStatInstanceFromClass(String name,
       PoolStats poolStats) {
-    return statsFactory.createConnectionStatInstanceFromClass(statisticsFactory, name, poolStats);
+    return statsFactory.createConnectionStatInstanceFromClass(name, poolStats);
   }
 
   public static RegionPerfStats createRegionPerfStatsImplFromClass(Class<?> interfaceClazz,
-      StatisticsFactory statisticsFactory,
-      CachePerfStats cachePerfStats,
-      String regionName) {
-    Class<? extends StatsImplementer> resolvedLocatorClassImpl;
+      CachePerfStats cachePerfStats, String regionName) {
     try {
-      resolvedLocatorClassImpl = statsFactory.resolvedStatsImplForClass.get(interfaceClazz);
-      StatsImplementer statsImplementor = resolvedLocatorClassImpl
+      Class<? extends StatsImplementer> resolvedLocatorClassImpl =
+          statsFactory.resolvedStatsImplForClass.get(interfaceClazz);
+      return (RegionPerfStats) resolvedLocatorClassImpl
           .getDeclaredConstructor(StatisticsFactory.class, CachePerfStats.class, String.class)
-          .newInstance(statisticsFactory, cachePerfStats, regionName);
-      statsImplementor.initializeImplementer(statisticsFactory);
-      statsImplementor.registerStatsImplementer(statisticsFactory);
-      return (RegionPerfStats) statsImplementor;
+          .newInstance(statsFactory.getStatisticsFactory(), cachePerfStats, regionName);
     } catch (InstantiationException | IllegalAccessException | NoSuchMethodException
         | InvocationTargetException e) {
       e.printStackTrace();
@@ -151,19 +133,35 @@ public class StatsFactory {
     return null;
   }
 
-  private StatsImplementer createConnectionStatInstanceFromClass(
-      StatisticsFactory statisticsFactory,
-      String locatorName, PoolStats poolStats) {
-    Class<? extends StatsImplementer> resolvedLocatorClassImpl;
+  private StatisticsFactory getStatisticsFactory() {
+    return statisticsFactory;
+  }
+
+  private void initializeStatsImplementations(Reflections reflections) {
+    reflections.getSubTypesOf(Stats.class)
+        .stream().filter(Class::isInterface)
+        .forEach(interfaze -> reflections.getSubTypesOf(interfaze).stream()
+            .filter(selectedStatsImplementor::isAssignableFrom)
+            .forEach(aClass -> resolvedStatsImplForClass
+                .put(interfaze, (Class<? extends StatsImplementer>) aClass)));
+    // The loading of CachePerfStats implementations needs to be special cased,
+    // as RegionPerfStats is also of type CachePerfStats, which causes problems when you
+    // want to find the direct implementation of CachePerfStats
+    reflections.getSubTypesOf(CachePerfStats.class).stream()
+        .filter(clazz -> selectedStatsImplementor.isAssignableFrom(clazz)
+            && !RegionPerfStats.class.isAssignableFrom(clazz) && !clazz.getName()
+                .contains("DummyCachePerfStats"))
+        .forEach(aClass -> resolvedStatsImplForClass
+            .put(CachePerfStats.class, (Class<? extends StatsImplementer>) aClass));
+  }
+
+  private StatsImplementer createConnectionStatInstanceFromClass(String locatorName, PoolStats poolStats) {
     try {
-      resolvedLocatorClassImpl = resolveImplementationForClass(ConnectionStats.class);
-      StatsImplementer statsImplementor =
-          resolvedLocatorClassImpl
-              .getDeclaredConstructor(StatisticsFactory.class, String.class, PoolStats.class)
-              .newInstance(statisticsFactory, locatorName, poolStats);
-      statsImplementor.initializeImplementer(statisticsFactory);
-      statsImplementor.registerStatsImplementer(statisticsFactory);
-      return statsImplementor;
+      Class<? extends StatsImplementer> resolvedLocatorClassImpl =
+          resolveImplementationForClass(ConnectionStats.class);
+      return resolvedLocatorClassImpl
+          .getDeclaredConstructor(StatisticsFactory.class, String.class, PoolStats.class)
+          .newInstance(statisticsFactory, locatorName, poolStats);
     } catch (InstantiationException | IllegalAccessException | NoSuchMethodException
         | InvocationTargetException e) {
       e.printStackTrace();
@@ -181,18 +179,13 @@ public class StatsFactory {
     return resolvedLocatorClassImpl;
   }
 
-  private StatsImplementer createInstanceFromClass(Class<?> interfaceClazz,
-      StatisticsFactory statisticsFactory,
-      String name) {
+  private StatsImplementer createInstanceFromClass(Class<?> interfaceClazz, String name) {
     try {
       Class<? extends StatsImplementer> resolvedLocatorClassImpl =
           resolveImplementationForClass(interfaceClazz);
-      StatsImplementer statsImplementor = resolvedLocatorClassImpl
+      return resolvedLocatorClassImpl
           .getDeclaredConstructor(StatisticsFactory.class, String.class)
           .newInstance(statisticsFactory, name);
-      statsImplementor.initializeImplementer(statisticsFactory);
-      statsImplementor.registerStatsImplementer(statisticsFactory);
-      return statsImplementor;
     } catch (InstantiationException | IllegalAccessException | NoSuchMethodException
         | InvocationTargetException e) {
       e.printStackTrace();