From 2ad1563032dbca72dba3b46bf92c3b99be8b4b10 Mon Sep 17 00:00:00 2001 From: Bela Ban Date: Sat, 27 Apr 2024 12:34:48 +0200 Subject: [PATCH] - ResourceDMBean now accepts filters (JGRP-2796) --- src/org/jgroups/jmx/ResourceDMBean.java | 28 ++++++++++++---- src/org/jgroups/util/ExtractMetrics.java | 42 +++++++++++++++++++----- 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/org/jgroups/jmx/ResourceDMBean.java b/src/org/jgroups/jmx/ResourceDMBean.java index 977ddaa201..1f152f9f54 100755 --- a/src/org/jgroups/jmx/ResourceDMBean.java +++ b/src/org/jgroups/jmx/ResourceDMBean.java @@ -7,6 +7,7 @@ import org.jgroups.conf.AttributeType; import org.jgroups.logging.Log; import org.jgroups.logging.LogFactory; +import org.jgroups.util.Average; import org.jgroups.util.Util; import javax.management.*; @@ -54,16 +55,19 @@ public class ResourceDMBean implements DynamicMBean { protected static final Predicate FILTER=obj -> obj.isAnnotationPresent(ManagedAttribute.class) || (obj.isAnnotationPresent(Property.class) && obj.getAnnotation(Property.class).exposeAsManagedAttribute()); - public ResourceDMBean(Object instance) { + this(instance, null); + } + + public ResourceDMBean(Object instance, Predicate filter) { if(instance == null) throw new NullPointerException("Cannot make an MBean wrapper for null instance"); this.obj=instance; Class c=obj.getClass(); expose_all=c.isAnnotationPresent(MBean.class) && c.getAnnotation(MBean.class).exposeAll(); - findFields(instance); - findMethods(instance); + findFields(instance, filter); + findMethods(instance, filter); fixFields(instance); List objects=Util.getComponents(instance); @@ -73,8 +77,8 @@ public ResourceDMBean(Object instance) { if(objs == null) objs=new ArrayList<>(); objs.add(inst); - findFields(inst); - findMethods(inst); + findFields(inst, filter); + findMethods(inst, filter); fixFields(inst); } } @@ -273,6 +277,10 @@ public static boolean isFractional(Class cl) { return cl.equals(float.class) || cl.equals(Float.class) || cl.equals(double.class) || cl.equals(Double.class); } + public static boolean isNumber(Class cl) { + return isNumeric(cl) || isFractional(cl) || Number.class.isAssignableFrom(cl) || Average.class.isAssignableFrom(cl); + } + protected static AttributeType getType(AccessibleObject ao) { Property prop=ao.getAnnotation(Property.class); @@ -306,14 +314,17 @@ protected static Class getClassForName(String name) throws ClassNotFoundExcep throw new ClassNotFoundException("Class " + name + " cannot be found"); } - protected void findMethods(Object instance) { + protected void findMethods(Object instance, Predicate filter) { // find all methods but don't include methods from Object class List methods = new ArrayList<>(Arrays.asList(instance.getClass().getMethods())); methods.removeAll(OBJECT_METHODS); for(Method method: methods) { + // does method have @ManagedAttribute annotation? if(method.isAnnotationPresent(ManagedAttribute.class) || method.isAnnotationPresent(Property.class)) { + if(filter != null && !filter.test(method)) + continue; exposeManagedAttribute(method, instance); } //or @ManagedOperation @@ -461,12 +472,15 @@ protected static String toLowerCase(String input) { } - protected void findFields(Object instance) { + protected void findFields(Object instance, Predicate filter) { // traverse class hierarchy and find all annotated fields for(Class clazz=instance.getClass(); clazz != null && clazz != Object.class; clazz=clazz.getSuperclass()) { Field[] fields=clazz.getDeclaredFields(); for(Field field: fields) { + if(filter != null && !filter.test(field)) + continue; + ManagedAttribute attr=field.getAnnotation(ManagedAttribute.class); Property prop=field.getAnnotation(Property.class); boolean expose_prop=prop != null && prop.exposeAsManagedAttribute(); diff --git a/src/org/jgroups/util/ExtractMetrics.java b/src/org/jgroups/util/ExtractMetrics.java index 2cebf32063..9330fe0707 100644 --- a/src/org/jgroups/util/ExtractMetrics.java +++ b/src/org/jgroups/util/ExtractMetrics.java @@ -5,8 +5,12 @@ import org.jgroups.stack.Protocol; import javax.management.MBeanAttributeInfo; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; +import java.util.function.Predicate; import java.util.function.Supplier; /** @@ -18,9 +22,19 @@ */ public class ExtractMetrics { protected JChannel ch; + protected static final Predicate IS_NUMBER=obj -> { + if(obj instanceof Field) + return ResourceDMBean.isNumber(((Field)obj).getType()); + if(obj instanceof Method) { + Method m=(Method)obj; + return ResourceDMBean.isNumber(m.getReturnType()); + } + return false; + }; + public static class Entry { - protected final String description; + protected final String description; protected final Supplier method; protected Entry(String description, Supplier method) { @@ -43,18 +57,24 @@ public String toString() { } public static Map> extract(JChannel ch) { + return extract(ch, null); + } + + public static Map> extract(JChannel ch, Predicate filter) { Map> map=new HashMap<>(); for(Protocol p: ch.stack().getProtocols()) { - map.put(p.getName(), extract(p)); + map.put(p.getName(), extract(p, filter)); } return map; } - public static Map extract(Protocol p) { - Map map=new HashMap<>(); + return extract(p, null); + } - ResourceDMBean dm=new ResourceDMBean(p); + public static Map extract(Protocol p, Predicate filter) { + Map map=new HashMap<>(); + ResourceDMBean dm=new ResourceDMBean(p, filter); dm.forAllAttributes((k,v) -> { MBeanAttributeInfo info=v.info(); String descr=info != null? info.getDescription() : "n/a"; @@ -73,20 +93,24 @@ public static Map extract(Protocol p) { return map; } - protected void start() throws Exception { + protected void start(boolean numeric) throws Exception { ch=new JChannel().connect("bla").name("X"); - Map> map=extract(ch); + Map> map=extract(ch, IS_NUMBER); for(Map.Entry> e: map.entrySet()) { System.out.printf("\n%s:\n---------------\n", e.getKey()); for(Map.Entry e2: e.getValue().entrySet()) { - System.out.printf(" %s: %s\n", e2.getKey(), e2.getValue()); + Entry entry=e2.getValue(); + Supplier s=entry.getMethod(); + if(s != null) + System.out.printf(" %s: %s\n", e2.getKey(), s.get()); } } Util.close(ch); } public static void main(String[] args) throws Throwable { - new ExtractMetrics().start(); + boolean numeric=args.length > 0 && Boolean.parseBoolean(args[0]); + new ExtractMetrics().start(numeric); } }