You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2017/04/26 09:41:17 UTC
lucene-solr:jira/solr-10262: SOLR-10262 Make metric implementations
configurable.
Repository: lucene-solr
Updated Branches:
refs/heads/jira/solr-10262 [created] 555a14968
SOLR-10262 Make metric implementations configurable.
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/555a1496
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/555a1496
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/555a1496
Branch: refs/heads/jira/solr-10262
Commit: 555a149688d39f90ef2897d5a8f6e9bc59f89a33
Parents: 680f4d7
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Wed Apr 26 11:40:40 2017 +0200
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Wed Apr 26 11:40:40 2017 +0200
----------------------------------------------------------------------
.../org/apache/solr/core/CoreContainer.java | 11 +-
.../org/apache/solr/core/MetricsConfig.java | 121 +++++++
.../java/org/apache/solr/core/NodeConfig.java | 32 +-
.../org/apache/solr/core/SolrXmlConfig.java | 29 +-
.../apache/solr/metrics/MetricSuppliers.java | 363 +++++++++++++++++++
.../solr/metrics/SolrCoreMetricManager.java | 2 +-
.../apache/solr/metrics/SolrMetricManager.java | 45 ++-
.../apache/solr/servlet/SolrDispatchFilter.java | 2 +-
.../org/apache/solr/util/SolrPluginUtils.java | 21 +-
.../src/test-files/solr/solr-metricsconfig.xml | 61 ++++
.../org/apache/solr/metrics/JvmMetricsTest.java | 4 +-
.../apache/solr/metrics/MetricsConfigTest.java | 126 +++++++
.../solr/metrics/MockCounterSupplier.java | 36 ++
.../solr/metrics/MockHistogramSupplier.java | 40 ++
.../apache/solr/metrics/MockMeterSupplier.java | 36 ++
.../apache/solr/metrics/MockTimerSupplier.java | 46 +++
.../metrics/SolrMetricsIntegrationTest.java | 2 +-
.../java/org/apache/solr/util/TestHarness.java | 6 +-
18 files changed, 940 insertions(+), 43 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/java/org/apache/solr/core/CoreContainer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index 28c1eaf..3ff5135 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -479,7 +479,7 @@ public class CoreContainer {
}
}
- metricManager = new SolrMetricManager();
+ metricManager = new SolrMetricManager(loader, cfg.getMetricsConfig());
coreContainerWorkExecutor = MetricUtils.instrumentedExecutorService(
coreContainerWorkExecutor, null,
@@ -525,9 +525,10 @@ public class CoreContainer {
if(pkiAuthenticationPlugin != null)
containerHandlers.put(PKIAuthenticationPlugin.PATH, pkiAuthenticationPlugin.getRequestHandler());
- metricManager.loadReporters(cfg.getMetricReporterPlugins(), loader, null, SolrInfoBean.Group.node);
- metricManager.loadReporters(cfg.getMetricReporterPlugins(), loader, null, SolrInfoBean.Group.jvm);
- metricManager.loadReporters(cfg.getMetricReporterPlugins(), loader, null, SolrInfoBean.Group.jetty);
+ PluginInfo[] metricReporters = cfg.getMetricsConfig().getMetricReporters();
+ metricManager.loadReporters(metricReporters, loader, null, SolrInfoBean.Group.node);
+ metricManager.loadReporters(metricReporters, loader, null, SolrInfoBean.Group.jvm);
+ metricManager.loadReporters(metricReporters, loader, null, SolrInfoBean.Group.jetty);
coreConfigService = ConfigSetService.createConfigSetService(cfg, loader, zkSys.zkController);
@@ -556,7 +557,7 @@ public class CoreContainer {
fieldCacheBean.initializeMetrics(metricManager, registryName, null);
if (isZooKeeperAware()) {
- metricManager.loadClusterReporters(cfg.getMetricReporterPlugins(), this);
+ metricManager.loadClusterReporters(metricReporters, this);
}
// setup executor to load cores in parallel
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/java/org/apache/solr/core/MetricsConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/MetricsConfig.java b/solr/core/src/java/org/apache/solr/core/MetricsConfig.java
new file mode 100644
index 0000000..796483b
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/core/MetricsConfig.java
@@ -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.solr.core;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ */
+public class MetricsConfig {
+
+ private final PluginInfo[] metricReporters;
+ private final Set<String> hiddenSysProps;
+ private final PluginInfo counterSupplier;
+ private final PluginInfo meterSupplier;
+ private final PluginInfo timerSupplier;
+ private final PluginInfo histogramSupplier;
+
+ private MetricsConfig(PluginInfo[] metricReporters, Set<String> hiddenSysProps,
+ PluginInfo counterSupplier, PluginInfo meterSupplier,
+ PluginInfo timerSupplier, PluginInfo histogramSupplier) {
+ this.metricReporters = metricReporters;
+ this.hiddenSysProps = hiddenSysProps;
+ this.counterSupplier = counterSupplier;
+ this.meterSupplier = meterSupplier;
+ this.timerSupplier = timerSupplier;
+ this.histogramSupplier = histogramSupplier;
+ }
+
+ public PluginInfo[] getMetricReporters() {
+ return metricReporters;
+ }
+
+ public Set<String> getHiddenSysProps() {
+ return hiddenSysProps;
+ }
+
+ public PluginInfo getCounterSupplier() {
+ return counterSupplier;
+ }
+
+ public PluginInfo getMeterSupplier() {
+ return meterSupplier;
+ }
+
+ public PluginInfo getTimerSupplier() {
+ return timerSupplier;
+ }
+
+ public PluginInfo getHistogramSupplier() {
+ return histogramSupplier;
+ }
+
+ public static class MetricsConfigBuilder {
+ private PluginInfo[] metricReporterPlugins = new PluginInfo[0];
+ private Set<String> hiddenSysProps = new HashSet<>();
+ private PluginInfo counterSupplier;
+ private PluginInfo meterSupplier;
+ private PluginInfo timerSupplier;
+ private PluginInfo histogramSupplier;
+
+ public MetricsConfigBuilder() {
+
+ }
+
+ public MetricsConfigBuilder setHiddenSysProps(Set<String> hiddenSysProps) {
+ if (hiddenSysProps != null && !hiddenSysProps.isEmpty()) {
+ this.hiddenSysProps.clear();
+ this.hiddenSysProps.addAll(hiddenSysProps);
+ }
+ return this;
+ }
+
+ public MetricsConfigBuilder setMetricReporterPlugins(PluginInfo[] metricReporterPlugins) {
+ this.metricReporterPlugins = metricReporterPlugins != null ? metricReporterPlugins : new PluginInfo[0];
+ return this;
+ }
+
+ public MetricsConfigBuilder setCounterSupplier(PluginInfo info) {
+ this.counterSupplier = info;
+ return this;
+ }
+
+ public MetricsConfigBuilder setMeterSupplier(PluginInfo info) {
+ this.meterSupplier = info;
+ return this;
+ }
+
+ public MetricsConfigBuilder setTimerSupplier(PluginInfo info) {
+ this.timerSupplier = info;
+ return this;
+ }
+
+ public MetricsConfigBuilder setHistogramSupplier(PluginInfo info) {
+ this.histogramSupplier = info;
+ return this;
+ }
+
+ public MetricsConfig build() {
+ return new MetricsConfig(metricReporterPlugins, hiddenSysProps, counterSupplier, meterSupplier,
+ timerSupplier, histogramSupplier);
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/java/org/apache/solr/core/NodeConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/NodeConfig.java b/solr/core/src/java/org/apache/solr/core/NodeConfig.java
index 7a209d0..2b70130 100644
--- a/solr/core/src/java/org/apache/solr/core/NodeConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/NodeConfig.java
@@ -65,9 +65,7 @@ public class NodeConfig {
private final PluginInfo[] backupRepositoryPlugins;
- private final PluginInfo[] metricReporterPlugins;
-
- private final Set<String> hiddenSysProps;
+ private final MetricsConfig metricsConfig;
private final PluginInfo transientCacheConfig;
@@ -78,7 +76,7 @@ public class NodeConfig {
LogWatcherConfig logWatcherConfig, CloudConfig cloudConfig, Integer coreLoadThreads,
int transientCacheSize, boolean useSchemaCache, String managementPath, SolrResourceLoader loader,
Properties solrProperties, PluginInfo[] backupRepositoryPlugins,
- PluginInfo[] metricReporterPlugins, Set<String> hiddenSysProps, PluginInfo transientCacheConfig) {
+ MetricsConfig metricsConfig, PluginInfo transientCacheConfig) {
this.nodeName = nodeName;
this.coreRootDirectory = coreRootDirectory;
this.configSetBaseDirectory = configSetBaseDirectory;
@@ -98,8 +96,7 @@ public class NodeConfig {
this.loader = loader;
this.solrProperties = solrProperties;
this.backupRepositoryPlugins = backupRepositoryPlugins;
- this.metricReporterPlugins = metricReporterPlugins;
- this.hiddenSysProps = hiddenSysProps;
+ this.metricsConfig = metricsConfig;
this.transientCacheConfig = transientCacheConfig;
if (this.cloudConfig != null && this.getCoreLoadThreadCount(false) < 2) {
@@ -189,12 +186,8 @@ public class NodeConfig {
return backupRepositoryPlugins;
}
- public PluginInfo[] getMetricReporterPlugins() {
- return metricReporterPlugins;
- }
-
- public Set<String> getHiddenSysProps() {
- return hiddenSysProps;
+ public MetricsConfig getMetricsConfig() {
+ return metricsConfig;
}
public PluginInfo getTransientCachePluginInfo() { return transientCacheConfig; }
@@ -220,8 +213,7 @@ public class NodeConfig {
private String managementPath;
private Properties solrProperties = new Properties();
private PluginInfo[] backupRepositoryPlugins;
- private PluginInfo[] metricReporterPlugins;
- private Set<String> hiddenSysProps = new HashSet<>(DEFAULT_HIDDEN_SYS_PROPS);
+ private MetricsConfig metricsConfig;
private PluginInfo transientCacheConfig;
private final SolrResourceLoader loader;
@@ -251,6 +243,7 @@ public class NodeConfig {
this.loader = loader;
this.coreRootDirectory = loader.getInstancePath();
this.configSetBaseDirectory = loader.getInstancePath().resolve("configsets");
+ this.metricsConfig = new MetricsConfig.MetricsConfigBuilder().build();
}
public NodeConfigBuilder setCoreRootDirectory(String coreRootDirectory) {
@@ -340,8 +333,8 @@ public class NodeConfig {
return this;
}
- public NodeConfigBuilder setMetricReporterPlugins(PluginInfo[] metricReporterPlugins) {
- this.metricReporterPlugins = metricReporterPlugins;
+ public NodeConfigBuilder setMetricsConfig(MetricsConfig metricsConfig) {
+ this.metricsConfig = metricsConfig;
return this;
}
@@ -350,16 +343,11 @@ public class NodeConfig {
return this;
}
- public NodeConfigBuilder setHiddenSysProps(Set<String> hiddenSysProps) {
- this.hiddenSysProps = hiddenSysProps;
- return this;
- }
-
public NodeConfig build() {
return new NodeConfig(nodeName, coreRootDirectory, configSetBaseDirectory, sharedLibDirectory, shardHandlerFactoryConfig,
updateShardHandlerConfig, coreAdminHandlerClass, collectionsAdminHandlerClass, infoHandlerClass, configSetsHandlerClass,
logWatcherConfig, cloudConfig, coreLoadThreads, transientCacheSize, useSchemaCache, managementPath, loader, solrProperties,
- backupRepositoryPlugins, metricReporterPlugins, hiddenSysProps, transientCacheConfig);
+ backupRepositoryPlugins, metricsConfig, transientCacheConfig);
}
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
index 65f29a4..e783a89 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
@@ -103,8 +103,7 @@ public class SolrXmlConfig {
if (cloudConfig != null)
configBuilder.setCloudConfig(cloudConfig);
configBuilder.setBackupRepositoryPlugins(getBackupRepositoryPluginInfos(config));
- configBuilder.setMetricReporterPlugins(getMetricReporterPluginInfos(config));
- configBuilder.setHiddenSysProps(getHiddenSysProps(config));
+ configBuilder.setMetricsConfig(getMetricsConfig(config));
return fillSolrSection(configBuilder, entries);
}
@@ -461,6 +460,32 @@ public class SolrXmlConfig {
return configs;
}
+ private static MetricsConfig getMetricsConfig(Config config) {
+ MetricsConfig.MetricsConfigBuilder builder = new MetricsConfig.MetricsConfigBuilder();
+ Node node = config.getNode("solr/metrics/suppliers/counter", false);
+ if (node != null) {
+ builder = builder.setCounterSupplier(new PluginInfo(node, "counterSupplier", false, false));
+ }
+ node = config.getNode("solr/metrics/suppliers/meter", false);
+ if (node != null) {
+ builder = builder.setMeterSupplier(new PluginInfo(node, "meterSupplier", false, false));
+ }
+ node = config.getNode("solr/metrics/suppliers/timer", false);
+ if (node != null) {
+ builder = builder.setTimerSupplier(new PluginInfo(node, "timerSupplier", false, false));
+ }
+ node = config.getNode("solr/metrics/suppliers/histogram", false);
+ if (node != null) {
+ builder = builder.setHistogramSupplier(new PluginInfo(node, "histogramSupplier", false, false));
+ }
+ PluginInfo[] reporterPlugins = getMetricReporterPluginInfos(config);
+ Set<String> hiddenSysProps = getHiddenSysProps(config);
+ return builder
+ .setMetricReporterPlugins(reporterPlugins)
+ .setHiddenSysProps(hiddenSysProps)
+ .build();
+ }
+
private static PluginInfo[] getMetricReporterPluginInfos(Config config) {
NodeList nodes = (NodeList) config.evaluate("solr/metrics/reporter", XPathConstants.NODESET);
List<PluginInfo> configs = new ArrayList<>();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/java/org/apache/solr/metrics/MetricSuppliers.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/MetricSuppliers.java b/solr/core/src/java/org/apache/solr/metrics/MetricSuppliers.java
new file mode 100644
index 0000000..c444f66
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/metrics/MetricSuppliers.java
@@ -0,0 +1,363 @@
+/*
+ * 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.solr.metrics;
+
+import java.lang.invoke.MethodHandles;
+import java.util.concurrent.TimeUnit;
+
+import com.codahale.metrics.Clock;
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.ExponentiallyDecayingReservoir;
+import com.codahale.metrics.Histogram;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Reservoir;
+import com.codahale.metrics.SlidingTimeWindowReservoir;
+import com.codahale.metrics.SlidingWindowReservoir;
+import com.codahale.metrics.Timer;
+import com.codahale.metrics.UniformReservoir;
+import org.apache.solr.core.PluginInfo;
+import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.util.SolrPluginUtils;
+import org.apache.solr.util.plugin.PluginInfoInitialized;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper class for constructing instances of {@link com.codahale.metrics.MetricRegistry.MetricSupplier}
+ * based on plugin configuration. This allows us to customize eg. {@link com.codahale.metrics.Reservoir}
+ * implementations and parameters for timers and histograms.
+ * <p>Custom supplier implementations must provide a zero-args constructor, and may optionally implement
+ * {@link org.apache.solr.util.plugin.PluginInfoInitialized} interface for configuration - if they don't then
+ * {@link org.apache.solr.util.SolrPluginUtils#invokeSetters(Object, Iterable, boolean)} will be used for initialization.</p>
+ */
+public class MetricSuppliers {
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ /**
+ * Default {@link Counter} supplier. No configuration available.
+ */
+ public static final class DefaultCounterSupplier implements MetricRegistry.MetricSupplier<Counter> {
+ @Override
+ public Counter newMetric() {
+ return new Counter();
+ }
+ }
+
+ private static final Clock CPU_CLOCK = new Clock.CpuTimeClock();
+ private static final Clock USER_CLOCK = new Clock.UserTimeClock();
+
+ /** Clock type parameter. */
+ public static final String CLOCK = "clock";
+ /** User-time clock. */
+ public static final String CLOCK_USER = "user";
+ /** CPU-time clock. */
+ public static final String CLOCK_CPU = "cpu";
+
+ /**
+ * Default {@link Meter} supplier. The following configuration is available, either as attribute
+ * or initArgs:
+ * <ul>
+ * <li>clock - (string) can be set to {@link #CLOCK_USER} for {@link com.codahale.metrics.Clock.UserTimeClock} or
+ * {@link #CLOCK_CPU} for {@link com.codahale.metrics.Clock.CpuTimeClock}. If not set then the value of
+ * {@link Clock#defaultClock()} will be used.</li>
+ * </ul>
+ */
+ public static final class DefaultMeterSupplier implements MetricRegistry.MetricSupplier<Meter>, PluginInfoInitialized {
+
+ public Clock clk = Clock.defaultClock();
+
+ @Override
+ public void init(PluginInfo info) {
+ clk = getClock(info, CLOCK);
+ }
+
+ @Override
+ public Meter newMetric() {
+ return new Meter(clk);
+ }
+
+ }
+
+ private static Clock getClock(PluginInfo info, String param) {
+ if (info == null) {
+ return Clock.defaultClock();
+ }
+ String clock = null;
+ if (info.attributes != null) {
+ clock = info.attributes.get(param);
+ }
+ if (clock == null && info.initArgs != null) {
+ clock = (String)info.initArgs.get(param);
+ }
+ Clock clk = Clock.defaultClock();
+ if (clock != null) {
+ if (clock.equalsIgnoreCase(CLOCK_USER)) {
+ clk = USER_CLOCK;
+ } else if (clock.equalsIgnoreCase(CLOCK_CPU)) {
+ clk = CPU_CLOCK;
+ }
+ }
+ return clk;
+ }
+
+ /** Implementation class, must implement {@link Reservoir}. Supports non-standard configuration
+ * of the implementations available in metrics-core.
+ */
+ public static final String RESERVOIR = "reservoir";
+ /** Size of reservoir. */
+ public static final String RESERVOIR_SIZE = "size";
+ /** Alpha parameter of {@link ExponentiallyDecayingReservoir}. */
+ public static final String RESERVOIR_EDR_ALPHA = "alpha";
+ /** Time window in seconds of {@link SlidingTimeWindowReservoir}. */
+ public static final String RESERVOIR_WINDOW = "window";
+
+ private static final String EDR_CLAZZ = ExponentiallyDecayingReservoir.class.getName();
+ private static final String UNI_CLAZZ = UniformReservoir.class.getName();
+ private static final String STW_CLAZZ = SlidingTimeWindowReservoir.class.getName();
+ private static final String SW_CLAZZ = SlidingWindowReservoir.class.getName();
+
+ private static final int DEFAULT_SIZE = 1028;
+ private static final double DEFAULT_ALPHA = 0.015;
+ private static final long DEFAULT_WINDOW = 300;
+
+ private static final Reservoir getReservoir(SolrResourceLoader loader, PluginInfo info) {
+ if (info == null) {
+ return new ExponentiallyDecayingReservoir();
+ }
+ Clock clk = getClock(info, CLOCK);
+ String clazz = ExponentiallyDecayingReservoir.class.getName();
+ int size = -1;
+ double alpha = -1;
+ long window = -1;
+ if (info.initArgs != null) {
+ if (info.initArgs.get(RESERVOIR) != null) {
+ String val = String.valueOf(info.initArgs.get(RESERVOIR)).trim();
+ if (!val.isEmpty()) {
+ clazz = val;
+ }
+ }
+ Number n = (Number)info.initArgs.get(RESERVOIR_SIZE);
+ if (n != null) {
+ size = n.intValue();
+ }
+ n = (Number)info.initArgs.get(RESERVOIR_EDR_ALPHA);
+ if (n != null) {
+ alpha = n.doubleValue();
+ }
+ n = (Number)info.initArgs.get(RESERVOIR_WINDOW);
+ if (n != null) {
+ window = n.longValue();
+ }
+ }
+ if (size <= 0) {
+ size = DEFAULT_SIZE;
+ }
+ if (alpha <= 0) {
+ alpha = DEFAULT_ALPHA;
+ }
+ // special case for core implementations
+ if (clazz.equals(EDR_CLAZZ)) {
+ return new ExponentiallyDecayingReservoir(size, alpha, clk);
+ } else if (clazz.equals(UNI_CLAZZ)) {
+ return new UniformReservoir(size);
+ } else if (clazz.equals(STW_CLAZZ)) {
+ if (window <= 0) {
+ window = DEFAULT_WINDOW; // 5 minutes, comparable to EDR
+ }
+ return new SlidingTimeWindowReservoir(window, TimeUnit.SECONDS);
+ } else if (clazz.equals(SW_CLAZZ)) {
+ return new SlidingWindowReservoir(size);
+ } else { // custom reservoir
+ Reservoir reservoir;
+ try {
+ reservoir = loader.newInstance(clazz, Reservoir.class);
+ if (reservoir instanceof PluginInfoInitialized) {
+ ((PluginInfoInitialized)reservoir).init(info);
+ } else {
+ SolrPluginUtils.invokeSetters(reservoir, info.initArgs, true);
+ }
+ return reservoir;
+ } catch (Exception e) {
+ log.warn("Error initializing custom Reservoir implementation (will use default): " + info, e);
+ return new ExponentiallyDecayingReservoir(size, alpha, clk);
+ }
+ }
+ }
+
+ /**
+ * Default supplier of {@link Timer} instances, with configurable clock and reservoir.
+ * See {@link DefaultMeterSupplier} for clock configuration. Reservoir configuration uses
+ * {@link #RESERVOIR}, {@link #RESERVOIR_EDR_ALPHA}, {@link #RESERVOIR_SIZE} and
+ * {@link #RESERVOIR_WINDOW}.
+ */
+ public static final class DefaultTimerSupplier implements MetricRegistry.MetricSupplier<Timer>, PluginInfoInitialized {
+
+ public Clock clk = Clock.defaultClock();
+ private PluginInfo info;
+ private SolrResourceLoader loader;
+
+ public DefaultTimerSupplier(SolrResourceLoader loader) {
+ this.loader = loader;
+ }
+
+ @Override
+ public void init(PluginInfo info) {
+ clk = getClock(info, CLOCK);
+ this.info = info;
+ }
+
+ public Reservoir getReservoir() {
+ return MetricSuppliers.getReservoir(loader, info);
+ }
+
+ @Override
+ public Timer newMetric() {
+ return new Timer(getReservoir(), clk);
+ }
+ }
+
+ /**
+ * Default supplier of {@link Histogram} instances, with configurable reservoir.
+ */
+ public static final class DefaultHistogramSupplier implements MetricRegistry.MetricSupplier<Histogram>, PluginInfoInitialized {
+
+ private PluginInfo info;
+ private SolrResourceLoader loader;
+
+ public DefaultHistogramSupplier(SolrResourceLoader loader) {
+ this.loader = loader;
+ }
+
+ @Override
+ public void init(PluginInfo info) {
+ this.info = info;
+ }
+
+ public Reservoir getReservoir() {
+ return MetricSuppliers.getReservoir(loader, info);
+ }
+
+ @Override
+ public Histogram newMetric() {
+ return new Histogram(getReservoir());
+ }
+ }
+
+ /**
+ * Create a {@link Counter} supplier.
+ * @param loader resource loader
+ * @param info plugin configuration, or null for default
+ * @return configured supplier instance, or default instance if configuration was invalid
+ */
+ public static MetricRegistry.MetricSupplier<Counter> counterSupplier(SolrResourceLoader loader, PluginInfo info) {
+ if (info == null || info.className == null || info.className.trim().isEmpty()) {
+ return new DefaultCounterSupplier();
+ }
+
+ MetricRegistry.MetricSupplier<Counter> supplier;
+ try {
+ supplier = loader.newInstance(info.className, MetricRegistry.MetricSupplier.class);
+ } catch (Exception e) {
+ log.warn("Error creating custom Counter supplier (will use default): " + info, e);
+ supplier = new DefaultCounterSupplier();
+ }
+ if (supplier instanceof PluginInfoInitialized) {
+ ((PluginInfoInitialized)supplier).init(info);
+ } else {
+ SolrPluginUtils.invokeSetters(supplier, info.initArgs, true);
+ }
+ return supplier;
+ }
+
+ /**
+ * Create a {@link Meter} supplier.
+ * @param loader resource loader
+ * @param info plugin configuration, or null for default
+ * @return configured supplier instance, or default instance if configuration was invalid
+ */
+ public static MetricRegistry.MetricSupplier<Meter> meterSupplier(SolrResourceLoader loader, PluginInfo info) {
+ MetricRegistry.MetricSupplier<Meter> supplier;
+ if (info == null || info.className == null || info.className.isEmpty()) {
+ supplier = new DefaultMeterSupplier();
+ } else {
+ try {
+ supplier = loader.newInstance(info.className, MetricRegistry.MetricSupplier.class);
+ } catch (Exception e) {
+ log.warn("Error creating custom Meter supplier (will use default): " + info, e);
+ supplier = new DefaultMeterSupplier();
+ }
+ }
+ if (supplier instanceof PluginInfoInitialized) {
+ ((PluginInfoInitialized)supplier).init(info);
+ } else {
+ SolrPluginUtils.invokeSetters(supplier, info.initArgs, true);
+ }
+ return supplier;
+ }
+
+ /**
+ * Create a {@link Timer} supplier.
+ * @param loader resource loader
+ * @param info plugin configuration, or null for default
+ * @return configured supplier instance, or default instance if configuration was invalid
+ */
+ public static MetricRegistry.MetricSupplier<Timer> timerSupplier(SolrResourceLoader loader, PluginInfo info) {
+ MetricRegistry.MetricSupplier<Timer> supplier;
+ if (info == null || info.className == null || info.className.isEmpty()) {
+ supplier = new DefaultTimerSupplier(loader);
+ } else {
+ try {
+ supplier = loader.newInstance(info.className, MetricRegistry.MetricSupplier.class);
+ } catch (Exception e) {
+ log.warn("Error creating custom Meter supplier (will use default): " + info, e);
+ supplier = new DefaultTimerSupplier(loader);
+ }
+ }
+ if (supplier instanceof PluginInfoInitialized) {
+ ((PluginInfoInitialized)supplier).init(info);
+ } else {
+ SolrPluginUtils.invokeSetters(supplier, info.initArgs, true);
+ }
+ return supplier;
+ }
+
+ /**
+ * Create a {@link Histogram} supplier.
+ * @param info plugin configuration, or null for default
+ * @return configured supplier instance, or default instance if configuration was invalid
+ */
+ public static MetricRegistry.MetricSupplier<Histogram> histogramSupplier(SolrResourceLoader loader, PluginInfo info) {
+ MetricRegistry.MetricSupplier<Histogram> supplier;
+ if (info == null || info.className == null || info.className.isEmpty()) {
+ supplier = new DefaultHistogramSupplier(loader);
+ } else {
+ try {
+ supplier = loader.newInstance(info.className, MetricRegistry.MetricSupplier.class);
+ } catch (Exception e) {
+ log.warn("Error creating custom Meter supplier (will use default): " + info, e);
+ supplier = new DefaultHistogramSupplier(loader);
+ }
+ }
+ if (supplier instanceof PluginInfoInitialized) {
+ ((PluginInfoInitialized)supplier).init(info);
+ } else {
+ SolrPluginUtils.invokeSetters(supplier, info.initArgs, true);
+ }
+ return supplier;
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java b/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
index 8de053c..c7b6318 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
@@ -82,7 +82,7 @@ public class SolrCoreMetricManager implements Closeable {
*/
public void loadReporters() {
NodeConfig nodeConfig = core.getCoreContainer().getConfig();
- PluginInfo[] pluginInfos = nodeConfig.getMetricReporterPlugins();
+ PluginInfo[] pluginInfos = nodeConfig.getMetricsConfig().getMetricReporters();
metricManager.loadReporters(pluginInfos, core.getResourceLoader(), tag,
SolrInfoBean.Group.core, registryName);
if (cloudMode) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
index d4eb06a..c041d1f 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
@@ -49,6 +49,7 @@ import com.codahale.metrics.SharedMetricRegistries;
import com.codahale.metrics.Timer;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.MetricsConfig;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrInfoBean;
@@ -102,7 +103,41 @@ public class SolrMetricManager {
public static final int DEFAULT_CLOUD_REPORTER_PERIOD = 60;
- public SolrMetricManager() { }
+ private MetricRegistry.MetricSupplier<Counter> counterSupplier;
+ private MetricRegistry.MetricSupplier<Meter> meterSupplier;
+ private MetricRegistry.MetricSupplier<Timer> timerSupplier;
+ private MetricRegistry.MetricSupplier<Histogram> histogramSupplier;
+
+ public SolrMetricManager() {
+ counterSupplier = MetricSuppliers.counterSupplier(null, null);
+ meterSupplier = MetricSuppliers.meterSupplier(null, null);
+ timerSupplier = MetricSuppliers.timerSupplier(null, null);
+ histogramSupplier = MetricSuppliers.histogramSupplier(null, null);
+ }
+
+ public SolrMetricManager(SolrResourceLoader loader, MetricsConfig metricsConfig) {
+ counterSupplier = MetricSuppliers.counterSupplier(loader, metricsConfig.getCounterSupplier());
+ meterSupplier = MetricSuppliers.meterSupplier(loader, metricsConfig.getMeterSupplier());
+ timerSupplier = MetricSuppliers.timerSupplier(loader, metricsConfig.getTimerSupplier());
+ histogramSupplier = MetricSuppliers.histogramSupplier(loader, metricsConfig.getHistogramSupplier());
+ }
+
+ // for unit tests
+ public MetricRegistry.MetricSupplier<Counter> getCounterSupplier() {
+ return counterSupplier;
+ }
+
+ public MetricRegistry.MetricSupplier<Meter> getMeterSupplier() {
+ return meterSupplier;
+ }
+
+ public MetricRegistry.MetricSupplier<Timer> getTimerSupplier() {
+ return timerSupplier;
+ }
+
+ public MetricRegistry.MetricSupplier<Histogram> getHistogramSupplier() {
+ return histogramSupplier;
+ }
/**
* An implementation of {@link MetricFilter} that selects metrics
@@ -539,7 +574,7 @@ public class SolrMetricManager {
if (info != null) {
info.registerMetricName(name);
}
- return registry(registry).meter(name);
+ return registry(registry).meter(name, meterSupplier);
}
/**
@@ -555,7 +590,7 @@ public class SolrMetricManager {
if (info != null) {
info.registerMetricName(name);
}
- return registry(registry).timer(name);
+ return registry(registry).timer(name, timerSupplier);
}
/**
@@ -571,7 +606,7 @@ public class SolrMetricManager {
if (info != null) {
info.registerMetricName(name);
}
- return registry(registry).counter(name);
+ return registry(registry).counter(name, counterSupplier);
}
/**
@@ -587,7 +622,7 @@ public class SolrMetricManager {
if (info != null) {
info.registerMetricName(name);
}
- return registry(registry).histogram(name);
+ return registry(registry).histogram(name, histogramSupplier);
}
/**
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
index 39ccadc..5905280 100644
--- a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
+++ b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
@@ -186,7 +186,7 @@ public class SolrDispatchFilter extends BaseSolrFilter {
private void setupJvmMetrics() {
SolrMetricManager metricManager = cores.getMetricManager();
- final Set<String> hiddenSysProps = cores.getConfig().getHiddenSysProps();
+ final Set<String> hiddenSysProps = cores.getConfig().getMetricsConfig().getHiddenSysProps();
try {
String registry = SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm);
metricManager.registerAll(registry, new AltBufferPoolMetricSet(), true, "buffers");
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
index 6a9f679..658b035 100644
--- a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
+++ b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
@@ -1070,6 +1070,10 @@ public class SolrPluginUtils {
public static void invokeSetters(Object bean, Iterable<Map.Entry<String,Object>> initArgs) {
+ invokeSetters(bean, initArgs, false);
+ }
+
+ public static void invokeSetters(Object bean, Iterable<Map.Entry<String,Object>> initArgs, boolean lenient) {
if (initArgs == null) return;
final Class<?> clazz = bean.getClass();
for (Map.Entry<String,Object> entry : initArgs) {
@@ -1077,19 +1081,27 @@ public class SolrPluginUtils {
String setterName = "set" + String.valueOf(Character.toUpperCase(key.charAt(0))) + key.substring(1);
try {
final Object val = entry.getValue();
- final Method method = findSetter(clazz, setterName, key, val.getClass());
- method.invoke(bean, val);
+ final Method method = findSetter(clazz, setterName, key, val.getClass(), lenient);
+ if (method != null) {
+ method.invoke(bean, val);
+ }
} catch (InvocationTargetException | IllegalAccessException e1) {
+ if (lenient) {
+ continue;
+ }
throw new RuntimeException("Error invoking setter " + setterName + " on class : " + clazz.getName(), e1);
}
}
}
- private static Method findSetter(Class<?> clazz, String setterName, String key, Class<?> paramClazz) {
+ private static Method findSetter(Class<?> clazz, String setterName, String key, Class<?> paramClazz, boolean lenient) {
BeanInfo beanInfo;
try {
beanInfo = Introspector.getBeanInfo(clazz);
} catch (IntrospectionException ie) {
+ if (lenient) {
+ return null;
+ }
throw new RuntimeException("Error getting bean info for class : " + clazz.getName(), ie);
}
for (final boolean matchParamClazz: new boolean[]{true, false}) {
@@ -1102,6 +1114,9 @@ public class SolrPluginUtils {
}
}
}
+ if (lenient) {
+ return null;
+ }
throw new RuntimeException("No setter corrresponding to '" + key + "' in " + clazz.getName());
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/test-files/solr/solr-metricsconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/solr-metricsconfig.xml b/solr/core/src/test-files/solr/solr-metricsconfig.xml
new file mode 100644
index 0000000..6edb2fa
--- /dev/null
+++ b/solr/core/src/test-files/solr/solr-metricsconfig.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<solr>
+ <metrics>
+ <suppliers>
+ <counter class="${counter.class:}">
+ <str name="foo">bar</str>
+ <int name="wxt">100</int>
+ <bool name="flag">true</bool>
+ </counter>
+ <meter class="${meter.class:}">
+ <str name="foo">bar</str>
+ <str name="clock">${clock:user}</str>
+ </meter>
+ <timer class="${timer.class:}">
+ <str name="foo">bar</str>
+ <str name="clock">${clock:user}</str>
+ <str name="reservoir">${timer.reservoir:}</str>
+ <int name="size">${histogram.size:-1}</int>
+ <double name="alpha">${histogram.alpha:-1}</double>
+ <long name="window">${histogram.window:-1}</long>
+ <str name="strParam">strParam</str>
+ <int name="intParam">-100</int>
+ <bool name="boolParam">true</bool>
+ </timer>
+ <histogram class="${histogram.class:}">
+ <str name="foo">bar</str>
+ <str name="clock">${clock:user}</str>
+ <str name="reservoir">${histogram.reservoir:}</str>
+ <int name="size">${histogram.size:-1}</int>
+ <double name="alpha">${histogram.alpha:-1}</double>
+ <long name="window">${histogram.window:-1}</long>
+ </histogram>
+ </suppliers>
+ <hiddenSysProps>
+ <str>foo</str>
+ <str>bar</str>
+ <str>baz</str>
+ </hiddenSysProps>
+ <!-- this reporter doesn't specify 'group' or 'registry', it will be instantiated for any group. -->
+ <reporter name="universal" class="org.apache.solr.metrics.reporters.MockMetricReporter">
+ <str name="configurable">configured</str>
+ </reporter>
+ </metrics>
+</solr>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/test/org/apache/solr/metrics/JvmMetricsTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/JvmMetricsTest.java b/solr/core/src/test/org/apache/solr/metrics/JvmMetricsTest.java
index 020fe5e..d40bc63 100644
--- a/solr/core/src/test/org/apache/solr/metrics/JvmMetricsTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/JvmMetricsTest.java
@@ -124,14 +124,14 @@ public class JvmMetricsTest extends SolrJettyTestBase {
String solrXml = FileUtils.readFileToString(Paths.get(home.toString(), "solr.xml").toFile(), "UTF-8");
NodeConfig config = SolrXmlConfig.fromString(loader, solrXml);
NodeConfig.NodeConfigBuilder.DEFAULT_HIDDEN_SYS_PROPS.forEach(s -> {
- assertTrue(s, config.getHiddenSysProps().contains(s));
+ assertTrue(s, config.getMetricsConfig().getHiddenSysProps().contains(s));
});
// custom config
solrXml = FileUtils.readFileToString(Paths.get(home.toString(), "solr-hiddensysprops.xml").toFile(), "UTF-8");
NodeConfig config2 = SolrXmlConfig.fromString(loader, solrXml);
Arrays.asList("foo", "bar", "baz").forEach(s -> {
- assertTrue(s, config2.getHiddenSysProps().contains(s));
+ assertTrue(s, config2.getMetricsConfig().getHiddenSysProps().contains(s));
});
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/test/org/apache/solr/metrics/MetricsConfigTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/MetricsConfigTest.java b/solr/core/src/test/org/apache/solr/metrics/MetricsConfigTest.java
new file mode 100644
index 0000000..789e95a
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/metrics/MetricsConfigTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.solr.metrics;
+
+import java.io.File;
+import java.io.InputStream;
+
+import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule;
+import com.codahale.metrics.Clock;
+import com.codahale.metrics.ExponentiallyDecayingReservoir;
+import com.codahale.metrics.Reservoir;
+import com.codahale.metrics.SlidingTimeWindowReservoir;
+import com.codahale.metrics.UniformReservoir;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.core.NodeConfig;
+import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.core.SolrXmlConfig;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+
+/**
+ *
+ */
+public class MetricsConfigTest extends SolrTestCaseJ4 {
+ @Rule
+ public TestRule solrTestRules = RuleChain.outerRule(new SystemPropertiesRestoreRule());
+
+ // tmp dir, cleaned up automatically.
+ private static File solrHome = null;
+ private static SolrResourceLoader loader = null;
+
+ @BeforeClass
+ public static void setupLoader() throws Exception {
+ solrHome = createTempDir().toFile();
+ loader = new SolrResourceLoader(solrHome.toPath());
+ }
+
+ @AfterClass
+ public static void cleanupLoader() throws Exception {
+ solrHome = null;
+ loader = null;
+ }
+
+ @Test
+ public void testDefaults() throws Exception {
+ NodeConfig cfg = loadNodeConfig();
+ SolrMetricManager mgr = new SolrMetricManager(loader, cfg.getMetricsConfig());
+ assertTrue(mgr.getCounterSupplier() instanceof MetricSuppliers.DefaultCounterSupplier);
+ assertTrue(mgr.getMeterSupplier() instanceof MetricSuppliers.DefaultMeterSupplier);
+ assertTrue(mgr.getTimerSupplier() instanceof MetricSuppliers.DefaultTimerSupplier);
+ assertTrue(mgr.getHistogramSupplier() instanceof MetricSuppliers.DefaultHistogramSupplier);
+ Clock clk = ((MetricSuppliers.DefaultTimerSupplier)mgr.getTimerSupplier()).clk;
+ assertTrue(clk instanceof Clock.UserTimeClock);
+ Reservoir rsv = ((MetricSuppliers.DefaultTimerSupplier)mgr.getTimerSupplier()).getReservoir();
+ assertTrue(rsv instanceof ExponentiallyDecayingReservoir);
+ }
+
+ @Test
+ public void testCustomReservoir() throws Exception {
+ System.setProperty("timer.reservoir", UniformReservoir.class.getName());
+ System.setProperty("histogram.size", "2048");
+ System.setProperty("histogram.window", "600");
+ System.setProperty("histogram.reservoir", SlidingTimeWindowReservoir.class.getName());
+ NodeConfig cfg = loadNodeConfig();
+ SolrMetricManager mgr = new SolrMetricManager(loader, cfg.getMetricsConfig());
+ assertTrue(mgr.getCounterSupplier() instanceof MetricSuppliers.DefaultCounterSupplier);
+ assertTrue(mgr.getMeterSupplier() instanceof MetricSuppliers.DefaultMeterSupplier);
+ assertTrue(mgr.getTimerSupplier() instanceof MetricSuppliers.DefaultTimerSupplier);
+ assertTrue(mgr.getHistogramSupplier() instanceof MetricSuppliers.DefaultHistogramSupplier);
+ Reservoir rsv = ((MetricSuppliers.DefaultTimerSupplier)mgr.getTimerSupplier()).getReservoir();
+ assertTrue(rsv instanceof UniformReservoir);
+ rsv = ((MetricSuppliers.DefaultHistogramSupplier)mgr.getHistogramSupplier()).getReservoir();
+ assertTrue(rsv instanceof SlidingTimeWindowReservoir);
+ }
+
+ @Test
+ public void testCustomSupplier() throws Exception {
+ System.setProperty("counter.class", MockCounterSupplier.class.getName());
+ System.setProperty("meter.class", MockMeterSupplier.class.getName());
+ System.setProperty("timer.class", MockTimerSupplier.class.getName());
+ System.setProperty("histogram.class", MockHistogramSupplier.class.getName());
+ NodeConfig cfg = loadNodeConfig();
+ SolrMetricManager mgr = new SolrMetricManager(loader, cfg.getMetricsConfig());
+ assertTrue(mgr.getCounterSupplier() instanceof MockCounterSupplier);
+ assertTrue(mgr.getMeterSupplier() instanceof MockMeterSupplier);
+ assertTrue(mgr.getTimerSupplier() instanceof MockTimerSupplier);
+ assertTrue(mgr.getHistogramSupplier() instanceof MockHistogramSupplier);
+
+ // assert setter-based configuration
+ MockCounterSupplier mockCounterSupplier = ((MockCounterSupplier)mgr.getCounterSupplier());
+ assertEquals("bar", mockCounterSupplier.foo);
+ MockMeterSupplier mockMeterSupplier = ((MockMeterSupplier)mgr.getMeterSupplier());
+ assertEquals("bar", mockMeterSupplier.foo);
+ MockTimerSupplier mockTimerSupplier = ((MockTimerSupplier)mgr.getTimerSupplier());
+ assertEquals(true, mockTimerSupplier.boolParam);
+ assertEquals("strParam", mockTimerSupplier.strParam);
+ assertEquals(-100, mockTimerSupplier.intParam);
+
+ // assert PluginInfoInitialized-based configuration
+ MockHistogramSupplier mockHistogramSupplier = ((MockHistogramSupplier)mgr.getHistogramSupplier());
+ assertNotNull(mockHistogramSupplier.info);
+ }
+
+ private NodeConfig loadNodeConfig() throws Exception {
+ InputStream is = MetricsConfigTest.class.getResourceAsStream("/solr/solr-metricsconfig.xml");
+ return SolrXmlConfig.fromInputStream(loader, is);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/test/org/apache/solr/metrics/MockCounterSupplier.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/MockCounterSupplier.java b/solr/core/src/test/org/apache/solr/metrics/MockCounterSupplier.java
new file mode 100644
index 0000000..d6ca407
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/metrics/MockCounterSupplier.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.metrics;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.MetricRegistry;
+
+/**
+ *
+ */
+public class MockCounterSupplier implements MetricRegistry.MetricSupplier<Counter> {
+ public String foo;
+
+ public void setFoo(String foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public Counter newMetric() {
+ return new Counter();
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/test/org/apache/solr/metrics/MockHistogramSupplier.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/MockHistogramSupplier.java b/solr/core/src/test/org/apache/solr/metrics/MockHistogramSupplier.java
new file mode 100644
index 0000000..3df72af
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/metrics/MockHistogramSupplier.java
@@ -0,0 +1,40 @@
+/*
+ * 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.solr.metrics;
+
+import com.codahale.metrics.ExponentiallyDecayingReservoir;
+import com.codahale.metrics.Histogram;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.solr.core.PluginInfo;
+import org.apache.solr.util.plugin.PluginInfoInitialized;
+
+/**
+ *
+ */
+public class MockHistogramSupplier implements MetricRegistry.MetricSupplier<Histogram>, PluginInfoInitialized {
+ public PluginInfo info;
+
+ @Override
+ public Histogram newMetric() {
+ return new Histogram(new ExponentiallyDecayingReservoir());
+ }
+
+ @Override
+ public void init(PluginInfo info) {
+ this.info = info;
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/test/org/apache/solr/metrics/MockMeterSupplier.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/MockMeterSupplier.java b/solr/core/src/test/org/apache/solr/metrics/MockMeterSupplier.java
new file mode 100644
index 0000000..c035244
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/metrics/MockMeterSupplier.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.metrics;
+
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricRegistry;
+
+/**
+ *
+ */
+public class MockMeterSupplier implements MetricRegistry.MetricSupplier<Meter> {
+ public String foo;
+
+ public void setFoo(String foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public Meter newMetric() {
+ return new Meter();
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/test/org/apache/solr/metrics/MockTimerSupplier.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/MockTimerSupplier.java b/solr/core/src/test/org/apache/solr/metrics/MockTimerSupplier.java
new file mode 100644
index 0000000..aa400d9
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/metrics/MockTimerSupplier.java
@@ -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.solr.metrics;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Timer;
+
+/**
+ *
+ */
+public class MockTimerSupplier implements MetricRegistry.MetricSupplier<Timer> {
+ public boolean boolParam;
+ public String strParam;
+ public int intParam;
+
+ public void setBoolParam(boolean boolParam) {
+ this.boolParam = boolParam;
+ }
+
+ public void setStrParam(String strParam) {
+ this.strParam = strParam;
+ }
+
+ public void setIntParam(int intParam) {
+ this.intParam = intParam;
+ }
+
+ @Override
+ public Timer newMetric() {
+ return new Timer();
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
index 56dab37..a8e7ecd 100644
--- a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
@@ -86,7 +86,7 @@ public class SolrMetricsIntegrationTest extends SolrTestCaseJ4 {
cc.rename(DEFAULT_TEST_CORENAME, CORE_NAME);
h.coreName = CORE_NAME;
cfg = cc.getConfig();
- PluginInfo[] plugins = cfg.getMetricReporterPlugins();
+ PluginInfo[] plugins = cfg.getMetricsConfig().getMetricReporters();
assertNotNull(plugins);
assertEquals(10 + jmxReporter, plugins.length);
reporters = metricManager.getReporters("solr.node");
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/555a1496/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java b/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java
index cefd75f..4a6e90a 100644
--- a/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java
+++ b/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java
@@ -36,6 +36,7 @@ import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.CoreDescriptor;
import org.apache.solr.core.CorePropertiesLocator;
import org.apache.solr.core.CoresLocator;
+import org.apache.solr.core.MetricsConfig;
import org.apache.solr.core.NodeConfig;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrConfig;
@@ -197,12 +198,15 @@ public class TestHarness extends BaseTestHarness {
attributes.put("name", "default");
attributes.put("class", SolrJmxReporter.class.getName());
PluginInfo defaultPlugin = new PluginInfo("reporter", attributes);
+ MetricsConfig metricsConfig = new MetricsConfig.MetricsConfigBuilder()
+ .setMetricReporterPlugins(new PluginInfo[] {defaultPlugin})
+ .build();
return new NodeConfig.NodeConfigBuilder("testNode", loader)
.setUseSchemaCache(Boolean.getBoolean("shareSchema"))
.setCloudConfig(cloudConfig)
.setUpdateShardHandlerConfig(updateShardHandlerConfig)
- .setMetricReporterPlugins(new PluginInfo[] {defaultPlugin})
+ .setMetricsConfig(metricsConfig)
.build();
}