001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.management.mbean; 018 019import java.io.ByteArrayInputStream; 020import java.util.ArrayList; 021import java.util.Collection; 022import java.util.Comparator; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026import java.util.concurrent.TimeUnit; 027 028import javax.management.MBeanServer; 029import javax.management.ObjectName; 030 031import org.w3c.dom.Document; 032 033import org.apache.camel.CamelContext; 034import org.apache.camel.Endpoint; 035import org.apache.camel.Exchange; 036import org.apache.camel.ManagementStatisticsLevel; 037import org.apache.camel.Producer; 038import org.apache.camel.ProducerTemplate; 039import org.apache.camel.Route; 040import org.apache.camel.TimerListener; 041import org.apache.camel.api.management.ManagedResource; 042import org.apache.camel.api.management.mbean.ManagedCamelContextMBean; 043import org.apache.camel.api.management.mbean.ManagedProcessorMBean; 044import org.apache.camel.api.management.mbean.ManagedRouteMBean; 045import org.apache.camel.api.management.mbean.ManagedStepMBean; 046import org.apache.camel.model.Model; 047import org.apache.camel.model.RouteDefinition; 048import org.apache.camel.model.RouteTemplateDefinition; 049import org.apache.camel.model.RouteTemplatesDefinition; 050import org.apache.camel.model.RoutesDefinition; 051import org.apache.camel.model.rest.RestDefinition; 052import org.apache.camel.model.rest.RestsDefinition; 053import org.apache.camel.spi.ManagementStrategy; 054import org.apache.camel.spi.UnitOfWork; 055import org.apache.camel.support.CamelContextHelper; 056import org.apache.camel.support.PluginHelper; 057import org.apache.camel.util.json.JsonArray; 058import org.apache.camel.util.json.JsonObject; 059 060@ManagedResource(description = "Managed CamelContext") 061public class ManagedCamelContext extends ManagedPerformanceCounter implements TimerListener, ManagedCamelContextMBean { 062 063 private final CamelContext context; 064 private final LoadTriplet load = new LoadTriplet(); 065 private final LoadThroughput thp = new LoadThroughput(); 066 private final String jmxDomain; 067 private final boolean includeRouteTemplates; 068 private final boolean includeKamelets; 069 private Statistic remoteExchangesTotal; 070 private Statistic remoteExchangesCompleted; 071 private Statistic remoteExchangesFailed; 072 private Statistic remoteExchangesInflight; 073 074 public ManagedCamelContext(CamelContext context) { 075 this.context = context; 076 this.jmxDomain = context.getManagementStrategy().getManagementAgent().getMBeanObjectDomainName(); 077 this.includeRouteTemplates = context.getManagementStrategy().getManagementAgent().getRegisterRoutesCreateByTemplate(); 078 this.includeKamelets = context.getManagementStrategy().getManagementAgent().getRegisterRoutesCreateByKamelet(); 079 } 080 081 @Override 082 public void init(ManagementStrategy strategy) { 083 super.init(strategy); 084 this.remoteExchangesTotal = new StatisticCounter(); 085 this.remoteExchangesCompleted = new StatisticCounter(); 086 this.remoteExchangesFailed = new StatisticCounter(); 087 this.remoteExchangesInflight = new StatisticCounter(); 088 boolean enabled = context.getManagementStrategy().getManagementAgent() != null 089 && context.getManagementStrategy().getManagementAgent().getStatisticsLevel() != ManagementStatisticsLevel.Off; 090 setStatisticsEnabled(enabled); 091 } 092 093 @Override 094 public void reset() { 095 super.reset(); 096 remoteExchangesTotal.reset(); 097 remoteExchangesCompleted.reset(); 098 remoteExchangesFailed.reset(); 099 remoteExchangesInflight.reset(); 100 } 101 102 @Override 103 public void completedExchange(Exchange exchange, long time) { 104 // the camel-context mbean is triggered for every route mbean 105 // so we must only trigger on the root level, otherwise the context mbean 106 // total counter will be incorrect. For example if an exchange is routed via 3 routes 107 // we should only count this as 1 instead of 3. 108 UnitOfWork uow = exchange.getUnitOfWork(); 109 if (uow != null) { 110 int level = uow.routeStackLevel(includeRouteTemplates, includeKamelets); 111 if (level <= 1) { 112 super.completedExchange(exchange, time); 113 if (exchange.getFromEndpoint() != null && exchange.getFromEndpoint().isRemote()) { 114 remoteExchangesTotal.increment(); 115 remoteExchangesCompleted.increment(); 116 remoteExchangesInflight.decrement(); 117 } 118 } 119 } else { 120 super.completedExchange(exchange, time); 121 if (exchange.getFromEndpoint() != null && exchange.getFromEndpoint().isRemote()) { 122 remoteExchangesTotal.increment(); 123 remoteExchangesCompleted.increment(); 124 remoteExchangesInflight.decrement(); 125 } 126 } 127 } 128 129 @Override 130 public void failedExchange(Exchange exchange) { 131 // the camel-context mbean is triggered for every route mbean 132 // so we must only trigger on the root level, otherwise the context mbean 133 // total counter will be incorrect. For example if an exchange is routed via 3 routes 134 // we should only count this as 1 instead of 3. 135 UnitOfWork uow = exchange.getUnitOfWork(); 136 if (uow != null) { 137 int level = uow.routeStackLevel(includeRouteTemplates, includeKamelets); 138 if (level <= 1) { 139 super.failedExchange(exchange); 140 if (exchange.getFromEndpoint() != null && exchange.getFromEndpoint().isRemote()) { 141 remoteExchangesTotal.increment(); 142 remoteExchangesFailed.increment(); 143 remoteExchangesInflight.decrement(); 144 } 145 } 146 } else { 147 super.failedExchange(exchange); 148 if (exchange.getFromEndpoint() != null && exchange.getFromEndpoint().isRemote()) { 149 remoteExchangesTotal.increment(); 150 remoteExchangesFailed.increment(); 151 remoteExchangesInflight.decrement(); 152 } 153 } 154 } 155 156 @Override 157 public void processExchange(Exchange exchange, String type) { 158 // the camel-context mbean is triggered for every route mbean 159 // so we must only trigger on the root level, otherwise the context mbean 160 // total counter will be incorrect. For example if an exchange is routed via 3 routes 161 // we should only count this as 1 instead of 3. 162 UnitOfWork uow = exchange.getUnitOfWork(); 163 if (uow != null) { 164 int level = uow.routeStackLevel(includeRouteTemplates, includeKamelets); 165 if (level <= 1) { 166 super.processExchange(exchange, type); 167 if (exchange.getFromEndpoint() != null && exchange.getFromEndpoint().isRemote()) { 168 remoteExchangesInflight.increment(); 169 } 170 } 171 } else { 172 super.processExchange(exchange, type); 173 if (exchange.getFromEndpoint() != null && exchange.getFromEndpoint().isRemote()) { 174 remoteExchangesInflight.increment(); 175 } 176 } 177 } 178 179 public CamelContext getContext() { 180 return context; 181 } 182 183 @Override 184 public String getCamelId() { 185 return context.getName(); 186 } 187 188 @Override 189 public String getCamelDescription() { 190 return context.getDescription(); 191 } 192 193 @Override 194 public String getManagementName() { 195 return context.getManagementName(); 196 } 197 198 @Override 199 public String getCamelVersion() { 200 return context.getVersion(); 201 } 202 203 @Override 204 public String getProfile() { 205 return context.getCamelContextExtension().getProfile(); 206 } 207 208 @Override 209 public Boolean getAutoStartup() { 210 return context.isAutoStartup(); 211 } 212 213 @Override 214 public String getAutoStartupExcludePattern() { 215 return context.getAutoStartupExcludePattern(); 216 } 217 218 @Override 219 public String getState() { 220 return context.getStatus().name(); 221 } 222 223 @Override 224 public String getUptime() { 225 return CamelContextHelper.getUptime(context); 226 } 227 228 @Override 229 public long getUptimeMillis() { 230 return context.getUptime().toMillis(); 231 } 232 233 @Override 234 public String getManagementStatisticsLevel() { 235 if (context.getManagementStrategy().getManagementAgent() != null) { 236 return context.getManagementStrategy().getManagementAgent().getStatisticsLevel().name(); 237 } else { 238 return null; 239 } 240 } 241 242 @Override 243 public String getClassResolver() { 244 return context.getClassResolver().getClass().getName(); 245 } 246 247 @Override 248 public String getPackageScanClassResolver() { 249 return PluginHelper.getPackageScanClassResolver(context).getClass().getName(); 250 } 251 252 @Override 253 public String getApplicationContextClassName() { 254 if (context.getApplicationContextClassLoader() != null) { 255 return context.getApplicationContextClassLoader().getClass().getName(); 256 } else { 257 return null; 258 } 259 } 260 261 @Override 262 public String getHeadersMapFactoryClassName() { 263 return context.getCamelContextExtension().getHeadersMapFactory().getClass().getName(); 264 } 265 266 @Override 267 public String getAdditionalSensitiveKeywords() { 268 return context.getCamelContextExtension().getAdditionalSensitiveKeywords(); 269 } 270 271 @Override 272 public Map<String, String> getGlobalOptions() { 273 if (context.getGlobalOptions().isEmpty()) { 274 return null; 275 } 276 return context.getGlobalOptions(); 277 } 278 279 @Override 280 public String getGlobalOption(String key) throws Exception { 281 return context.getGlobalOption(key); 282 } 283 284 @Override 285 public void setGlobalOption(String key, String value) throws Exception { 286 context.getGlobalOptions().put(key, value); 287 } 288 289 @Override 290 public Boolean getTracing() { 291 return context.isTracing(); 292 } 293 294 @Override 295 public void setTracing(Boolean tracing) { 296 context.setTracing(tracing); 297 } 298 299 public Integer getInflightExchanges() { 300 return (int) super.getExchangesInflight(); 301 } 302 303 @Override 304 public Integer getTotalRoutes() { 305 return context.getRoutesSize(); 306 } 307 308 @Override 309 public Integer getStartedRoutes() { 310 int started = 0; 311 for (Route route : context.getRoutes()) { 312 if (context.getRouteController().getRouteStatus(route.getId()).isStarted()) { 313 started++; 314 } 315 } 316 return started; 317 } 318 319 @Override 320 public void setTimeout(long timeout) { 321 context.getShutdownStrategy().setTimeout(timeout); 322 } 323 324 @Override 325 public long getTimeout() { 326 return context.getShutdownStrategy().getTimeout(); 327 } 328 329 @Override 330 public void setTimeUnit(TimeUnit timeUnit) { 331 context.getShutdownStrategy().setTimeUnit(timeUnit); 332 } 333 334 @Override 335 public TimeUnit getTimeUnit() { 336 return context.getShutdownStrategy().getTimeUnit(); 337 } 338 339 @Override 340 public void setShutdownNowOnTimeout(boolean shutdownNowOnTimeout) { 341 context.getShutdownStrategy().setShutdownNowOnTimeout(shutdownNowOnTimeout); 342 } 343 344 @Override 345 public boolean isShutdownNowOnTimeout() { 346 return context.getShutdownStrategy().isShutdownNowOnTimeout(); 347 } 348 349 @Override 350 public String getLoad01() { 351 double load1 = load.getLoad1(); 352 if (Double.isNaN(load1)) { 353 // empty string if load statistics is disabled 354 return ""; 355 } else { 356 return String.format("%.2f", load1); 357 } 358 } 359 360 @Override 361 public String getLoad05() { 362 double load5 = load.getLoad5(); 363 if (Double.isNaN(load5)) { 364 // empty string if load statistics is disabled 365 return ""; 366 } else { 367 return String.format("%.2f", load5); 368 } 369 } 370 371 @Override 372 public String getLoad15() { 373 double load15 = load.getLoad15(); 374 if (Double.isNaN(load15)) { 375 // empty string if load statistics is disabled 376 return ""; 377 } else { 378 return String.format("%.2f", load15); 379 } 380 } 381 382 @Override 383 public String getThroughput() { 384 double d = thp.getThroughput(); 385 if (Double.isNaN(d)) { 386 // empty string if load statistics is disabled 387 return ""; 388 } else { 389 return String.format("%.2f", d); 390 } 391 } 392 393 @Override 394 public long getRemoteExchangesTotal() { 395 return remoteExchangesTotal.getValue(); 396 } 397 398 @Override 399 public long getRemoteExchangesCompleted() { 400 return remoteExchangesCompleted.getValue(); 401 } 402 403 @Override 404 public long getRemoteExchangesFailed() { 405 return remoteExchangesFailed.getValue(); 406 } 407 408 @Override 409 public long getRemoteExchangesInflight() { 410 return remoteExchangesInflight.getValue(); 411 } 412 413 @Override 414 public boolean isUseBreadcrumb() { 415 return context.isUseBreadcrumb(); 416 } 417 418 @Override 419 public boolean isAllowUseOriginalMessage() { 420 return context.isAllowUseOriginalMessage(); 421 } 422 423 @Override 424 public boolean isMessageHistory() { 425 return context.isMessageHistory() != null ? context.isMessageHistory() : false; 426 } 427 428 @Override 429 public boolean isLogMask() { 430 return context.isLogMask() != null ? context.isLogMask() : false; 431 } 432 433 @Override 434 public boolean isUseMDCLogging() { 435 return context.isUseMDCLogging(); 436 } 437 438 @Override 439 public boolean isUseDataType() { 440 return context.isUseDataType(); 441 } 442 443 @Override 444 public void onTimer() { 445 load.update(getInflightExchanges()); 446 thp.update(getExchangesTotal()); 447 } 448 449 @Override 450 public void start() throws Exception { 451 if (context.isSuspended()) { 452 context.resume(); 453 } else { 454 context.start(); 455 } 456 } 457 458 @Override 459 public void stop() throws Exception { 460 context.stop(); 461 } 462 463 @Override 464 public void restart() throws Exception { 465 context.stop(); 466 context.start(); 467 } 468 469 @Override 470 public void suspend() throws Exception { 471 context.suspend(); 472 } 473 474 @Override 475 public void resume() throws Exception { 476 if (context.isSuspended()) { 477 context.resume(); 478 } else { 479 throw new IllegalStateException("CamelContext is not suspended"); 480 } 481 } 482 483 @Override 484 public void startAllRoutes() throws Exception { 485 context.getRouteController().startAllRoutes(); 486 } 487 488 @Override 489 public boolean canSendToEndpoint(String endpointUri) { 490 try { 491 Endpoint endpoint = context.getEndpoint(endpointUri); 492 if (endpoint != null) { 493 try (Producer producer = endpoint.createProducer()) { 494 return producer != null; 495 } 496 } 497 } catch (Exception e) { 498 // ignore 499 } 500 501 return false; 502 } 503 504 @Override 505 public void sendBody(String endpointUri, Object body) throws Exception { 506 try (ProducerTemplate template = context.createProducerTemplate()) { 507 template.sendBody(endpointUri, body); 508 } 509 } 510 511 @Override 512 public void sendStringBody(String endpointUri, String body) throws Exception { 513 sendBody(endpointUri, body); 514 } 515 516 @Override 517 public void sendBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers) throws Exception { 518 try (ProducerTemplate template = context.createProducerTemplate()) { 519 template.sendBodyAndHeaders(endpointUri, body, headers); 520 } 521 } 522 523 @Override 524 public Object requestBody(String endpointUri, Object body) throws Exception { 525 try (ProducerTemplate template = context.createProducerTemplate()) { 526 return template.requestBody(endpointUri, body); 527 } 528 } 529 530 @Override 531 public Object requestStringBody(String endpointUri, String body) throws Exception { 532 return requestBody(endpointUri, body); 533 } 534 535 @Override 536 public Object requestBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers) throws Exception { 537 try (ProducerTemplate template = context.createProducerTemplate()) { 538 return template.requestBodyAndHeaders(endpointUri, body, headers); 539 } 540 } 541 542 @Override 543 public String dumpRestsAsXml() throws Exception { 544 return dumpRestsAsXml(false); 545 } 546 547 @Override 548 public String dumpRestsAsXml(boolean resolvePlaceholders) throws Exception { 549 List<RestDefinition> rests = context.getCamelContextExtension().getContextPlugin(Model.class).getRestDefinitions(); 550 if (rests.isEmpty()) { 551 return null; 552 } 553 554 RestsDefinition def = new RestsDefinition(); 555 def.setRests(rests); 556 557 return PluginHelper.getModelToXMLDumper(context).dumpModelAsXml(context, def, resolvePlaceholders, true, false); 558 } 559 560 @Override 561 public String dumpRoutesAsXml() throws Exception { 562 return dumpRoutesAsXml(false, true); 563 } 564 565 @Override 566 public String dumpRoutesAsXml(boolean resolvePlaceholders) throws Exception { 567 return dumpRoutesAsXml(resolvePlaceholders, true); 568 } 569 570 @Override 571 public String dumpRoutesAsXml(boolean resolvePlaceholders, boolean generatedIds) throws Exception { 572 return dumpRoutesAsXml(resolvePlaceholders, true, false); 573 } 574 575 @Override 576 public String dumpRoutesAsXml(boolean resolvePlaceholders, boolean generatedIds, boolean sourceLocation) throws Exception { 577 List<RouteDefinition> routes = context.getCamelContextExtension().getContextPlugin(Model.class).getRouteDefinitions(); 578 if (routes.isEmpty()) { 579 return null; 580 } 581 582 // use routes definition to dump the routes 583 RoutesDefinition def = new RoutesDefinition(); 584 def.setRoutes(routes); 585 586 // if we are debugging then ids is needed for the debugger 587 if (context.isDebugging()) { 588 generatedIds = true; 589 } 590 return PluginHelper.getModelToXMLDumper(context).dumpModelAsXml(context, def, resolvePlaceholders, generatedIds, 591 sourceLocation); 592 } 593 594 @Override 595 public String dumpRoutesAsYaml() throws Exception { 596 return dumpRoutesAsYaml(false, false); 597 } 598 599 @Override 600 public String dumpRoutesAsYaml(boolean resolvePlaceholders) throws Exception { 601 return dumpRoutesAsYaml(resolvePlaceholders, false, true); 602 } 603 604 @Override 605 public String dumpRoutesAsYaml(boolean resolvePlaceholders, boolean uriAsParameters) throws Exception { 606 return dumpRoutesAsYaml(resolvePlaceholders, uriAsParameters, true); 607 } 608 609 @Override 610 public String dumpRoutesAsYaml(boolean resolvePlaceholders, boolean uriAsParameters, boolean generatedIds) 611 throws Exception { 612 return dumpRoutesAsYaml(resolvePlaceholders, uriAsParameters, true, false); 613 } 614 615 @Override 616 public String dumpRoutesAsYaml( 617 boolean resolvePlaceholders, boolean uriAsParameters, boolean generatedIds, boolean sourceLocation) 618 throws Exception { 619 List<RouteDefinition> routes = context.getCamelContextExtension().getContextPlugin(Model.class).getRouteDefinitions(); 620 if (routes.isEmpty()) { 621 return null; 622 } 623 624 // use routes definition to dump the routes 625 RoutesDefinition def = new RoutesDefinition(); 626 def.setRoutes(routes); 627 628 // if we are debugging then ids is needed for the debugger 629 if (context.isDebugging()) { 630 generatedIds = true; 631 } 632 633 return PluginHelper.getModelToYAMLDumper(context).dumpModelAsYaml(context, def, resolvePlaceholders, uriAsParameters, 634 generatedIds, sourceLocation); 635 } 636 637 @Override 638 public String dumpRouteTemplatesAsXml() throws Exception { 639 List<RouteTemplateDefinition> templates 640 = context.getCamelContextExtension().getContextPlugin(Model.class).getRouteTemplateDefinitions(); 641 if (templates.isEmpty()) { 642 return null; 643 } 644 645 // use a route templates definition to dump the templates 646 RouteTemplatesDefinition def = new RouteTemplatesDefinition(); 647 def.setRouteTemplates(templates); 648 649 return PluginHelper.getModelToXMLDumper(context).dumpModelAsXml(context, def); 650 } 651 652 @Override 653 public String dumpRoutesStatsAsXml(boolean fullStats, boolean includeProcessors) throws Exception { 654 StringBuilder sb = new StringBuilder(); 655 sb.append("<camelContextStat") 656 .append(String.format(" id=\"%s\" state=\"%s\" uptime=\"%s\"", getCamelId(), getState(), getUptimeMillis())); 657 // use substring as we only want the attributes 658 String stat = dumpStatsAsXml(fullStats); 659 sb.append(" exchangesInflight=\"").append(getInflightExchanges()).append("\""); 660 sb.append(" ").append(stat, 7, stat.length() - 2).append(">\n"); 661 662 MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer(); 663 if (server != null) { 664 // gather all the routes for this CamelContext, which requires JMX 665 String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; 666 ObjectName query = ObjectName 667 .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=routes,*"); 668 Set<ObjectName> routes = server.queryNames(query, null); 669 670 List<ManagedProcessorMBean> processors = new ArrayList<>(); 671 if (includeProcessors) { 672 // gather all the processors for this CamelContext, which requires JMX 673 query = ObjectName.getInstance( 674 jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=processors,*"); 675 Set<ObjectName> names = server.queryNames(query, null); 676 for (ObjectName on : names) { 677 ManagedProcessorMBean processor = context.getManagementStrategy().getManagementAgent().newProxyClient(on, 678 ManagedProcessorMBean.class); 679 processors.add(processor); 680 } 681 } 682 processors.sort(new OrderProcessorMBeans()); 683 684 // loop the routes, and append the processor stats if needed 685 sb.append(" <routeStats>\n"); 686 for (ObjectName on : routes) { 687 ManagedRouteMBean route 688 = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedRouteMBean.class); 689 sb.append(" <routeStat") 690 .append(String.format(" id=\"%s\" state=\"%s\" uptime=\"%s\"", route.getRouteId(), route.getState(), 691 route.getUptimeMillis())); 692 if (route.getRouteGroup() != null) { 693 sb.append(String.format(" group=\"%s\"", route.getRouteGroup())); 694 } 695 if (route.getSourceLocation() != null) { 696 sb.append(String.format(" sourceLocation=\"%s\"", route.getSourceLocation())); 697 } 698 699 // use substring as we only want the attributes 700 stat = route.dumpStatsAsXml(fullStats); 701 sb.append(" exchangesInflight=\"").append(route.getExchangesInflight()).append("\""); 702 sb.append(" ").append(stat, 7, stat.length() - 2).append(">\n"); 703 704 // add processor details if needed 705 if (includeProcessors) { 706 sb.append(" <processorStats>\n"); 707 for (ManagedProcessorMBean processor : processors) { 708 int line = processor.getSourceLineNumber() != null ? processor.getSourceLineNumber() : -1; 709 // the processor must belong to this route 710 if (route.getRouteId().equals(processor.getRouteId())) { 711 sb.append(" <processorStat") 712 .append(String.format( 713 " id=\"%s\" index=\"%s\" state=\"%s\" disabled=\"%s\" sourceLineNumber=\"%s\"", 714 processor.getProcessorId(), processor.getIndex(), processor.getState(), 715 processor.getDisabled(), line)); 716 // use substring as we only want the attributes 717 stat = processor.dumpStatsAsXml(fullStats); 718 sb.append(" exchangesInflight=\"").append(processor.getExchangesInflight()).append("\""); 719 sb.append(" ").append(stat, 7, stat.length()).append("\n"); 720 } 721 } 722 sb.append(" </processorStats>\n"); 723 } 724 sb.append(" </routeStat>\n"); 725 } 726 sb.append(" </routeStats>\n"); 727 } 728 729 sb.append("</camelContextStat>"); 730 return sb.toString(); 731 } 732 733 @Override 734 public String dumpRouteStatsAsJSon(boolean fullStats, boolean includeProcessors) throws Exception { 735 JsonObject root = new JsonObject(); 736 root.put("id", getCamelId()); 737 root.put("state", getState()); 738 root.put("uptime", getUptimeMillis()); 739 740 statsAsJSon(root, fullStats); 741 root.put("exchangesInflight", getInflightExchanges()); 742 743 MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer(); 744 if (server != null) { 745 // gather all the routes for this CamelContext, which requires JMX 746 String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; 747 ObjectName query = ObjectName 748 .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=routes,*"); 749 Set<ObjectName> routes = server.queryNames(query, null); 750 751 List<ManagedProcessorMBean> processors = new ArrayList<>(); 752 if (includeProcessors) { 753 // gather all the processors for this CamelContext, which requires JMX 754 query = ObjectName.getInstance( 755 jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=processors,*"); 756 Set<ObjectName> names = server.queryNames(query, null); 757 for (ObjectName on : names) { 758 ManagedProcessorMBean processor = context.getManagementStrategy().getManagementAgent().newProxyClient(on, 759 ManagedProcessorMBean.class); 760 processors.add(processor); 761 } 762 } 763 processors.sort(new OrderProcessorMBeans()); 764 765 // loop the routes, and append the processor stats if needed 766 JsonArray arr = new JsonArray(); 767 root.put("routes", arr); 768 for (ObjectName on : routes) { 769 JsonObject jo = new JsonObject(); 770 arr.add(jo); 771 772 ManagedRouteMBean route 773 = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedRouteMBean.class); 774 jo.put("id", route.getRouteId()); 775 jo.put("state", route.getState()); 776 jo.put("uptime", route.getUptimeMillis()); 777 if (route.getRouteGroup() != null) { 778 jo.put("group", route.getRouteGroup()); 779 } 780 if (route.getSourceLocation() != null) { 781 jo.put("sourceLocation", route.getSourceLocation()); 782 } 783 784 // use substring as we only want the attributes 785 route.statsAsJSon(jo, fullStats); 786 787 // add processor details if needed 788 if (includeProcessors) { 789 JsonArray arr2 = new JsonArray(); 790 jo.put("processors", arr2); 791 for (ManagedProcessorMBean processor : processors) { 792 int line = processor.getSourceLineNumber() != null ? processor.getSourceLineNumber() : -1; 793 // the processor must belong to this route 794 if (route.getRouteId().equals(processor.getRouteId())) { 795 JsonObject jo2 = new JsonObject(); 796 arr2.add(jo2); 797 jo2.put("id", processor.getProcessorId()); 798 jo2.put("index", processor.getIndex()); 799 jo2.put("state", processor.getState()); 800 jo2.put("disabled", processor.getDisabled()); 801 jo2.put("sourceLineNumber", line); 802 processor.statsAsJSon(jo2, fullStats); 803 jo2.put("exchangesInflight", processor.getExchangesInflight()); 804 } 805 } 806 } 807 } 808 } 809 810 return root.toJson(); 811 } 812 813 @Override 814 public String dumpStepStatsAsXml(boolean fullStats) throws Exception { 815 StringBuilder sb = new StringBuilder(); 816 sb.append("<camelContextStat") 817 .append(String.format(" id=\"%s\" state=\"%s\" uptime=\"%s\"", getCamelId(), getState(), getUptimeMillis())); 818 // use substring as we only want the attributes 819 String stat = dumpStatsAsXml(fullStats); 820 sb.append(" exchangesInflight=\"").append(getInflightExchanges()).append("\""); 821 sb.append(" ").append(stat, 7, stat.length() - 2).append(">\n"); 822 823 MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer(); 824 if (server != null) { 825 // gather all the routes for this CamelContext, which requires JMX 826 String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; 827 ObjectName query = ObjectName 828 .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=routes,*"); 829 Set<ObjectName> routes = server.queryNames(query, null); 830 831 List<ManagedProcessorMBean> steps = new ArrayList<>(); 832 // gather all the steps for this CamelContext, which requires JMX 833 query = ObjectName 834 .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=steps,*"); 835 Set<ObjectName> names = server.queryNames(query, null); 836 for (ObjectName on : names) { 837 ManagedStepMBean step 838 = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedStepMBean.class); 839 steps.add(step); 840 } 841 steps.sort(new OrderProcessorMBeans()); 842 843 // loop the routes, and append the processor stats if needed 844 sb.append(" <routeStats>\n"); 845 for (ObjectName on : routes) { 846 ManagedRouteMBean route 847 = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedRouteMBean.class); 848 sb.append(" <routeStat") 849 .append(String.format(" id=\"%s\" state=\"%s\" uptime=\"%s\"", route.getRouteId(), route.getState(), 850 route.getUptimeMillis())); 851 if (route.getRouteGroup() != null) { 852 sb.append(String.format(" group=\"%s\"", route.getRouteGroup())); 853 } 854 if (route.getSourceLocation() != null) { 855 sb.append(String.format(" sourceLocation=\"%s\"", route.getSourceLocation())); 856 } 857 858 // use substring as we only want the attributes 859 stat = route.dumpStatsAsXml(fullStats); 860 sb.append(" exchangesInflight=\"").append(route.getExchangesInflight()).append("\""); 861 sb.append(" ").append(stat, 7, stat.length() - 2).append(">\n"); 862 863 // add steps details if needed 864 sb.append(" <stepStats>\n"); 865 for (ManagedProcessorMBean step : steps) { 866 // the step must belong to this route 867 if (route.getRouteId().equals(step.getRouteId())) { 868 int line = step.getSourceLineNumber() != null ? step.getSourceLineNumber() : -1; 869 sb.append(" <stepStat") 870 .append(String.format( 871 " id=\"%s\" index=\"%s\" state=\"%s\" disabled=\"%s\" sourceLineNumber=\"%s\"", 872 step.getProcessorId(), step.getIndex(), step.getState(), step.getDisabled(), line)); 873 // use substring as we only want the attributes 874 stat = step.dumpStatsAsXml(fullStats); 875 sb.append(" exchangesInflight=\"").append(step.getExchangesInflight()).append("\""); 876 sb.append(" ").append(stat, 7, stat.length()).append("\n"); 877 } 878 sb.append(" </stepStats>\n"); 879 } 880 sb.append(" </stepStat>\n"); 881 } 882 sb.append(" </routeStats>\n"); 883 } 884 885 sb.append("</camelContextStat>"); 886 return sb.toString(); 887 } 888 889 @Override 890 public String dumpRoutesCoverageAsXml() throws Exception { 891 StringBuilder sb = new StringBuilder(); 892 sb.append("<camelContextRouteCoverage") 893 .append(String.format(" id=\"%s\" exchangesTotal=\"%s\" totalProcessingTime=\"%s\"", getCamelId(), 894 getExchangesTotal(), getTotalProcessingTime())) 895 .append(">\n"); 896 897 String xml = dumpRoutesAsXml(false, true, true); 898 if (xml != null) { 899 // use the coverage xml parser to dump the routes and enrich with coverage stats 900 Document dom = RouteCoverageXmlParser.parseXml(context, new ByteArrayInputStream(xml.getBytes())); 901 // convert dom back to xml 902 String converted = context.getTypeConverter().convertTo(String.class, dom); 903 sb.append(converted); 904 } 905 906 sb.append("\n</camelContextRouteCoverage>"); 907 return sb.toString(); 908 } 909 910 @Override 911 public boolean createEndpoint(String uri) throws Exception { 912 if (context.hasEndpoint(uri) != null) { 913 // endpoint already exists 914 return false; 915 } 916 917 Endpoint endpoint = context.getEndpoint(uri); 918 if (endpoint != null) { 919 // ensure endpoint is registered, as the management strategy could have been configured to not always 920 // register new endpoints in JMX, so we need to check if its registered, and if not register it manually 921 ObjectName on 922 = context.getManagementStrategy().getManagementObjectNameStrategy().getObjectNameForEndpoint(endpoint); 923 if (on != null && !context.getManagementStrategy().getManagementAgent().isRegistered(on)) { 924 // register endpoint as mbean 925 Object me = context.getManagementStrategy().getManagementObjectStrategy().getManagedObjectForEndpoint(context, 926 endpoint); 927 context.getManagementStrategy().getManagementAgent().register(me, on); 928 } 929 return true; 930 } else { 931 return false; 932 } 933 } 934 935 @Override 936 public int removeEndpoints(String pattern) throws Exception { 937 // endpoints is always removed from JMX if removed from context 938 Collection<Endpoint> removed = context.removeEndpoints(pattern); 939 return removed.size(); 940 } 941 942 @Override 943 public void reset(boolean includeRoutes) throws Exception { 944 reset(); 945 load.reset(); 946 thp.reset(); 947 948 // and now reset all routes for this route 949 if (includeRoutes) { 950 MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer(); 951 if (server != null) { 952 String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; 953 ObjectName query = ObjectName 954 .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=routes,*"); 955 Set<ObjectName> names = server.queryNames(query, null); 956 for (ObjectName name : names) { 957 server.invoke(name, "reset", new Object[] { true }, new String[] { "boolean" }); 958 } 959 } 960 } 961 } 962 963 @Override 964 public Set<String> componentNames() throws Exception { 965 return context.getComponentNames(); 966 } 967 968 @Override 969 public Set<String> languageNames() throws Exception { 970 return context.getLanguageNames(); 971 } 972 973 @Override 974 public Set<String> dataFormatNames() throws Exception { 975 return context.getDataFormatNames(); 976 } 977 978 @Override 979 public Set<String> routeIds() { 980 return context.getRouteIds(); 981 } 982 983 @Override 984 public Set<String> routeGroups() { 985 return context.getRouteGroupIds(); 986 } 987 988 /** 989 * Used for sorting the processor mbeans accordingly to their index. 990 */ 991 private static final class OrderProcessorMBeans implements Comparator<ManagedProcessorMBean> { 992 993 @Override 994 public int compare(ManagedProcessorMBean o1, ManagedProcessorMBean o2) { 995 return o1.getIndex().compareTo(o2.getIndex()); 996 } 997 } 998 999}