mirror of https://github.com/apache/lucene.git
SOLR-10262: Add support for configurable metrics implementations.
This commit is contained in:
parent
d59faafd89
commit
3217fd7c3c
|
@ -88,6 +88,8 @@ New Features
|
|||
* SOLR-10547: JSON Facet API: Implement support for single-valued string fields for min/max aggregations.
|
||||
(yonik)
|
||||
|
||||
* SOLR-10262: Add support for configurable metrics implementations. (ab)
|
||||
|
||||
Bug Fixes
|
||||
----------------------
|
||||
* SOLR-9262: Connection and read timeouts are being ignored by UpdateShardHandler after SOLR-4509.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<>();
|
||||
|
|
|
@ -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 Timer 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 Histogram 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;
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -196,7 +196,7 @@ public class SolrDispatchFilter extends BaseSolrFilter {
|
|||
|
||||
private void setupJvmMetrics(CoreContainer coresInit) {
|
||||
SolrMetricManager metricManager = coresInit.getMetricManager();
|
||||
final Set<String> hiddenSysProps = coresInit.getConfig().getHiddenSysProps();
|
||||
final Set<String> hiddenSysProps = coresInit.getConfig().getMetricsConfig().getHiddenSysProps();
|
||||
try {
|
||||
String registry = SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm);
|
||||
metricManager.registerAll(registry, new AltBufferPoolMetricSet(), true, "buffers");
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
|
@ -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));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue