import static com.codahale.metrics.MetricRegistry.name; import java.lang.management.ManagementFactory; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.management.AttributeNotFoundException; import javax.management.InstanceNotFoundException; import javax.management.MBeanException; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.management.ReflectionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.codahale.metrics.Gauge; import com.codahale.metrics.JmxReporter; import com.codahale.metrics.Metric; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricSet; /** * Metrics for time since last successful exchange for camel routes . * Assumes managementNamePattern="#name#" */ public class RouteMetrics { private static final Logger log = LoggerFactory.getLogger(RouteMetrics.class); private final MetricRegistry metricsRegistry; private final JmxReporter jmxReporter; /** * @param routeNames * comma separated list of routes to instrument * * @throws NullPointerException * @throws IllegalArgumentException * @throws MalformedObjectNameException */ public RouteMetrics(String routeNames) { log.info("Setting up route metrics for ESB"); String[] routes = routeNames.split(","); metricsRegistry = new MetricRegistry(); metricsRegistry.registerAll(getRoutesMetricsSet(routes)); jmxReporter = JmxReporter.forRegistry(metricsRegistry).build(); jmxReporter.start(); log.info("Started JMX reporter for ESB route metrics"); } private MetricSet getRoutesMetricsSet(String... route) { final Map gauges = new HashMap(); for (final String routeName : route) { log.debug("Setting up gauges for {}", routeName); gauges.put(name("route", routeName, "secondsSinceLastSuccess"), new Gauge() { @Override public Long getValue() { Date lastExchange = (Date) getRouteAttribute(routeName, "LastExchangeCompletedTimestamp"); if (lastExchange != null) { long age = System.currentTimeMillis() - lastExchange.getTime(); return age / 1000; } return -100L; } }); } return new MetricSet() { @Override public Map getMetrics() { return Collections.unmodifiableMap(gauges); } }; } private static Object getRouteAttribute(String routeName, String AttributeName) { final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try { Iterator mbeanNames = mbs.queryNames(getObjectNamePattern(routeName), null).iterator(); if (mbeanNames.hasNext()) { ObjectName mbeanName = mbeanNames.next(); log.debug("Getting {} for: {}", AttributeName, mbeanName); Object value = mbs.getAttribute(mbeanName, AttributeName); return value; } log.warn("Route MBean not found for {}", routeName); } catch (AttributeNotFoundException e) { logWarning(e); } catch (InstanceNotFoundException e) { logWarning(e); } catch (MBeanException e) { logWarning(e); } catch (ReflectionException e) { logWarning(e); } catch (MalformedObjectNameException e) { logWarning(e); } catch (NullPointerException e) { logWarning(e); } return null; } private static ObjectName getObjectNamePattern(String routeName) throws MalformedObjectNameException, NullPointerException { StringBuilder sb = new StringBuilder("org.apache.camel:type=routes,name=\""); sb.append(routeName).append("\",*"); log.debug("ObjecNamePattern: {}", sb.toString()); return new ObjectName(sb.toString()); } private static void logWarning(Exception e) { log.warn("Exception while getting route metrics: {}", e.toString()); log.debug(e.toString(), e); }