/*
* 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.reporters;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import com.codahale.metrics.MetricFilter;
import com.codahale.metrics.Slf4jReporter;
import org.apache.solr.metrics.SolrMetricManager;
import org.apache.solr.metrics.SolrMetricReporter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Metrics reporter that wraps {@link com.codahale.metrics.Slf4jReporter}.
* The following init arguments are supported:
* <ul>
* <li><code>period</code>: (optional, int) number of seconds between reports, default is 60,</li>
* <li><code>prefix</code>: (optional, str) prefix for metric names, in addition to
* registry name. Default is none, ie. just registry name.</li>
* <li><code>filter</code>: (optional, str) if not empty only metric names that start
* with this value will be reported, default is all metrics from a registry,</li>
* <li><code>logger</code>: (optional, str) logger name to use. Default is the
* metrics group, eg. <code>solr.jvm</code></li>
* </ul>
*/
public class SolrSlf4jReporter extends SolrMetricReporter {
// we need this to pass validate-source-patterns
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private int period = 60;
private String instancePrefix = null;
private String logger = null;
private List<String> filters = new ArrayList<>();
private Slf4jReporter reporter;
/**
* Create a SLF4J reporter for metrics managed in a named registry.
*
* @param metricManager metric manager instance that manages the selected registry
* @param registryName registry to use, one of registries managed by
* {@link SolrMetricManager}
*/
public SolrSlf4jReporter(SolrMetricManager metricManager, String registryName) {
super(metricManager, registryName);
}
public void setPrefix(String prefix) {
this.instancePrefix = prefix;
}
/**
* Report only metrics with names matching any of the prefix filters.
* @param filters list of 0 or more prefixes. If the list is empty then
* all names will match.
*/
public void setFilter(List<String> filters) {
if (filters == null || filters.isEmpty()) {
return;
}
this.filters.addAll(filters);
}
public void setFilter(String filter) {
if (filter != null && !filter.isEmpty()) {
this.filters.add(filter);
}
}
public void setLogger(String logger) {
this.logger = logger;
}
public void setPeriod(int period) {
this.period = period;
}
@Override
protected void validate() throws IllegalStateException {
if (!enabled) {
log.info("Reporter disabled for registry " + registryName);
return;
}
if (period < 1) {
throw new IllegalStateException("Init argument 'period' is in time unit 'seconds' and must be at least 1.");
}
if (instancePrefix == null) {
instancePrefix = registryName;
} else {
instancePrefix = instancePrefix + "." + registryName;
}
Slf4jReporter.Builder builder = Slf4jReporter
.forRegistry(metricManager.registry(registryName))
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS);
MetricFilter filter;
if (!filters.isEmpty()) {
filter = new SolrMetricManager.PrefixFilter(filters);
} else {
filter = MetricFilter.ALL;
}
builder = builder.filter(filter);
if (logger == null || logger.isEmpty()) {
// construct logger name from Group
if (pluginInfo.attributes.containsKey("group")) {
logger = SolrMetricManager.overridableRegistryName(pluginInfo.attributes.get("group"));
} else if (pluginInfo.attributes.containsKey("registry")) {
String reg = SolrMetricManager.overridableRegistryName(pluginInfo.attributes.get("registry"));
String[] names = reg.split("\\.");
if (names.length < 2) {
logger = reg;
} else {
logger = names[0] + "." + names[1];
}
}
}
builder = builder.outputTo(LoggerFactory.getLogger(logger));
reporter = builder.build();
reporter.start(period, TimeUnit.SECONDS);
}
@Override
public void close() throws IOException {
if (reporter != null) {
reporter.close();
}
}
}