Author: davsclaus Date: Fri Jun 8 14:10:49 2012 New Revision: 1348081 URL: http://svn.apache.org/viewvc?rev=1348081&view=rev Log: CAMEL-5101: CamelContext MBean now has aggregated performance stats from the routes.
Added: camel/trunk/camel-core/src/main/java/org/apache/camel/management/CompositePerformanceCounter.java camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedCanekContextExchangeStatisticsTest.java - copied, changed from r1347974, camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRegisterExchangeStatisticsTest.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java camel/trunk/camel-core/src/main/java/org/apache/camel/management/InstrumentationProcessor.java camel/trunk/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java?rev=1348081&r1=1348080&r2=1348081&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java Fri Jun 8 14:10:49 2012 @@ -22,7 +22,7 @@ import java.util.concurrent.TimeUnit; import org.apache.camel.api.management.ManagedAttribute; import org.apache.camel.api.management.ManagedOperation; -public interface ManagedCamelContextMBean { +public interface ManagedCamelContextMBean extends ManagedPerformanceCounterMBean { @ManagedAttribute(description = "Camel ID") String getCamelId(); Added: camel/trunk/camel-core/src/main/java/org/apache/camel/management/CompositePerformanceCounter.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/CompositePerformanceCounter.java?rev=1348081&view=auto ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/management/CompositePerformanceCounter.java (added) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/CompositePerformanceCounter.java Fri Jun 8 14:10:49 2012 @@ -0,0 +1,69 @@ +/** + * 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.camel.management; + +import org.apache.camel.Exchange; +import org.apache.camel.api.management.PerformanceCounter; + +/** + * A composite {@link PerformanceCounter} is used for tracking performance statistics on both a per + * context and route level, by issuing callbacks on both when an event happens. + * <p/> + * This implementation is used so the {@link org.apache.camel.management.mbean.ManagedCamelContext} + * can aggregate all stats from the routes. + */ +public class CompositePerformanceCounter implements PerformanceCounter { + + private final PerformanceCounter counter1; + private final PerformanceCounter counter2; + + public CompositePerformanceCounter(PerformanceCounter counter1, PerformanceCounter counter2) { + this.counter1 = counter1; + this.counter2 = counter2; + } + + @Override + public void completedExchange(Exchange exchange, long time) { + if (counter1.isStatisticsEnabled()) { + counter1.completedExchange(exchange, time); + } + if (counter2.isStatisticsEnabled()) { + counter2.completedExchange(exchange, time); + } + } + + @Override + public void failedExchange(Exchange exchange) { + if (counter1.isStatisticsEnabled()) { + counter1.failedExchange(exchange); + } + if (counter2.isStatisticsEnabled()) { + counter2.failedExchange(exchange); + } + } + + @Override + public boolean isStatisticsEnabled() { + // this method is not used + return true; + } + + @Override + public void setStatisticsEnabled(boolean statisticsEnabled) { + // this method is not used + } +} Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java?rev=1348081&r1=1348080&r2=1348081&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java Fri Jun 8 14:10:49 2012 @@ -51,10 +51,12 @@ import org.apache.camel.impl.EndpointReg import org.apache.camel.impl.EventDrivenConsumerRoute; import org.apache.camel.impl.ProducerCache; import org.apache.camel.impl.ThrottlingInflightRoutePolicy; +import org.apache.camel.management.mbean.ManagedCamelContext; import org.apache.camel.management.mbean.ManagedConsumerCache; import org.apache.camel.management.mbean.ManagedEndpoint; import org.apache.camel.management.mbean.ManagedEndpointRegistry; import org.apache.camel.management.mbean.ManagedProducerCache; +import org.apache.camel.management.mbean.ManagedRoute; import org.apache.camel.management.mbean.ManagedService; import org.apache.camel.management.mbean.ManagedThrottlingInflightRoutePolicy; import org.apache.camel.management.mbean.ManagedTracer; @@ -103,7 +105,8 @@ public class DefaultManagementLifecycleS new HashMap<Processor, KeyValueHolder<ProcessorDefinition<?>, InstrumentationProcessor>>(); private final List<PreRegisterService> preServices = new ArrayList<PreRegisterService>(); private final TimerListenerManager timerListenerManager = new TimerListenerManager(); - private CamelContext camelContext; + private volatile CamelContext camelContext; + private volatile ManagedCamelContext camelContextMBean; private volatile boolean initialized; private final Set<String> knowRouteIds = new HashSet<String>(); private final Map<Tracer, ManagedTracer> managedTracers = new HashMap<Tracer, ManagedTracer>(); @@ -183,6 +186,10 @@ public class DefaultManagementLifecycleS // yes we made it and are initialized initialized = true; + if (mc instanceof ManagedCamelContext) { + camelContextMBean = (ManagedCamelContext) mc; + } + // register any pre registered now that we are initialized enlistPreRegisteredServices(); } @@ -251,6 +258,8 @@ public class DefaultManagementLifecycleS } catch (Exception e) { LOG.warn("Could not unregister CamelContext MBean", e); } + + camelContextMBean = null; } public void onComponentAdd(String name, Component component) { @@ -493,9 +502,17 @@ public class DefaultManagementLifecycleS if (route instanceof EventDrivenConsumerRoute) { EventDrivenConsumerRoute edcr = (EventDrivenConsumerRoute) route; Processor processor = edcr.getProcessor(); - if (processor instanceof InstrumentationProcessor) { + if (processor instanceof InstrumentationProcessor && mr instanceof ManagedRoute) { InstrumentationProcessor ip = (InstrumentationProcessor) processor; - ip.setCounter(mr); + ManagedRoute routeMBean = (ManagedRoute) mr; + + // we need to wrap the counter with the camel context so we get stats updated on the context as well + if (camelContextMBean != null) { + CompositePerformanceCounter wrapper = new CompositePerformanceCounter(routeMBean, camelContextMBean); + ip.setCounter(wrapper); + } else { + ip.setCounter(routeMBean); + } } } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/InstrumentationProcessor.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/InstrumentationProcessor.java?rev=1348081&r1=1348080&r2=1348081&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/management/InstrumentationProcessor.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/InstrumentationProcessor.java Fri Jun 8 14:10:49 2012 @@ -58,8 +58,10 @@ public class InstrumentationProcessor ex if (this.counter instanceof DelegatePerformanceCounter) { ((DelegatePerformanceCounter) this.counter).setCounter(mpc); - } else { + } else if (mpc != null) { this.counter = mpc; + } else if (counter instanceof PerformanceCounter) { + this.counter = (PerformanceCounter) counter; } } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java?rev=1348081&r1=1348080&r2=1348081&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java Fri Jun 8 14:10:49 2012 @@ -30,6 +30,7 @@ import javax.management.ObjectName; import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; +import org.apache.camel.ManagementStatisticsLevel; import org.apache.camel.ProducerTemplate; import org.apache.camel.TimerListener; import org.apache.camel.api.management.ManagedResource; @@ -40,22 +41,19 @@ import org.apache.camel.model.ModelCamel import org.apache.camel.model.ModelHelper; import org.apache.camel.model.RouteDefinition; import org.apache.camel.model.RoutesDefinition; -import org.apache.camel.spi.ManagementStrategy; /** * @version */ @ManagedResource(description = "Managed CamelContext") -public class ManagedCamelContext implements TimerListener, ManagedCamelContextMBean { +public class ManagedCamelContext extends ManagedPerformanceCounter implements TimerListener, ManagedCamelContextMBean { private final ModelCamelContext context; private final LoadTriplet load = new LoadTriplet(); public ManagedCamelContext(ModelCamelContext context) { this.context = context; - } - - public void init(ManagementStrategy strategy) { - // do nothing + boolean enabled = context.getManagementStrategy().getStatisticsLevel() != ManagementStatisticsLevel.Off; + setStatisticsEnabled(enabled); } public CamelContext getContext() { @@ -241,7 +239,10 @@ public class ManagedCamelContext impleme @Override public String dumpRoutesStatsAsXml(boolean fullStats, boolean includeProcessors) throws Exception { StringBuilder sb = new StringBuilder(); - sb.append("<camelContextStat").append(String.format(" id=\"%s\"", getCamelId())).append(">\n"); + sb.append("<camelContextStat").append(String.format(" id=\"%s\"", getCamelId())); + // use substring as we only want the attributes + String stat = dumpStatsAsXml(fullStats); + sb.append(" ").append(stat.substring(7, stat.length() - 2)).append(">\n"); MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer(); if (server != null) { @@ -266,7 +267,7 @@ public class ManagedCamelContext impleme ManagedRouteMBean route = MBeanServerInvocationHandler.newProxyInstance(server, on, ManagedRouteMBean.class, true); sb.append(" <routeStat").append(String.format(" id=\"%s\"", route.getRouteId())); // use substring as we only want the attributes - String stat = route.dumpStatsAsXml(fullStats); + stat = route.dumpStatsAsXml(fullStats); sb.append(" ").append(stat.substring(7, stat.length() - 2)).append(">\n"); // add processor details if needed Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedCanekContextExchangeStatisticsTest.java (from r1347974, camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRegisterExchangeStatisticsTest.java) URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedCanekContextExchangeStatisticsTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedCanekContextExchangeStatisticsTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRegisterExchangeStatisticsTest.java&r1=1347974&r2=1348081&rev=1348081&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRegisterExchangeStatisticsTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedCanekContextExchangeStatisticsTest.java Fri Jun 8 14:10:49 2012 @@ -24,23 +24,50 @@ import org.apache.camel.builder.RouteBui /** * @version */ -public class ManagedRegisterExchangeStatisticsTest extends ManagementTestSupport { +public class ManagedCanekContextExchangeStatisticsTest extends ManagementTestSupport { public void testExchangesCompletedStatistics() throws Exception { MBeanServer mbeanServer = getMBeanServer(); - ObjectName on = ObjectName.getInstance("org.apache.camel:context=localhost/camel-1,type=routes,name=\"route1\""); + ObjectName on = ObjectName.getInstance("org.apache.camel:context=localhost/camel-1,type=context,name=\"camel-1\""); Long completed = (Long) mbeanServer.getAttribute(on, "ExchangesCompleted"); assertEquals(0, completed.longValue()); - getMockEndpoint("mock:result").expectedMessageCount(1); + ObjectName route1 = ObjectName.getInstance("org.apache.camel:context=localhost/camel-1,type=routes,name=\"route1\""); + Long completed1 = (Long) mbeanServer.getAttribute(route1, "ExchangesCompleted"); + assertEquals(0, completed1.longValue()); + + ObjectName route2 = ObjectName.getInstance("org.apache.camel:context=localhost/camel-1,type=routes,name=\"route2\""); + Long completed2 = (Long) mbeanServer.getAttribute(route1, "ExchangesCompleted"); + assertEquals(0, completed2.longValue()); + getMockEndpoint("mock:result").expectedMessageCount(1); template.sendBody("direct:start", "Hello World"); + assertMockEndpointsSatisfied(); + + completed = (Long) mbeanServer.getAttribute(route1, "ExchangesCompleted"); + assertEquals(1, completed.longValue()); + completed1 = (Long) mbeanServer.getAttribute(route1, "ExchangesCompleted"); + assertEquals(1, completed1.longValue()); + + completed2 = (Long) mbeanServer.getAttribute(route2, "ExchangesCompleted"); + assertEquals(0, completed2.longValue()); + + resetMocks(); + getMockEndpoint("mock:result").expectedMessageCount(2); + template.sendBody("direct:start", "Hi World"); + template.sendBody("direct:bar", "Bye World"); assertMockEndpointsSatisfied(); completed = (Long) mbeanServer.getAttribute(on, "ExchangesCompleted"); - assertEquals(1, completed.longValue()); + assertEquals(3, completed.longValue()); + + completed1 = (Long) mbeanServer.getAttribute(route1, "ExchangesCompleted"); + assertEquals(2, completed1.longValue()); + + completed2 = (Long) mbeanServer.getAttribute(route2, "ExchangesCompleted"); + assertEquals(1, completed2.longValue()); } @Override @@ -48,7 +75,13 @@ public class ManagedRegisterExchangeStat return new RouteBuilder() { @Override public void configure() throws Exception { - from("direct:start").to("log:foo").to("mock:result"); + from("direct:start") + .routeId("route1") + .to("log:foo").to("mock:result"); + + from("direct:bar") + .routeId("route2") + .to("log:bar").to("mock:result"); } }; }