Skip to content

Commit

Permalink
SOLR-17340: /admin/info/system optimization by caching BeanInfo (#2538)
Browse files Browse the repository at this point in the history
Note the prefix arg was always null, thus this one-line change is just a refactoring for correctness.
  • Loading branch information
psalagnac authored Jul 22, 2024
1 parent a439ebf commit 0da7a78
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 27 deletions.
2 changes: 2 additions & 0 deletions solr/CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ Optimizations

* SOLR-17349: SolrDocumentFetcher should always skip lazy field loading overhead if documentCache==null (Michael Gibney)

* SOLR-17340: Add cache on top of system metrics BeanInfos to make calls to /admin/info/system faster (Pierre Salagnac)

Bug Fixes
---------------------
* SOLR-12813: subqueries should respect basic auth. (Rudy Seitz via Eric Pugh)
Expand Down
72 changes: 45 additions & 27 deletions solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
Expand All @@ -64,30 +66,37 @@ public class MetricUtils {
public static final String VALUE = "value";
public static final String VALUES = "values";

static final String MS = "_ms";
private static final String MS = "_ms";

static final String MIN = "min";
static final String MIN_MS = MIN + MS;
static final String MAX = "max";
static final String MAX_MS = MAX + MS;
static final String MEAN = "mean";
static final String MEAN_MS = MEAN + MS;
static final String MEDIAN = "median";
static final String MEDIAN_MS = MEDIAN + MS;
static final String STDDEV = "stddev";
static final String STDDEV_MS = STDDEV + MS;
static final String SUM = "sum";
static final String P75 = "p75";
static final String P75_MS = P75 + MS;
static final String P95 = "p95";
static final String P95_MS = P95 + MS;
static final String P99 = "p99";
static final String P99_MS = P99 + MS;
static final String P999 = "p999";
static final String P999_MS = P999 + MS;
private static final String MIN = "min";
private static final String MIN_MS = MIN + MS;
private static final String MAX = "max";
private static final String MAX_MS = MAX + MS;
private static final String MEAN = "mean";
private static final String MEAN_MS = MEAN + MS;
private static final String MEDIAN = "median";
private static final String MEDIAN_MS = MEDIAN + MS;
private static final String STDDEV = "stddev";
private static final String STDDEV_MS = STDDEV + MS;
private static final String SUM = "sum";
private static final String P75 = "p75";
private static final String P75_MS = P75 + MS;
private static final String P95 = "p95";
private static final String P95_MS = P95 + MS;
private static final String P99 = "p99";
private static final String P99_MS = P99 + MS;
private static final String P999 = "p999";
private static final String P999_MS = P999 + MS;

public static final Predicate<CharSequence> ALL_PROPERTIES = (name) -> true;

/**
* Local cache for BeanInfo instances that are created to scan for system metrics. List of
* properties is not supposed to change for the JVM lifespan, so we can keep already create
* BeanInfo instance for future calls.
*/
private static final ConcurrentMap<Class<?>, BeanInfo> beanInfos = new ConcurrentHashMap<>();

/**
* Adds metrics from a Timer to a NamedList, using well-known back-compat names.
*
Expand Down Expand Up @@ -764,12 +773,21 @@ public static ExecutorService instrumentedExecutorService(
public static <T extends PlatformManagedObject> void addMXBeanMetrics(
T obj, Class<? extends T> intf, String prefix, BiConsumer<String, Metric> consumer) {
if (intf.isInstance(obj)) {
BeanInfo beanInfo;
try {
beanInfo =
Introspector.getBeanInfo(intf, intf.getSuperclass(), Introspector.IGNORE_ALL_BEANINFO);
} catch (IntrospectionException e) {
log.warn("Unable to fetch properties of MXBean {}", obj.getClass().getName());
BeanInfo beanInfo =
beanInfos.computeIfAbsent(
intf,
clazz -> {
try {
return Introspector.getBeanInfo(
clazz, clazz.getSuperclass(), Introspector.IGNORE_ALL_BEANINFO);

} catch (IntrospectionException e) {
log.warn("Unable to fetch properties of MXBean {}", obj.getClass().getName());
return null;
}
});

if (beanInfo == null) {
return;
}
for (final PropertyDescriptor desc : beanInfo.getPropertyDescriptors()) {
Expand Down Expand Up @@ -827,7 +845,7 @@ public static <T extends PlatformManagedObject> void addMXBeanMetrics(
try {
final Class<? extends PlatformManagedObject> intf =
Class.forName(clazz).asSubclass(PlatformManagedObject.class);
MetricUtils.addMXBeanMetrics(obj, intf, null, consumer);
MetricUtils.addMXBeanMetrics(obj, intf, prefix, consumer);
} catch (ClassNotFoundException e) {
// ignore
}
Expand Down

0 comments on commit 0da7a78

Please sign in to comment.