4040import java .util .List ;
4141import java .util .Map ;
4242import java .util .SortedSet ;
43+ import java .util .concurrent .ConcurrentHashMap ;
44+ import java .util .concurrent .ConcurrentMap ;
4345import java .util .concurrent .ExecutorService ;
4446import java .util .concurrent .TimeUnit ;
4547import java .util .function .BiConsumer ;
@@ -64,30 +66,37 @@ public class MetricUtils {
6466 public static final String VALUE = "value" ;
6567 public static final String VALUES = "values" ;
6668
67- static final String MS = "_ms" ;
69+ private static final String MS = "_ms" ;
6870
69- static final String MIN = "min" ;
70- static final String MIN_MS = MIN + MS ;
71- static final String MAX = "max" ;
72- static final String MAX_MS = MAX + MS ;
73- static final String MEAN = "mean" ;
74- static final String MEAN_MS = MEAN + MS ;
75- static final String MEDIAN = "median" ;
76- static final String MEDIAN_MS = MEDIAN + MS ;
77- static final String STDDEV = "stddev" ;
78- static final String STDDEV_MS = STDDEV + MS ;
79- static final String SUM = "sum" ;
80- static final String P75 = "p75" ;
81- static final String P75_MS = P75 + MS ;
82- static final String P95 = "p95" ;
83- static final String P95_MS = P95 + MS ;
84- static final String P99 = "p99" ;
85- static final String P99_MS = P99 + MS ;
86- static final String P999 = "p999" ;
87- static final String P999_MS = P999 + MS ;
71+ private static final String MIN = "min" ;
72+ private static final String MIN_MS = MIN + MS ;
73+ private static final String MAX = "max" ;
74+ private static final String MAX_MS = MAX + MS ;
75+ private static final String MEAN = "mean" ;
76+ private static final String MEAN_MS = MEAN + MS ;
77+ private static final String MEDIAN = "median" ;
78+ private static final String MEDIAN_MS = MEDIAN + MS ;
79+ private static final String STDDEV = "stddev" ;
80+ private static final String STDDEV_MS = STDDEV + MS ;
81+ private static final String SUM = "sum" ;
82+ private static final String P75 = "p75" ;
83+ private static final String P75_MS = P75 + MS ;
84+ private static final String P95 = "p95" ;
85+ private static final String P95_MS = P95 + MS ;
86+ private static final String P99 = "p99" ;
87+ private static final String P99_MS = P99 + MS ;
88+ private static final String P999 = "p999" ;
89+ private static final String P999_MS = P999 + MS ;
8890
8991 public static final Predicate <CharSequence > ALL_PROPERTIES = (name ) -> true ;
9092
93+ /**
94+ * Local cache for BeanInfo instances that are created to scan for system metrics. List of
95+ * properties is not supposed to change for the JVM lifespan, so we can keep already create
96+ * BeanInfo instance for future calls.
97+ */
98+ private static final ConcurrentMap <Class <?>, BeanInfo > beanInfos = new ConcurrentHashMap <>();
99+
91100 /**
92101 * Adds metrics from a Timer to a NamedList, using well-known back-compat names.
93102 *
@@ -764,12 +773,21 @@ public static ExecutorService instrumentedExecutorService(
764773 public static <T extends PlatformManagedObject > void addMXBeanMetrics (
765774 T obj , Class <? extends T > intf , String prefix , BiConsumer <String , Metric > consumer ) {
766775 if (intf .isInstance (obj )) {
767- BeanInfo beanInfo ;
768- try {
769- beanInfo =
770- Introspector .getBeanInfo (intf , intf .getSuperclass (), Introspector .IGNORE_ALL_BEANINFO );
771- } catch (IntrospectionException e ) {
772- log .warn ("Unable to fetch properties of MXBean {}" , obj .getClass ().getName ());
776+ BeanInfo beanInfo =
777+ beanInfos .computeIfAbsent (
778+ intf ,
779+ clazz -> {
780+ try {
781+ return Introspector .getBeanInfo (
782+ clazz , clazz .getSuperclass (), Introspector .IGNORE_ALL_BEANINFO );
783+
784+ } catch (IntrospectionException e ) {
785+ log .warn ("Unable to fetch properties of MXBean {}" , obj .getClass ().getName ());
786+ return null ;
787+ }
788+ });
789+
790+ if (beanInfo == null ) {
773791 return ;
774792 }
775793 for (final PropertyDescriptor desc : beanInfo .getPropertyDescriptors ()) {
@@ -827,7 +845,7 @@ public static <T extends PlatformManagedObject> void addMXBeanMetrics(
827845 try {
828846 final Class <? extends PlatformManagedObject > intf =
829847 Class .forName (clazz ).asSubclass (PlatformManagedObject .class );
830- MetricUtils .addMXBeanMetrics (obj , intf , null , consumer );
848+ MetricUtils .addMXBeanMetrics (obj , intf , prefix , consumer );
831849 } catch (ClassNotFoundException e ) {
832850 // ignore
833851 }
0 commit comments