/** * 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.commands; import java.io.PrintStream; import java.io.StringReader; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import org.apache.camel.util.CamelContextStatDump; import static org.apache.camel.util.ObjectHelper.isEmpty; /** * Command to display detailed information about a given {@link org.apache.camel.CamelContext}. */ public class ContextInfoCommand extends AbstractContextCommand { public static final String XML_TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; public static final String OUTPUT_TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss"; private StringEscape stringEscape; private boolean verbose; /** * @param context The name of the Camel context * @param verbose Whether to output verbose */ public ContextInfoCommand(String context, boolean verbose) { super(context); this.verbose = verbose; } /** * Sets the {@link org.apache.camel.commands.StringEscape} to use. */ public void setStringEscape(StringEscape stringEscape) { this.stringEscape = stringEscape; } @Override protected Object performContextCommand(CamelController camelController, String contextName, PrintStream out, PrintStream err) throws Exception { Map<String, Object> row = camelController.getCamelContextInformation(context); if (row == null || row.isEmpty()) { err.println("Camel context " + context + " not found."); return null; } out.println(""); out.println(stringEscape.unescapeJava("\u001B[1mCamel Context " + context + "\u001B[0m")); out.println(stringEscape.unescapeJava("\tName: " + row.get("name"))); out.println(stringEscape.unescapeJava("\tManagementName: " + row.get("managementName"))); out.println(stringEscape.unescapeJava("\tVersion: " + row.get("version"))); out.println(stringEscape.unescapeJava("\tStatus: " + row.get("status"))); out.println(stringEscape.unescapeJava("\tUptime: " + row.get("uptime"))); out.println(""); out.println(stringEscape.unescapeJava("\u001B[1mMiscellaneous\u001B[0m")); out.println(stringEscape.unescapeJava("\tSuspended: " + row.get("suspended"))); out.println(stringEscape.unescapeJava("\tShutdown Timeout: " + row.get("shutdownTimeout") + " sec.")); if (row.get("managementStatisticsLevel") != null) { out.println(stringEscape.unescapeJava("\tManagement StatisticsLevel: " + row.get("managementStatisticsLevel"))); } out.println(stringEscape.unescapeJava("\tAllow UseOriginalMessage: " + row.get("allowUseOriginalMessage"))); out.println(stringEscape.unescapeJava("\tMessage History: " + row.get("messageHistory"))); out.println(stringEscape.unescapeJava("\tTracing: " + row.get("tracing"))); out.println(stringEscape.unescapeJava("\tLog Mask: " + row.get("logMask"))); out.println(""); out.println(stringEscape.unescapeJava("\u001B[1mProperties\u001B[0m")); for (Map.Entry<String, Object> entry : row.entrySet()) { String key = entry.getKey(); if (key.startsWith("property.")) { key = key.substring(9); out.println(stringEscape.unescapeJava("\t" + key + " = " + entry.getValue())); } } if (verbose) { out.println(""); out.println(stringEscape.unescapeJava("\u001B[1mAdvanced\u001B[0m")); out.println(stringEscape.unescapeJava("\tClassResolver: " + row.get("classResolver"))); out.println(stringEscape.unescapeJava("\tPackageScanClassResolver: " + row.get("packageScanClassResolver"))); out.println(stringEscape.unescapeJava("\tApplicationContextClassLoader: " + row.get("applicationContextClassLoader"))); printStatistics(camelController, out); // add type converter details out.println(stringEscape.unescapeJava("\tNumber of type converters: " + row.get("typeConverter.numberOfTypeConverters"))); boolean enabled = false; if (row.get("typeConverter.statisticsEnabled") != null) { enabled = (boolean) row.get("typeConverter.statisticsEnabled"); } if (enabled) { long noop = (long) row.get("typeConverter.noopCounter"); long attempt = (long) row.get("typeConverter.attemptCounter"); long hit = (long) row.get("typeConverter.hitCounter"); long miss = (long) row.get("typeConverter.missCounter"); long failed = (long) row.get("typeConverter.failedCounter"); out.println(stringEscape.unescapeJava(String.format("\tType converter usage: [noop=%s, attempts=%s, hits=%s, misses=%s, failures=%s]", noop, attempt, hit, miss, failed))); } // add async processor await details out.println(stringEscape.unescapeJava("\tNumber of blocked threads: " + row.get("asyncProcessorAwaitManager.size"))); enabled = false; if (row.get("asyncProcessorAwaitManager.statisticsEnabled") != null) { enabled = (boolean) row.get("asyncProcessorAwaitManager.statisticsEnabled"); } if (enabled) { long blocked = (long) row.get("asyncProcessorAwaitManager.threadsBlocked"); long interrupted = (long) row.get("asyncProcessorAwaitManager.threadsInterrupted"); long total = (long) row.get("asyncProcessorAwaitManager.totalDuration"); long min = (long) row.get("asyncProcessorAwaitManager.minDuration"); long max = (long) row.get("asyncProcessorAwaitManager.maxDuration"); long mean = (long) row.get("asyncProcessorAwaitManager.meanDuration"); out.println(stringEscape.unescapeJava(String.format("\tAsyncProcessorAwaitManager usage: [blocked=%s, interrupted=%s, total=%s msec, min=%s msec, max=%s msec, mean=%s msec]", blocked, interrupted, total, min, max, mean))); } // add stream caching details if enabled enabled = (boolean) row.get("streamCachingEnabled"); if (enabled) { Object spoolDirectory = safeNull(row.get("streamCaching.spoolDirectory")); Object spoolChiper = safeNull(row.get("streamCaching.spoolChiper")); Object spoolThreshold = safeNull(row.get("streamCaching.spoolThreshold")); Object spoolUsedHeapMemoryThreshold = safeNull(row.get("streamCaching.spoolUsedHeapMemoryThreshold")); Object spoolUsedHeapMemoryLimit = safeNull(row.get("streamCaching.spoolUsedHeapMemoryLimit")); Object anySpoolRules = safeNull(row.get("streamCaching.anySpoolRules")); Object bufferSize = safeNull(row.get("streamCaching.bufferSize")); Object removeSpoolDirectoryWhenStopping = safeNull(row.get("streamCaching.removeSpoolDirectoryWhenStopping")); boolean statisticsEnabled = (boolean) row.get("streamCaching.statisticsEnabled"); String text = String.format("\tStream caching: [spoolDirectory=%s, spoolChiper=%s, spoolThreshold=%s, spoolUsedHeapMemoryThreshold=%s, " + "spoolUsedHeapMemoryLimit=%s, anySpoolRules=%s, bufferSize=%s, removeSpoolDirectoryWhenStopping=%s, statisticsEnabled=%s]", spoolDirectory, spoolChiper, spoolThreshold, spoolUsedHeapMemoryThreshold, spoolUsedHeapMemoryLimit, anySpoolRules, bufferSize, removeSpoolDirectoryWhenStopping, statisticsEnabled); out.println(stringEscape.unescapeJava(text)); if (statisticsEnabled) { Object cacheMemoryCounter = safeNull(row.get("streamCaching.cacheMemoryCounter")); Object cacheMemorySize = safeNull(row.get("streamCaching.cacheMemorySize")); Object cacheMemoryAverageSize = safeNull(row.get("streamCaching.cacheMemoryAverageSize")); Object cacheSpoolCounter = safeNull(row.get("streamCaching.cacheSpoolCounter")); Object cacheSpoolSize = safeNull(row.get("streamCaching.cacheSpoolSize")); Object cacheSpoolAverageSize = safeNull(row.get("streamCaching.cacheSpoolAverageSize")); text = String.format("\t [cacheMemoryCounter=%s, cacheMemorySize=%s, cacheMemoryAverageSize=%s, cacheSpoolCounter=%s, " + "cacheSpoolSize=%s, cacheSpoolAverageSize=%s]", cacheMemoryCounter, cacheMemorySize, cacheMemoryAverageSize, cacheSpoolCounter, cacheSpoolSize, cacheSpoolAverageSize); out.println(stringEscape.unescapeJava(text)); } } long totalRoutes = (long) row.get("totalRoutes"); long startedRoutes = (long) row.get("totalRoutes"); out.println(stringEscape.unescapeJava("\tNumber of running routes: " + startedRoutes)); out.println(stringEscape.unescapeJava("\tNumber of not running routes: " + (totalRoutes - startedRoutes))); } return null; } protected void printStatistics(CamelController camelController, PrintStream out) throws Exception { out.println(""); out.println(stringEscape.unescapeJava("\u001B[1mStatistics\u001B[0m")); String xml = camelController.getCamelContextStatsAsXml(context, true, false); if (xml != null) { JAXBContext context = JAXBContext.newInstance(CamelContextStatDump.class); Unmarshaller unmarshaller = context.createUnmarshaller(); CamelContextStatDump stat = (CamelContextStatDump) unmarshaller.unmarshal(new StringReader(xml)); long total = stat.getExchangesCompleted() + stat.getExchangesFailed(); out.println(stringEscape.unescapeJava("\tExchanges Total: " + total)); out.println(stringEscape.unescapeJava("\tExchanges Completed: " + stat.getExchangesCompleted())); out.println(stringEscape.unescapeJava("\tExchanges Failed: " + stat.getExchangesFailed())); out.println(stringEscape.unescapeJava("\tExchanges Inflight: " + stat.getExchangesInflight())); out.println(stringEscape.unescapeJava("\tMin Processing Time: " + stat.getMinProcessingTime() + " ms")); out.println(stringEscape.unescapeJava("\tMax Processing Time: " + stat.getMaxProcessingTime() + " ms")); out.println(stringEscape.unescapeJava("\tMean Processing Time: " + stat.getMeanProcessingTime() + " ms")); out.println(stringEscape.unescapeJava("\tTotal Processing Time: " + stat.getTotalProcessingTime() + " ms")); out.println(stringEscape.unescapeJava("\tLast Processing Time: " + stat.getLastProcessingTime() + " ms")); out.println(stringEscape.unescapeJava("\tDelta Processing Time: " + stat.getDeltaProcessingTime() + " ms")); if (isEmpty(stat.getStartTimestamp())) { // Print an empty value for scripting out.println(stringEscape.unescapeJava("\tStart Statistics Date:")); } else { Date date = new SimpleDateFormat(XML_TIMESTAMP_FORMAT).parse(stat.getStartTimestamp()); String text = new SimpleDateFormat(OUTPUT_TIMESTAMP_FORMAT).format(date); out.println(stringEscape.unescapeJava("\tStart Statistics Date: " + text)); } // Test for null to see if a any exchanges have been processed first to avoid NPE if (isEmpty(stat.getResetTimestamp())) { // Print an empty value for scripting out.println(stringEscape.unescapeJava("\tReset Statistics Date:")); } else { Date date = new SimpleDateFormat(XML_TIMESTAMP_FORMAT).parse(stat.getResetTimestamp()); String text = new SimpleDateFormat(OUTPUT_TIMESTAMP_FORMAT).format(date); out.println(stringEscape.unescapeJava("\tReset Statistics Date: " + text)); } // Test for null to see if a any exchanges have been processed first to avoid NPE if (isEmpty(stat.getFirstExchangeCompletedTimestamp())) { // Print an empty value for scripting out.println(stringEscape.unescapeJava("\tFirst Exchange Date:")); } else { Date date = new SimpleDateFormat(XML_TIMESTAMP_FORMAT).parse(stat.getFirstExchangeCompletedTimestamp()); String text = new SimpleDateFormat(OUTPUT_TIMESTAMP_FORMAT).format(date); out.println(stringEscape.unescapeJava("\tFirst Exchange Date: " + text)); } // Test for null to see if a any exchanges have been processed first to avoid NPE if (isEmpty(stat.getLastExchangeCompletedTimestamp())) { // Print an empty value for scripting out.println(stringEscape.unescapeJava("\tLast Exchange Date:")); } else { Date date = new SimpleDateFormat(XML_TIMESTAMP_FORMAT).parse(stat.getLastExchangeCompletedTimestamp()); String text = new SimpleDateFormat(OUTPUT_TIMESTAMP_FORMAT).format(date); out.println(stringEscape.unescapeJava("\tLast Exchange Date: " + text)); } } } }