diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/BeanDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/BeanDevConsole.java index 566c04d1a320c..8cb788b3b2126 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/BeanDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/BeanDevConsole.java @@ -71,29 +71,10 @@ protected String doCallText(Map options) { Stream keys = beans.keySet().stream().filter(r -> accept(r, filter)).sorted(String::compareToIgnoreCase); keys.forEach(k -> { Object bean = beans.get(k); - if (bean != null) { - boolean include = internal || !bean.getClass().getName().startsWith("org.apache.camel."); - if (include) { - sb.append(String.format(" %s (class: %s)%n", k, bean.getClass().getName())); - - Map values = new TreeMap<>(); - if (properties) { - try { - bi.getProperties(bean, values, null); - } catch (Throwable e) { - // ignore - } - values.forEach((pk, pv) -> { - if (pv == null) { - if (nulls) { - sb.append(String.format(" %s = null%n", pk)); - } - } else { - String t = pv.getClass().getName(); - sb.append(String.format(" %s (%s) = %s%n", pk, t, pv)); - } - }); - } + if (shouldIncludeBean(bean, internal)) { + sb.append(String.format(" %s (class: %s)%n", k, bean.getClass().getName())); + if (properties) { + appendBeanPropertiesText(sb, bi, bean, nulls); } } sb.append("\n"); @@ -105,6 +86,27 @@ protected String doCallText(Map options) { return sb.toString(); } + private void appendBeanPropertiesText(StringBuilder sb, BeanIntrospection bi, Object bean, boolean nulls) { + Map values = new TreeMap<>(); + try { + bi.getProperties(bean, values, null); + } catch (Throwable e) { + // ignore + } + values.forEach((pk, pv) -> appendPropertyText(sb, pk, pv, nulls)); + } + + private void appendPropertyText(StringBuilder sb, String pk, Object pv, boolean nulls) { + if (pv == null) { + if (nulls) { + sb.append(String.format(" %s = null%n", pk)); + } + } else { + String t = pv.getClass().getName(); + sb.append(String.format(" %s (%s) = %s%n", pk, t, pv)); + } + } + @Override protected JsonObject doCallJson(Map options) { String filter = (String) options.get(FILTER); @@ -122,51 +124,9 @@ protected JsonObject doCallJson(Map options) { Stream keys = beans.keySet().stream().filter(r -> accept(r, filter)).sorted(String::compareToIgnoreCase); keys.forEach(k -> { Object bean = beans.get(k); - if (bean != null) { - boolean include = internal || !bean.getClass().getName().startsWith("org.apache.camel."); - if (include) { - Map values = new TreeMap<>(); - if (properties) { - try { - bi.getProperties(bean, values, null); - } catch (Throwable e) { - // ignore - } - } - JsonObject jb = new JsonObject(); - jb.put("name", k); - jb.put("type", bean.getClass().getName()); - jo.put(k, jb); - - if (!values.isEmpty()) { - JsonArray arr = new JsonArray(); - values.forEach((pk, pv) -> { - Object value = pv; - String type = pv != null ? pv.getClass().getName() : null; - if (type != null) { - value = Jsoner.trySerialize(pv); - if (value == null) { - // cannot serialize so escape - value = Jsoner.escape(pv.toString()); - } else { - // okay so use the value as-s - value = pv; - } - } - JsonObject jp = new JsonObject(); - jp.put("name", pk); - if (type != null) { - jp.put("type", type); - } - jp.put("value", value); - boolean accept = value != null || nulls; - if (accept) { - arr.add(jp); - } - }); - jb.put("properties", arr); - } - } + if (shouldIncludeBean(bean, internal)) { + JsonObject jb = buildBeanJson(k, bean, bi, properties, nulls); + jo.put(k, jb); } }); } catch (Exception e) { @@ -176,6 +136,66 @@ protected JsonObject doCallJson(Map options) { return root; } + private JsonObject buildBeanJson(String name, Object bean, BeanIntrospection bi, boolean properties, boolean nulls) { + JsonObject jb = new JsonObject(); + jb.put("name", name); + jb.put("type", bean.getClass().getName()); + + if (!properties) { + return jb; + } + + Map values = new TreeMap<>(); + try { + bi.getProperties(bean, values, null); + } catch (Throwable e) { + // ignore + } + + if (!values.isEmpty()) { + JsonArray arr = new JsonArray(); + values.forEach((pk, pv) -> addPropertyToArray(arr, pk, pv, nulls)); + jb.put("properties", arr); + } + + return jb; + } + + private void addPropertyToArray(JsonArray arr, String pk, Object pv, boolean nulls) { + Object value = resolvePropertyValue(pv); + if (value == null && !nulls) { + return; + } + + JsonObject jp = new JsonObject(); + jp.put("name", pk); + if (pv != null) { + jp.put("type", pv.getClass().getName()); + } + jp.put("value", value); + arr.add(jp); + } + + private Object resolvePropertyValue(Object pv) { + if (pv == null) { + return null; + } + Object serialized = Jsoner.trySerialize(pv); + if (serialized == null) { + // cannot serialize so escape + return Jsoner.escape(pv.toString()); + } + // okay so use the value as-is + return pv; + } + + private static boolean shouldIncludeBean(Object bean, boolean internal) { + if (bean == null) { + return false; + } + return internal || !bean.getClass().getName().startsWith("org.apache.camel."); + } + private static boolean accept(String name, String filter) { if (filter == null || filter.isBlank()) { return true; diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/BrowseDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/BrowseDevConsole.java index 5611085f500c9..5214e46184e9e 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/BrowseDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/BrowseDevConsole.java @@ -104,45 +104,20 @@ protected String doCallText(Map options) { StringBuilder sb = new StringBuilder(); String filter = (String) options.get(FILTER); - String lim = (String) options.get(LIMIT); - String tail = (String) options.get(TAIL); - final int pos = tail == null ? 0 : Integer.parseInt(tail); - final int max = lim == null ? limit : Integer.parseInt(lim); - boolean freshSize = "true".equals(options.getOrDefault(FRESH_SIZE, "false")); - boolean dump = "true".equals(options.getOrDefault(DUMP, "true")); - boolean includeBody = "true".equals(options.getOrDefault(INCLUDE_BODY, "true")); - int maxChars = Integer.parseInt((String) options.getOrDefault(BODY_MAX_CHARS, "" + bodyMaxChars)); + final int pos = parseIntOption(options, TAIL, 0); + final int max = parseIntOption(options, LIMIT, limit); + boolean freshSize = parseBooleanOption(options, FRESH_SIZE, false); + boolean dump = parseBooleanOption(options, DUMP, true); + boolean includeBody = parseBooleanOption(options, INCLUDE_BODY, true); + int maxChars = parseIntOption(options, BODY_MAX_CHARS, bodyMaxChars); - Collection endpoints = new TreeSet<>(Comparator.comparing(Endpoint::getEndpointUri)); - endpoints.addAll(getCamelContext().getEndpoints()); - for (Endpoint endpoint : endpoints) { - if (endpoint instanceof BrowsableEndpoint be - && (filter == null || PatternHelper.matchPattern(endpoint.getEndpointUri(), filter))) { - - if (dump) { - List list = freshSize ? be.getExchanges(Integer.MAX_VALUE, null) : be.getExchanges(max, null); - int queueSize = list != null ? list.size() : 0; - int begin = 0; - if (list != null && pos > 0) { - begin = Math.max(0, list.size() - pos); - list = list.subList(begin, list.size()); - } - if (list != null) { - sb.append("\n"); - sb.append(String.format("Browse: %s (size: %d limit: %d position: %d)%n", endpoint.getEndpointUri(), - queueSize, max, begin)); - for (Exchange e : list) { - String json - = MessageHelper.dumpAsJSon(e.getMessage(), false, false, includeBody, 2, true, true, true, - maxChars, true); - sb.append(json); - sb.append("\n"); - } - } - } else { - BrowsableEndpoint.BrowseStatus status = be.getBrowseStatus(Integer.MAX_VALUE); - sb.append(String.format("Browse: %s (size: %d%n", endpoint.getEndpointUri(), status.size())); - } + List browsableEndpoints = getBrowsableEndpoints(filter); + for (BrowsableEndpoint be : browsableEndpoints) { + if (dump) { + appendDumpText(sb, be, freshSize, max, pos, includeBody, maxChars); + } else { + BrowsableEndpoint.BrowseStatus status = be.getBrowseStatus(Integer.MAX_VALUE); + sb.append(String.format("Browse: %s (size: %d%n", be.getEndpointUri(), status.size())); } } sb.append("\n"); @@ -150,76 +125,52 @@ protected String doCallText(Map options) { return sb.toString(); } + private void appendDumpText( + StringBuilder sb, BrowsableEndpoint be, boolean freshSize, int max, int pos, boolean includeBody, int maxChars) { + List list = freshSize ? be.getExchanges(Integer.MAX_VALUE, null) : be.getExchanges(max, null); + if (list == null) { + return; + } + + int queueSize = list.size(); + int begin = calculateBeginPosition(list.size(), pos); + if (begin > 0) { + list = list.subList(begin, list.size()); + } + + sb.append("\n"); + sb.append(String.format("Browse: %s (size: %d limit: %d position: %d)%n", be.getEndpointUri(), + queueSize, max, begin)); + for (Exchange e : list) { + String json = MessageHelper.dumpAsJSon(e.getMessage(), false, false, includeBody, 2, true, true, true, + maxChars, true); + sb.append(json); + sb.append("\n"); + } + } + @Override protected JsonObject doCallJson(Map options) { JsonObject root = new JsonObject(); JsonArray arr = new JsonArray(); String filter = (String) options.get(FILTER); - String lim = (String) options.get(LIMIT); - String tail = (String) options.get(TAIL); - final int pos = tail == null ? 0 : Integer.parseInt(tail); - final int max = lim == null ? limit : Integer.parseInt(lim); - boolean freshSize = "true".equals(options.getOrDefault(FRESH_SIZE, "false")); - boolean dump = "true".equals(options.getOrDefault(DUMP, "true")); - boolean includeBody = "true".equals(options.getOrDefault(INCLUDE_BODY, "true")); - int maxChars = Integer.parseInt((String) options.getOrDefault(BODY_MAX_CHARS, "" + bodyMaxChars)); + final int pos = parseIntOption(options, TAIL, 0); + final int max = parseIntOption(options, LIMIT, limit); + boolean freshSize = parseBooleanOption(options, FRESH_SIZE, false); + boolean dump = parseBooleanOption(options, DUMP, true); + boolean includeBody = parseBooleanOption(options, INCLUDE_BODY, true); + int maxChars = parseIntOption(options, BODY_MAX_CHARS, bodyMaxChars); - Collection endpoints = new TreeSet<>(Comparator.comparing(Endpoint::getEndpointUri)); - endpoints.addAll(getCamelContext().getEndpoints()); - for (Endpoint endpoint : endpoints) { - if (endpoint instanceof BrowsableEndpoint be - && (filter == null || PatternHelper.matchPattern(endpoint.getEndpointUri(), filter))) { - if (dump) { - List list = freshSize ? be.getExchanges(Integer.MAX_VALUE, null) : be.getExchanges(max, null); - int queueSize = list != null ? list.size() : 0; - int begin = 0; - if (list != null && pos > 0) { - begin = Math.max(0, list.size() - pos); - list = list.subList(begin, list.size()); - } - if (list != null) { - JsonObject jo = new JsonObject(); - jo.put("endpointUri", endpoint.getEndpointUri()); - jo.put("queueSize", queueSize); - jo.put("limit", max); - jo.put("position", begin); - if (!list.isEmpty()) { - long ts = list.get(0).getMessage().getHeader(Exchange.MESSAGE_TIMESTAMP, 0L, long.class); - if (ts > 0) { - jo.put("firstTimestamp", ts); - } - if (list.size() > 1) { - ts = list.get(list.size() - 1).getMessage().getHeader(Exchange.MESSAGE_TIMESTAMP, 0L, - long.class); - if (ts > 0) { - jo.put("lastTimestamp", ts); - } - } - } - arr.add(jo); - JsonArray arr2 = new JsonArray(); - for (Exchange e : list) { - arr2.add(MessageHelper.dumpAsJSonObject(e.getMessage(), false, false, includeBody, true, true, true, - maxChars)); - } - if (!arr2.isEmpty()) { - jo.put("messages", arr2); - } - } - } else { - BrowsableEndpoint.BrowseStatus status = be.getBrowseStatus(Integer.MAX_VALUE); - JsonObject jo = new JsonObject(); - jo.put("endpointUri", endpoint.getEndpointUri()); - jo.put("queueSize", status.size()); - if (status.firstTimestamp() > 0) { - jo.put("firstTimestamp", status.firstTimestamp()); - } - if (status.lastTimestamp() > 0) { - jo.put("lastTimestamp", status.lastTimestamp()); - } + List browsableEndpoints = getBrowsableEndpoints(filter); + for (BrowsableEndpoint be : browsableEndpoints) { + if (dump) { + JsonObject jo = buildDumpJson(be, freshSize, max, pos, includeBody, maxChars); + if (jo != null) { arr.add(jo); } + } else { + arr.add(buildStatusOnlyJson(be)); } } if (!arr.isEmpty()) { @@ -229,4 +180,102 @@ protected JsonObject doCallJson(Map options) { return root; } + private JsonObject buildDumpJson( + BrowsableEndpoint be, boolean freshSize, int max, int pos, boolean includeBody, int maxChars) { + List list = freshSize ? be.getExchanges(Integer.MAX_VALUE, null) : be.getExchanges(max, null); + if (list == null) { + return null; + } + + int queueSize = list.size(); + int begin = calculateBeginPosition(list.size(), pos); + if (begin > 0) { + list = list.subList(begin, list.size()); + } + + JsonObject jo = buildEndpointJson(be, queueSize, max, begin); + addTimestampsFromList(jo, list); + addMessagesToJson(jo, list, includeBody, maxChars); + return jo; + } + + private List getBrowsableEndpoints(String filter) { + Collection endpoints = new TreeSet<>(Comparator.comparing(Endpoint::getEndpointUri)); + endpoints.addAll(getCamelContext().getEndpoints()); + return endpoints.stream() + .filter(e -> e instanceof BrowsableEndpoint) + .map(e -> (BrowsableEndpoint) e) + .filter(be -> matchesFilter(be.getEndpointUri(), filter)) + .toList(); + } + + private boolean matchesFilter(String uri, String filter) { + return filter == null || PatternHelper.matchPattern(uri, filter); + } + + private int parseIntOption(Map options, String key, int defaultValue) { + String value = (String) options.get(key); + return value == null ? defaultValue : Integer.parseInt(value); + } + + private boolean parseBooleanOption(Map options, String key, boolean defaultValue) { + return "true".equals(options.getOrDefault(key, String.valueOf(defaultValue))); + } + + private int calculateBeginPosition(int listSize, int tailPos) { + if (tailPos <= 0) { + return 0; + } + return Math.max(0, listSize - tailPos); + } + + private JsonObject buildStatusOnlyJson(BrowsableEndpoint be) { + BrowsableEndpoint.BrowseStatus status = be.getBrowseStatus(Integer.MAX_VALUE); + JsonObject jo = new JsonObject(); + jo.put("endpointUri", be.getEndpointUri()); + jo.put("queueSize", status.size()); + if (status.firstTimestamp() > 0) { + jo.put("firstTimestamp", status.firstTimestamp()); + } + if (status.lastTimestamp() > 0) { + jo.put("lastTimestamp", status.lastTimestamp()); + } + return jo; + } + + private JsonObject buildEndpointJson(BrowsableEndpoint be, int queueSize, int max, int begin) { + JsonObject jo = new JsonObject(); + jo.put("endpointUri", be.getEndpointUri()); + jo.put("queueSize", queueSize); + jo.put("limit", max); + jo.put("position", begin); + return jo; + } + + private void addTimestampsFromList(JsonObject jo, List list) { + if (list.isEmpty()) { + return; + } + long firstTs = list.get(0).getMessage().getHeader(Exchange.MESSAGE_TIMESTAMP, 0L, long.class); + if (firstTs > 0) { + jo.put("firstTimestamp", firstTs); + } + if (list.size() > 1) { + long lastTs = list.get(list.size() - 1).getMessage().getHeader(Exchange.MESSAGE_TIMESTAMP, 0L, long.class); + if (lastTs > 0) { + jo.put("lastTimestamp", lastTs); + } + } + } + + private void addMessagesToJson(JsonObject jo, List list, boolean includeBody, int maxChars) { + JsonArray arr = new JsonArray(); + for (Exchange e : list) { + arr.add(MessageHelper.dumpAsJSonObject(e.getMessage(), false, false, includeBody, true, true, true, maxChars)); + } + if (!arr.isEmpty()) { + jo.put("messages", arr); + } + } + } diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/ConsumerDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/ConsumerDevConsole.java index 9c980feb88fcb..cf7ac81fe6bdd 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/ConsumerDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/ConsumerDevConsole.java @@ -46,89 +46,111 @@ protected String doCallText(Map options) { StringBuilder sb = new StringBuilder(); ManagedCamelContext mcc = getCamelContext().getCamelContextExtension().getContextPlugin(ManagedCamelContext.class); - if (mcc != null) { - for (Route route : getCamelContext().getRoutes()) { - String id = route.getId(); - ManagedConsumerMBean mc = mcc.getManagedConsumer(id); - if (mc != null) { - Integer inflight = mc.getInflightExchanges(); - if (inflight == null) { - inflight = 0; - } - - if (!sb.isEmpty()) { - sb.append("\n"); - } - sb.append(String.format("%n Id: %s", id)); - sb.append(String.format("%n Uri: %s", mc.getEndpointUri())); - sb.append(String.format("%n State: %s", mc.getState())); - sb.append(String.format("%n Class: %s", mc.getServiceType())); - sb.append(String.format("%n Remote: %b", mc.isRemoteEndpoint())); - sb.append(String.format("%n Hosted: %b", mc.isHostedService())); - sb.append(String.format("%n Inflight: %d", inflight)); - if (mcc instanceof ManagedSchedulePollConsumerMBean mpc) { - sb.append(String.format("%n Polling: %s", mpc.isPolling())); - sb.append(String.format("%n First Poll Done: %s", mpc.isFirstPollDone())); - sb.append(String.format("%n Scheduler Started: %s", mpc.isSchedulerStarted())); - sb.append(String.format("%n Scheduler Class: %s", mpc.getSchedulerClassName())); - sb.append(String.format("%n Repeat Count: %s", mpc.getRepeatCount())); - sb.append(String.format("%n Fixed Delay: %s", mpc.isUseFixedDelay())); - sb.append(String.format("%n Greedy: %s", mpc.isGreedy())); - sb.append(String.format("%n Running Logging Level: %s", mpc.getRunningLoggingLevel())); - sb.append(String.format("%n Send Empty Message When Idle: %s", mpc.isSendEmptyMessageWhenIdle())); - sb.append(String.format("%n Counter (total: %d success: %d error: %d)", - mpc.getCounter(), mpc.getSuccessCounter(), mpc.getErrorCounter())); - sb.append(String.format("%n Delay (initial: %d delay: %d unit: %s)", - mpc.getInitialDelay(), mpc.getDelay(), mpc.getTimeUnit())); - sb.append(String.format( - "\n Backoff(counter: %d multiplier: %d errorThreshold: %d, idleThreshold: %d )", - mpc.getBackoffCounter(), mpc.getBackoffMultiplier(), mpc.getBackoffErrorThreshold(), - mpc.getBackoffIdleThreshold())); - } - if ("TimerConsumer".equals(mc.getServiceType())) { - // need to use JMX to gather details for camel-timer consumer - try { - MBeanServer ms = ManagementFactory.getPlatformMBeanServer(); - ObjectName on = getCamelContext().getManagementStrategy().getManagementObjectNameStrategy() - .getObjectNameForConsumer(getCamelContext(), - route.getConsumer()); - if (ms.isRegistered(on)) { - String timerName = (String) ms.getAttribute(on, "TimerName"); - Long counter = (Long) ms.getAttribute(on, "Counter"); - Boolean polling = (Boolean) ms.getAttribute(on, "Polling"); - Boolean fixedRate = (Boolean) ms.getAttribute(on, "FixedRate"); - Long delay = (Long) ms.getAttribute(on, "Delay"); - Long period = (Long) ms.getAttribute(on, "Period"); - Long repeatCount = (Long) ms.getAttribute(on, "RepeatCount"); - String runLoggingLevel = (String) ms.getAttribute(on, "RunLoggingLevel"); - - sb.append(String.format("%n Timer Name: %s", timerName)); - sb.append(String.format("%n Polling: %s", polling)); - sb.append(String.format("%n Fixed Rate: %s", fixedRate)); - if (delay != null) { - sb.append(String.format("%n Delay: %s", delay)); - } - if (period != null) { - sb.append(String.format("%n Period: %s", period)); - } - if (repeatCount != null) { - sb.append(String.format("%n Repeat Count: %s", repeatCount)); - } - sb.append(String.format("%n Running Logging Level: %s", runLoggingLevel)); - sb.append(String.format("%n Counter (total: %s)", counter)); - - } - } catch (Exception e) { - // ignore - } - } - } + if (mcc == null) { + return sb.toString(); + } + + for (Route route : getCamelContext().getRoutes()) { + String id = route.getId(); + ManagedConsumerMBean mc = mcc.getManagedConsumer(id); + if (mc == null) { + continue; + } + + if (!sb.isEmpty()) { + sb.append("\n"); } + + appendBasicConsumerInfoText(sb, id, mc); + appendScheduledPollConsumerText(sb, mcc); + appendTimerConsumerText(sb, mc, route); } return sb.toString(); } + private void appendBasicConsumerInfoText(StringBuilder sb, String id, ManagedConsumerMBean mc) { + int inflight = mc.getInflightExchanges() != null ? mc.getInflightExchanges() : 0; + + sb.append(String.format("%n Id: %s", id)); + sb.append(String.format("%n Uri: %s", mc.getEndpointUri())); + sb.append(String.format("%n State: %s", mc.getState())); + sb.append(String.format("%n Class: %s", mc.getServiceType())); + sb.append(String.format("%n Remote: %b", mc.isRemoteEndpoint())); + sb.append(String.format("%n Hosted: %b", mc.isHostedService())); + sb.append(String.format("%n Inflight: %d", inflight)); + } + + private void appendScheduledPollConsumerText(StringBuilder sb, ManagedCamelContext mcc) { + if (!(mcc instanceof ManagedSchedulePollConsumerMBean mpc)) { + return; + } + + sb.append(String.format("%n Polling: %s", mpc.isPolling())); + sb.append(String.format("%n First Poll Done: %s", mpc.isFirstPollDone())); + sb.append(String.format("%n Scheduler Started: %s", mpc.isSchedulerStarted())); + sb.append(String.format("%n Scheduler Class: %s", mpc.getSchedulerClassName())); + sb.append(String.format("%n Repeat Count: %s", mpc.getRepeatCount())); + sb.append(String.format("%n Fixed Delay: %s", mpc.isUseFixedDelay())); + sb.append(String.format("%n Greedy: %s", mpc.isGreedy())); + sb.append(String.format("%n Running Logging Level: %s", mpc.getRunningLoggingLevel())); + sb.append(String.format("%n Send Empty Message When Idle: %s", mpc.isSendEmptyMessageWhenIdle())); + sb.append(String.format("%n Counter (total: %d success: %d error: %d)", + mpc.getCounter(), mpc.getSuccessCounter(), mpc.getErrorCounter())); + sb.append(String.format("%n Delay (initial: %d delay: %d unit: %s)", + mpc.getInitialDelay(), mpc.getDelay(), mpc.getTimeUnit())); + sb.append(String.format( + "\n Backoff(counter: %d multiplier: %d errorThreshold: %d, idleThreshold: %d )", + mpc.getBackoffCounter(), mpc.getBackoffMultiplier(), mpc.getBackoffErrorThreshold(), + mpc.getBackoffIdleThreshold())); + } + + private void appendTimerConsumerText(StringBuilder sb, ManagedConsumerMBean mc, Route route) { + if (!"TimerConsumer".equals(mc.getServiceType())) { + return; + } + + try { + MBeanServer ms = ManagementFactory.getPlatformMBeanServer(); + ObjectName on = getCamelContext().getManagementStrategy().getManagementObjectNameStrategy() + .getObjectNameForConsumer(getCamelContext(), route.getConsumer()); + + if (!ms.isRegistered(on)) { + return; + } + + appendTimerAttributesText(sb, ms, on); + } catch (Exception e) { + // ignore + } + } + + private void appendTimerAttributesText(StringBuilder sb, MBeanServer ms, ObjectName on) throws Exception { + String timerName = (String) ms.getAttribute(on, "TimerName"); + Long counter = (Long) ms.getAttribute(on, "Counter"); + Boolean polling = (Boolean) ms.getAttribute(on, "Polling"); + Boolean fixedRate = (Boolean) ms.getAttribute(on, "FixedRate"); + Long delay = (Long) ms.getAttribute(on, "Delay"); + Long period = (Long) ms.getAttribute(on, "Period"); + Long repeatCount = (Long) ms.getAttribute(on, "RepeatCount"); + String runLoggingLevel = (String) ms.getAttribute(on, "RunLoggingLevel"); + + sb.append(String.format("%n Timer Name: %s", timerName)); + sb.append(String.format("%n Polling: %s", polling)); + sb.append(String.format("%n Fixed Rate: %s", fixedRate)); + if (delay != null) { + sb.append(String.format("%n Delay: %s", delay)); + } + if (period != null) { + sb.append(String.format("%n Period: %s", period)); + } + if (repeatCount != null) { + sb.append(String.format("%n Repeat Count: %s", repeatCount)); + } + sb.append(String.format("%n Running Logging Level: %s", runLoggingLevel)); + sb.append(String.format("%n Counter (total: %s)", counter)); + } + @Override protected JsonObject doCallJson(Map options) { final JsonObject root = new JsonObject(); @@ -136,95 +158,120 @@ protected JsonObject doCallJson(Map options) { root.put("consumers", list); ManagedCamelContext mcc = getCamelContext().getCamelContextExtension().getContextPlugin(ManagedCamelContext.class); - if (mcc != null) { - for (Route route : getCamelContext().getRoutes()) { - String id = route.getId(); - ManagedRouteMBean mr = mcc.getManagedRoute(id); - ManagedConsumerMBean mc = mcc.getManagedConsumer(id); - if (mr != null && mc != null) { - JsonObject jo = new JsonObject(); - Integer inflight = mc.getInflightExchanges(); - if (inflight == null) { - inflight = 0; - } - - jo.put("id", id); - jo.put("uri", mc.getEndpointUri()); - jo.put("state", mc.getState()); - jo.put("class", mc.getServiceType()); - jo.put("remote", mc.isRemoteEndpoint()); - jo.put("hosted", mc.isHostedService()); - jo.put("inflight", inflight); - jo.put("scheduled", false); - if (mcc instanceof ManagedSchedulePollConsumerMBean mpc) { - jo.put("scheduled", true); - jo.put("polling", mpc.isPolling()); - jo.put("firstPollDone", mpc.isFirstPollDone()); - jo.put("schedulerStarted", mpc.isSchedulerStarted()); - jo.put("schedulerClass", mpc.getSchedulerClassName()); - jo.put("repeatCount", mpc.getRepeatCount()); - jo.put("fixedDelay", mpc.isUseFixedDelay()); - jo.put("initialDelay", mpc.getInitialDelay()); - jo.put("delay", mpc.getDelay()); - jo.put("timeUnit", mpc.getTimeUnit()); - jo.put("greedy", mpc.isGreedy()); - jo.put("runningLoggingLevel", mpc.getRunningLoggingLevel()); - jo.put("totalCounter", mpc.getCounter()); - jo.put("errorCounter", mpc.getErrorCounter()); - jo.put("successCounter", mpc.getSuccessCounter()); - jo.put("backoffCounter", mpc.getBackoffCounter()); - jo.put("backoffMultiplier", mpc.getBackoffMultiplier()); - jo.put("backoffErrorThreshold", mpc.getBackoffErrorThreshold()); - jo.put("backoffIdleThreshold", mpc.getBackoffIdleThreshold()); - } - if ("TimerConsumer".equals(mc.getServiceType())) { - jo.put("scheduled", true); - // need to use JMX to gather details for camel-timer consumer - try { - MBeanServer ms = ManagementFactory.getPlatformMBeanServer(); - ObjectName on = getCamelContext().getManagementStrategy().getManagementObjectNameStrategy() - .getObjectNameForConsumer(getCamelContext(), - route.getConsumer()); - if (ms.isRegistered(on)) { - String timerName = (String) ms.getAttribute(on, "TimerName"); - Long counter = (Long) ms.getAttribute(on, "Counter"); - Boolean polling = (Boolean) ms.getAttribute(on, "Polling"); - Boolean fixedRate = (Boolean) ms.getAttribute(on, "FixedRate"); - Long delay = (Long) ms.getAttribute(on, "Delay"); - Long period = (Long) ms.getAttribute(on, "Period"); - Long repeatCount = (Long) ms.getAttribute(on, "RepeatCount"); - String runLoggingLevel = (String) ms.getAttribute(on, "RunLoggingLevel"); - - jo.put("timerName", timerName); - jo.put("polling", polling); - jo.put("fixedRate", fixedRate); - if (delay != null) { - jo.put("delay", delay); - } - if (period != null) { - jo.put("period", period); - } - if (repeatCount != null) { - jo.put("repeatCount", repeatCount); - } - jo.put("runningLoggingLevel", runLoggingLevel); - jo.put("totalCounter", counter); - } - } catch (Exception e) { - // ignore - } - } - final JsonObject stats = toJsonObject(mr); - jo.put("statistics", stats); - - list.add(jo); - } + if (mcc == null) { + return root; + } + + for (Route route : getCamelContext().getRoutes()) { + String id = route.getId(); + ManagedRouteMBean mr = mcc.getManagedRoute(id); + ManagedConsumerMBean mc = mcc.getManagedConsumer(id); + + if (mr == null || mc == null) { + continue; } + + JsonObject jo = buildBasicConsumerJson(id, mc); + addScheduledPollConsumerJson(jo, mcc); + addTimerConsumerJson(jo, mc, route); + jo.put("statistics", toJsonObject(mr)); + + list.add(jo); } return root; } + private JsonObject buildBasicConsumerJson(String id, ManagedConsumerMBean mc) { + JsonObject jo = new JsonObject(); + int inflight = mc.getInflightExchanges() != null ? mc.getInflightExchanges() : 0; + + jo.put("id", id); + jo.put("uri", mc.getEndpointUri()); + jo.put("state", mc.getState()); + jo.put("class", mc.getServiceType()); + jo.put("remote", mc.isRemoteEndpoint()); + jo.put("hosted", mc.isHostedService()); + jo.put("inflight", inflight); + jo.put("scheduled", false); + + return jo; + } + + private void addScheduledPollConsumerJson(JsonObject jo, ManagedCamelContext mcc) { + if (!(mcc instanceof ManagedSchedulePollConsumerMBean mpc)) { + return; + } + + jo.put("scheduled", true); + jo.put("polling", mpc.isPolling()); + jo.put("firstPollDone", mpc.isFirstPollDone()); + jo.put("schedulerStarted", mpc.isSchedulerStarted()); + jo.put("schedulerClass", mpc.getSchedulerClassName()); + jo.put("repeatCount", mpc.getRepeatCount()); + jo.put("fixedDelay", mpc.isUseFixedDelay()); + jo.put("initialDelay", mpc.getInitialDelay()); + jo.put("delay", mpc.getDelay()); + jo.put("timeUnit", mpc.getTimeUnit()); + jo.put("greedy", mpc.isGreedy()); + jo.put("runningLoggingLevel", mpc.getRunningLoggingLevel()); + jo.put("totalCounter", mpc.getCounter()); + jo.put("errorCounter", mpc.getErrorCounter()); + jo.put("successCounter", mpc.getSuccessCounter()); + jo.put("backoffCounter", mpc.getBackoffCounter()); + jo.put("backoffMultiplier", mpc.getBackoffMultiplier()); + jo.put("backoffErrorThreshold", mpc.getBackoffErrorThreshold()); + jo.put("backoffIdleThreshold", mpc.getBackoffIdleThreshold()); + } + + private void addTimerConsumerJson(JsonObject jo, ManagedConsumerMBean mc, Route route) { + if (!"TimerConsumer".equals(mc.getServiceType())) { + return; + } + + jo.put("scheduled", true); + + try { + MBeanServer ms = ManagementFactory.getPlatformMBeanServer(); + ObjectName on = getCamelContext().getManagementStrategy().getManagementObjectNameStrategy() + .getObjectNameForConsumer(getCamelContext(), route.getConsumer()); + + if (!ms.isRegistered(on)) { + return; + } + + addTimerAttributesJson(jo, ms, on); + } catch (Exception e) { + // ignore + } + } + + private void addTimerAttributesJson(JsonObject jo, MBeanServer ms, ObjectName on) throws Exception { + String timerName = (String) ms.getAttribute(on, "TimerName"); + Long counter = (Long) ms.getAttribute(on, "Counter"); + Boolean polling = (Boolean) ms.getAttribute(on, "Polling"); + Boolean fixedRate = (Boolean) ms.getAttribute(on, "FixedRate"); + Long delay = (Long) ms.getAttribute(on, "Delay"); + Long period = (Long) ms.getAttribute(on, "Period"); + Long repeatCount = (Long) ms.getAttribute(on, "RepeatCount"); + String runLoggingLevel = (String) ms.getAttribute(on, "RunLoggingLevel"); + + jo.put("timerName", timerName); + jo.put("polling", polling); + jo.put("fixedRate", fixedRate); + if (delay != null) { + jo.put("delay", delay); + } + if (period != null) { + jo.put("period", period); + } + if (repeatCount != null) { + jo.put("repeatCount", repeatCount); + } + jo.put("runningLoggingLevel", runLoggingLevel); + jo.put("totalCounter", counter); + } + private static JsonObject toJsonObject(ManagedRouteMBean mr) { JsonObject stats = new JsonObject(); stats.put("idleSince", mr.getIdleSince()); diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java index b104700afc1fa..3a31b105f0ac3 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java @@ -112,89 +112,110 @@ private void doCommand(String command, String breakpoint, int position) { return; } - if ("enable".equalsIgnoreCase(command)) { - backlog.enableDebugger(); - } else if ("disable".equalsIgnoreCase(command)) { - backlog.disableDebugger(); - } else if ("attach".equalsIgnoreCase(command)) { - backlog.attach(); - } else if ("detach".equalsIgnoreCase(command)) { - backlog.detach(); - } else if ("resume".equalsIgnoreCase(command)) { - backlog.resumeAll(); - } else if ("step".equalsIgnoreCase(command)) { - if (ObjectHelper.isNotEmpty(breakpoint)) { - backlog.stepBreakpoint(breakpoint); - } else { - if (position < 1 || !stepToPosition(backlog, position)) { - // if we cannot successfully step to a position we must do a step - backlog.stepBreakpoint(); - } + String cmd = command.toLowerCase(); + switch (cmd) { + case "enable" -> backlog.enableDebugger(); + case "disable" -> backlog.disableDebugger(); + case "attach" -> backlog.attach(); + case "detach" -> backlog.detach(); + case "resume" -> backlog.resumeAll(); + case "step" -> executeStepCommand(backlog, breakpoint, position); + case "stepover" -> backlog.stepOver(); + case "skipover" -> backlog.skipOver(); + case "add" -> executeAddCommand(backlog, breakpoint); + case "remove" -> executeRemoveCommand(backlog, breakpoint); + default -> { } - } else if ("stepover".equalsIgnoreCase(command)) { - backlog.stepOver(); - } else if ("skipover".equalsIgnoreCase(command)) { - backlog.skipOver(); - } else if ("add".equalsIgnoreCase(command) && ObjectHelper.isNotEmpty(breakpoint)) { + } + } + + private void executeStepCommand(BacklogDebugger backlog, String breakpoint, int position) { + if (ObjectHelper.isNotEmpty(breakpoint)) { + backlog.stepBreakpoint(breakpoint); + return; + } + if (position < 1 || !stepToPosition(backlog, position)) { + backlog.stepBreakpoint(); + } + } + + private void executeAddCommand(BacklogDebugger backlog, String breakpoint) { + if (ObjectHelper.isNotEmpty(breakpoint)) { backlog.addBreakpoint(breakpoint); - } else if ("remove".equalsIgnoreCase(command)) { - if (ObjectHelper.isNotEmpty(breakpoint)) { - backlog.removeBreakpoint(breakpoint); - } else { - backlog.removeAllBreakpoints(); - } } } - private boolean stepToPosition(BacklogDebugger backlog, int position) { - if (position < 1) { - return false; + private void executeRemoveCommand(BacklogDebugger backlog, String breakpoint) { + if (ObjectHelper.isNotEmpty(breakpoint)) { + backlog.removeBreakpoint(breakpoint); + } else { + backlog.removeAllBreakpoints(); } - if (!backlog.isSingleStepMode()) { + } + + private boolean stepToPosition(BacklogDebugger backlog, int position) { + if (!canStepToPosition(backlog, position)) { return false; } - if (backlog.getSuspendedBreakpointNodeIds().size() != 1) { + + String id = backlog.getSuspendedBreakpointNodeIds().iterator().next(); + int diff = calculateStepDifference(backlog, id, position); + if (diff <= 0) { return false; } - String id = backlog.getSuspendedBreakpointNodeIds().iterator().next(); + + return executeSteps(backlog, diff); + } + + private boolean canStepToPosition(BacklogDebugger backlog, int position) { + return position >= 1 + && backlog.isSingleStepMode() + && backlog.getSuspendedBreakpointNodeIds().size() == 1; + } + + private int calculateStepDifference(BacklogDebugger backlog, String id, int position) { Exchange exchange = backlog.getSuspendedExchange(id); if (exchange == null) { - return false; + return -1; } List list = exchange.getProperty(ExchangePropertyKey.MESSAGE_HISTORY, List.class); if (list == null) { - return false; - } - int diff = position - list.size() + 1; - if (diff <= 0) { - return false; + return -1; } + return position - list.size() + 1; + } + private boolean executeSteps(BacklogDebugger backlog, int diff) { StopWatch watch = new StopWatch(); for (int i = 0; i < diff; i++) { - // if there are no suspended then exit if (backlog.getSuspendedBreakpointNodeIds().isEmpty()) { return true; } - // stop when we hit last - id = backlog.getSuspendedBreakpointNodeIds().iterator().next(); + + String id = backlog.getSuspendedBreakpointNodeIds().iterator().next(); var msg = backlog.getSuspendedBreakpointMessage(id); if (msg.isLast()) { return true; } - // go to next and wait for debugger to suspend again - watch.restart(); - backlog.stepBreakpoint(); - while (backlog.isSingleStepMode() && backlog.getSuspendedBreakpointNodeIds().isEmpty()) { - if (watch.taken() > 10000) { - return false; - } - try { - Thread.sleep(10); - } catch (Exception e) { - // ignore - } + if (!stepAndWait(backlog, watch)) { + return false; + } + } + return true; + } + + private boolean stepAndWait(BacklogDebugger backlog, StopWatch watch) { + watch.restart(); + backlog.stepBreakpoint(); + while (backlog.isSingleStepMode() && backlog.getSuspendedBreakpointNodeIds().isEmpty()) { + if (watch.taken() > 10000) { + return false; + } + try { + Thread.sleep(10); + } catch (Exception e) { + // ignore } } return true; diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/MessageHistoryDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/MessageHistoryDevConsole.java index 86cbad4729452..d3bf821714772 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/MessageHistoryDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/MessageHistoryDevConsole.java @@ -63,38 +63,47 @@ protected String doCallText(Map options) { protected JsonObject doCallJson(Map options) { JsonObject root = new JsonObject(); - String codeLimit = (String) options.getOrDefault(CODE_LIMIT, "5"); + int limit = Integer.parseInt((String) options.getOrDefault(CODE_LIMIT, "5")); BacklogTracer tracer = getCamelContext().getCamelContextExtension().getContextPlugin(BacklogTracer.class); - if (tracer != null) { - JsonArray arr = new JsonArray(); - - Collection queue = tracer.getLatestMessageHistory(); - for (BacklogTracerEventMessage t : queue) { - JsonObject to = (JsonObject) t.asJSon(); - - // enrich with source code +/- lines around location - int limit = Integer.parseInt(codeLimit); - if (limit > 0) { - String rid = to.getString("routeId"); - String loc = to.getString("location"); - if (rid != null) { - List code = enrichSourceCode(rid, loc, limit); - if (code != null && !code.isEmpty()) { - to.put("code", code); - } - } - } + if (tracer == null) { + return root; + } - arr.add(to); - } - root.put("name", getCamelContext().getName()); - root.put("traces", arr); + JsonArray arr = new JsonArray(); + Collection queue = tracer.getLatestMessageHistory(); + for (BacklogTracerEventMessage t : queue) { + arr.add(processTraceMessage(t, limit)); } + root.put("name", getCamelContext().getName()); + root.put("traces", arr); return root; } + private JsonObject processTraceMessage(BacklogTracerEventMessage t, int codeLimit) { + JsonObject to = (JsonObject) t.asJSon(); + + if (codeLimit > 0) { + addSourceCodeToTrace(to, codeLimit); + } + + return to; + } + + private void addSourceCodeToTrace(JsonObject to, int limit) { + String rid = to.getString("routeId"); + String loc = to.getString("location"); + if (rid == null) { + return; + } + + List code = enrichSourceCode(rid, loc, limit); + if (code != null && !code.isEmpty()) { + to.put("code", code); + } + } + private List enrichSourceCode(String routeId, String location, int lines) { Route route = getCamelContext().getRoute(routeId); if (route == null) { diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/ProcessorDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/ProcessorDevConsole.java index 042dc628afcd4..85f5b04e2df82 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/ProcessorDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/ProcessorDevConsole.java @@ -121,65 +121,76 @@ public static void includeProcessorsText( return; } sb.append("\n"); - sb.append(String.format("%n Route Id: %s", mp.getRouteId())); - sb.append(String.format("%n Id: %s", mp.getProcessorId())); - if (mp.getNodePrefixId() != null) { - sb.append(String.format("%n Node Prefix Id: %s", mp.getNodePrefixId())); - } - if (mp.getDescription() != null) { - sb.append(String.format("%n Description: %s", mp.getDescription())); - } - if (mp.getNote() != null) { - sb.append(String.format("%n Note: %s", mp.getNote())); - } - sb.append(String.format("%n Processor: %s", mp.getProcessorName())); - if (mp.getStepId() != null) { - sb.append(String.format("%n Step Id: %s", mp.getStepId())); - } - sb.append(String.format("%n Level: %d", mp.getLevel())); - if (mp.getSourceLocation() != null) { - String loc = mp.getSourceLocation(); - if (mp.getSourceLineNumber() != null) { - loc += ":" + mp.getSourceLineNumber(); - } - sb.append(String.format("%n Source: %s", loc)); - } + outputProcessorBasicInfoText(sb, mp); + outputProcessorSourceText(sb, mp); + outputProcessorDestinationText(sb, camelContext, mp); + outputProcessorStateText(sb, mp); + outputProcessorStatsText(sb, mp); + } + } - // processors which can send to a destination (such as to/toD/poll etc) - String destination = getDestination(camelContext, mp); - if (destination != null) { - sb.append(String.format("%n Uri: %s", destination)); - } + private static void outputProcessorBasicInfoText(StringBuilder sb, ManagedProcessorMBean mp) { + sb.append(String.format("%n Route Id: %s", mp.getRouteId())); + sb.append(String.format("%n Id: %s", mp.getProcessorId())); + appendOptionalText(sb, "Node Prefix Id", mp.getNodePrefixId()); + appendOptionalText(sb, "Description", mp.getDescription()); + appendOptionalText(sb, "Note", mp.getNote()); + sb.append(String.format("%n Processor: %s", mp.getProcessorName())); + appendOptionalText(sb, "Step Id", mp.getStepId()); + sb.append(String.format("%n Level: %d", mp.getLevel())); + } - sb.append(String.format("%n State: %s", mp.getState())); - sb.append(String.format("%n Disabled: %s", mp.getDisabled())); - sb.append(String.format("%n Total: %s", mp.getExchangesTotal())); - sb.append(String.format("%n Failed: %s", mp.getExchangesFailed())); - sb.append(String.format("%n Inflight: %s", mp.getExchangesInflight())); - long idle = mp.getIdleSince(); - if (idle > 0) { - sb.append(String.format("%n Idle Since: %s", TimeUtils.printDuration(idle))); - } else { - sb.append(String.format("%n Idle Since: %s", "")); - } - sb.append(String.format("%n Mean Time: %s", TimeUtils.printDuration(mp.getMeanProcessingTime(), true))); - sb.append(String.format("%n Max Time: %s", TimeUtils.printDuration(mp.getMaxProcessingTime(), true))); - sb.append(String.format("%n Min Time: %s", TimeUtils.printDuration(mp.getMinProcessingTime(), true))); - if (mp.getExchangesTotal() > 0) { - sb.append(String.format("%n Last Time: %s", TimeUtils.printDuration(mp.getLastProcessingTime(), true))); - sb.append( - String.format("%n Delta Time: %s", TimeUtils.printDuration(mp.getDeltaProcessingTime(), true))); - } - Date last = mp.getLastExchangeCompletedTimestamp(); - if (last != null) { - String ago = TimeUtils.printSince(last.getTime()); - sb.append(String.format("%n Since Last Completed: %s", ago)); - } - last = mp.getLastExchangeFailureTimestamp(); - if (last != null) { - String ago = TimeUtils.printSince(last.getTime()); - sb.append(String.format("%n Since Last Failed: %s", ago)); - } + private static void outputProcessorSourceText(StringBuilder sb, ManagedProcessorMBean mp) { + if (mp.getSourceLocation() == null) { + return; + } + String loc = mp.getSourceLocation(); + if (mp.getSourceLineNumber() != null) { + loc += ":" + mp.getSourceLineNumber(); + } + sb.append(String.format("%n Source: %s", loc)); + } + + private static void outputProcessorDestinationText(StringBuilder sb, CamelContext camelContext, ManagedProcessorMBean mp) { + String destination = getDestination(camelContext, mp); + if (destination != null) { + sb.append(String.format("%n Uri: %s", destination)); + } + } + + private static void outputProcessorStateText(StringBuilder sb, ManagedProcessorMBean mp) { + sb.append(String.format("%n State: %s", mp.getState())); + sb.append(String.format("%n Disabled: %s", mp.getDisabled())); + sb.append(String.format("%n Total: %s", mp.getExchangesTotal())); + sb.append(String.format("%n Failed: %s", mp.getExchangesFailed())); + sb.append(String.format("%n Inflight: %s", mp.getExchangesInflight())); + } + + private static void outputProcessorStatsText(StringBuilder sb, ManagedProcessorMBean mp) { + long idle = mp.getIdleSince(); + sb.append(String.format("%n Idle Since: %s", idle > 0 ? TimeUtils.printDuration(idle) : "")); + sb.append(String.format("%n Mean Time: %s", TimeUtils.printDuration(mp.getMeanProcessingTime(), true))); + sb.append(String.format("%n Max Time: %s", TimeUtils.printDuration(mp.getMaxProcessingTime(), true))); + sb.append(String.format("%n Min Time: %s", TimeUtils.printDuration(mp.getMinProcessingTime(), true))); + + if (mp.getExchangesTotal() > 0) { + sb.append(String.format("%n Last Time: %s", TimeUtils.printDuration(mp.getLastProcessingTime(), true))); + sb.append(String.format("%n Delta Time: %s", TimeUtils.printDuration(mp.getDeltaProcessingTime(), true))); + } + + Date lastCompleted = mp.getLastExchangeCompletedTimestamp(); + if (lastCompleted != null) { + sb.append(String.format("%n Since Last Completed: %s", TimeUtils.printSince(lastCompleted.getTime()))); + } + Date lastFailed = mp.getLastExchangeFailureTimestamp(); + if (lastFailed != null) { + sb.append(String.format("%n Since Last Failed: %s", TimeUtils.printSince(lastFailed.getTime()))); + } + } + + private static void appendOptionalText(StringBuilder sb, String label, String value) { + if (value != null) { + sb.append(String.format("%n %s: %s", label, value)); } } @@ -235,79 +246,110 @@ private void includeProcessorsJson(ManagedRouteMBean mrb, JsonArray arr, String public static void includeProcessorsJSon( CamelContext camelContext, JsonArray arr, int max, List mps) { for (int i = 0; i < mps.size(); i++) { - ManagedProcessorMBean mp = mps.get(i); if (arr.size() > max) { return; } - JsonObject jo = new JsonObject(); + + ManagedProcessorMBean mp = mps.get(i); + ManagedProcessorMBean nextMp = i < mps.size() - 1 ? mps.get(i + 1) : null; + + JsonObject jo = buildProcessorJson(camelContext, mp, nextMp); arr.add(jo); + } + } - jo.put("routeId", mp.getRouteId()); - jo.put("id", mp.getProcessorId()); - if (mp.getNodePrefixId() != null) { - jo.put("nodePrefixId", mp.getNodePrefixId()); - } - if (mp.getDescription() != null) { - jo.put("description", mp.getDescription()); - } - if (mp.getNote() != null) { - jo.put("note", mp.getNote()); - } - if (mp.getSourceLocation() != null) { - String loc = mp.getSourceLocation(); - if (mp.getSourceLineNumber() != null) { - loc += ":" + mp.getSourceLineNumber(); - } - jo.put("source", loc); - } - jo.put("state", mp.getState()); - jo.put("disabled", mp.getDisabled()); - if (mp.getStepId() != null) { - jo.put("stepId", mp.getStepId()); - } + private static JsonObject buildProcessorJson( + CamelContext camelContext, ManagedProcessorMBean mp, ManagedProcessorMBean nextMp) { + JsonObject jo = new JsonObject(); - // calculate end line number - ManagedProcessorMBean mp2 = i < mps.size() - 1 ? mps.get(i + 1) : null; - Integer end = mp2 != null ? mp2.getSourceLineNumber() : null; - if (mp.getSourceLineNumber() != null) { - if (end == null) { - end = mp.getSourceLineNumber() + 5; - } else { - // clip so we do not read ahead to far, as we just want a snippet of the source code - end = Math.min(mp.getSourceLineNumber() + 5, end); - } - } + addProcessorBasicInfoJson(jo, mp); + addProcessorSourceJson(jo, mp); + addProcessorCodeSnippetJson(jo, camelContext, mp, nextMp); + addProcessorDestinationJson(jo, camelContext, mp); + jo.put("statistics", getStatsObject(mp)); - JsonArray ca = new JsonArray(); - List lines - = ConsoleHelper.loadSourceLines(camelContext, mp.getSourceLocation(), mp.getSourceLineNumber(), end); - Integer pos = mp.getSourceLineNumber(); - for (String line : lines) { - JsonObject c = new JsonObject(); - c.put("line", pos); - c.put("code", Jsoner.escape(line)); - if (pos != null && pos.equals(mp.getSourceLineNumber())) { - c.put("match", true); - } - ca.add(c); - if (pos != null) { - pos++; - } + return jo; + } + + private static void addProcessorBasicInfoJson(JsonObject jo, ManagedProcessorMBean mp) { + jo.put("routeId", mp.getRouteId()); + jo.put("id", mp.getProcessorId()); + putIfNotNull(jo, "nodePrefixId", mp.getNodePrefixId()); + putIfNotNull(jo, "description", mp.getDescription()); + putIfNotNull(jo, "note", mp.getNote()); + jo.put("state", mp.getState()); + jo.put("disabled", mp.getDisabled()); + putIfNotNull(jo, "stepId", mp.getStepId()); + jo.put("processor", mp.getProcessorName()); + jo.put("level", mp.getLevel()); + } + + private static void addProcessorSourceJson(JsonObject jo, ManagedProcessorMBean mp) { + if (mp.getSourceLocation() == null) { + return; + } + String loc = mp.getSourceLocation(); + if (mp.getSourceLineNumber() != null) { + loc += ":" + mp.getSourceLineNumber(); + } + jo.put("source", loc); + } + + private static void addProcessorCodeSnippetJson( + JsonObject jo, CamelContext camelContext, ManagedProcessorMBean mp, ManagedProcessorMBean nextMp) { + if (mp.getSourceLineNumber() == null) { + return; + } + + Integer end = calculateCodeSnippetEndLine(mp, nextMp); + List lines = ConsoleHelper.loadSourceLines(camelContext, mp.getSourceLocation(), mp.getSourceLineNumber(), end); + + if (lines.isEmpty()) { + return; + } + + JsonArray ca = buildCodeLinesArray(lines, mp.getSourceLineNumber()); + if (!ca.isEmpty()) { + jo.put("code", ca); + } + } + + private static Integer calculateCodeSnippetEndLine(ManagedProcessorMBean mp, ManagedProcessorMBean nextMp) { + Integer nextLine = nextMp != null ? nextMp.getSourceLineNumber() : null; + if (nextLine == null) { + return mp.getSourceLineNumber() + 5; + } + return Math.min(mp.getSourceLineNumber() + 5, nextLine); + } + + private static JsonArray buildCodeLinesArray(List lines, Integer startLine) { + JsonArray ca = new JsonArray(); + Integer pos = startLine; + for (String line : lines) { + JsonObject c = new JsonObject(); + c.put("line", pos); + c.put("code", Jsoner.escape(line)); + if (pos != null && pos.equals(startLine)) { + c.put("match", true); } - if (!ca.isEmpty()) { - jo.put("code", ca); + ca.add(c); + if (pos != null) { + pos++; } - jo.put("processor", mp.getProcessorName()); - jo.put("level", mp.getLevel()); + } + return ca; + } - // processors which can send to a destination (such as to/toD/poll etc) - String destination = getDestination(camelContext, mp); - if (destination != null) { - jo.put("uri", destination); - } + private static void addProcessorDestinationJson(JsonObject jo, CamelContext camelContext, ManagedProcessorMBean mp) { + String destination = getDestination(camelContext, mp); + if (destination != null) { + jo.put("uri", destination); + } + } - final JsonObject stats = getStatsObject(mp); - jo.put("statistics", stats); + private static void putIfNotNull(JsonObject jo, String key, Object value) { + if (value != null) { + jo.put(key, value); } } @@ -366,13 +408,21 @@ private static boolean accept(ManagedProcessorMBean mrb, String filter) { } protected void doAction(CamelContext camelContext, String command, String filter) { - if (filter == null) { - filter = "*"; + String effectiveFilter = filter != null ? filter : "*"; + String[] patterns = effectiveFilter.split(","); + + List mps = collectAllProcessors(); + List matchingProcessors = filterProcessorsByPattern(mps, patterns); + + for (ManagedProcessorMBean mp : matchingProcessors) { + executeCommand(command, mp); } - String[] patterns = filter.split(","); + } + private List collectAllProcessors() { List mps = new ArrayList<>(); ManagedCamelContext mcc = getCamelContext().getCamelContextExtension().getContextPlugin(ManagedCamelContext.class); + for (Route r : getCamelContext().getRoutes()) { ManagedRouteMBean mrb = mcc.getManagedRoute(r.getRouteId()); try { @@ -383,35 +433,38 @@ protected void doAction(CamelContext camelContext, String command, String filter // ignore } } + return mps; + } - // find matching IDs - mps = mps.stream() - .filter(mp -> { - for (String p : patterns) { - if (PatternHelper.matchPattern(mp.getProcessorId(), p) - || PatternHelper.matchPattern(mp.getRouteId(), p)) { - return true; - } - } - return false; - }) + private List filterProcessorsByPattern(List mps, String[] patterns) { + return mps.stream() + .filter(mp -> matchesAnyPattern(mp, patterns)) .toList(); + } - for (ManagedProcessorMBean mp : mps) { - try { - if ("start".equals(command)) { - mp.start(); - } else if ("stop".equals(command)) { - mp.stop(); - } else if ("disable".equals(command)) { - mp.disable(); - } else if ("enable".equals(command)) { - mp.enable(); + private boolean matchesAnyPattern(ManagedProcessorMBean mp, String[] patterns) { + for (String p : patterns) { + if (PatternHelper.matchPattern(mp.getProcessorId(), p) + || PatternHelper.matchPattern(mp.getRouteId(), p)) { + return true; + } + } + return false; + } + + private void executeCommand(String command, ManagedProcessorMBean mp) { + try { + switch (command) { + case "start" -> mp.start(); + case "stop" -> mp.stop(); + case "disable" -> mp.disable(); + case "enable" -> mp.enable(); + default -> { } - } catch (Exception e) { - LOG.warn("Error {} processor: {} due to: {}. This exception is ignored.", command, mp.getProcessorId(), - e.getMessage(), e); } + } catch (Exception e) { + LOG.warn("Error {} processor: {} due to: {}. This exception is ignored.", command, mp.getProcessorId(), + e.getMessage(), e); } } diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/ProducerDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/ProducerDevConsole.java index 046bce7898152..3bcb1b1aa1870 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/ProducerDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/ProducerDevConsole.java @@ -41,77 +41,83 @@ public ProducerDevConsole() { protected String doCallText(Map options) { StringBuilder sb = new StringBuilder(); - MBeanServer mbeanServer = getCamelContext().getManagementStrategy().getManagementAgent().getMBeanServer(); - if (mbeanServer != null) { - try { - String jmxDomain - = getCamelContext().getManagementStrategy().getManagementAgent().getMBeanObjectDomainName(); - String prefix - = getCamelContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; - ObjectName query = ObjectName.getInstance( - jmxDomain + ":context=" + prefix + getCamelContext().getManagementName() + ",type=producers,*"); - Set set = mbeanServer.queryNames(query, null); - if (set != null && !set.isEmpty()) { - for (ObjectName on : set) { - ManagedProducerMBean mp = getManagedProducer(getCamelContext(), on); - if (!sb.isEmpty()) { - sb.append("\n"); - } - sb.append(String.format("%n Uri: %s", mp.getEndpointUri())); - sb.append(String.format("%n State: %s", mp.getState())); - sb.append(String.format("%n Class: %s", mp.getServiceType())); - sb.append(String.format("%n Remote: %b", mp.isRemoteEndpoint())); - sb.append(String.format("%n Singleton: %b", mp.isSingleton())); - if (mp.getRouteId() != null) { - sb.append(String.format("%n Route Id: %s", mp.getRouteId())); - } - } - } - } catch (Exception e) { - // ignore + Set producers = queryProducerMBeans(); + if (producers == null) { + return sb.toString(); + } + + for (ObjectName on : producers) { + ManagedProducerMBean mp = getManagedProducer(getCamelContext(), on); + if (!sb.isEmpty()) { + sb.append("\n"); } + appendProducerText(sb, mp); } + return sb.toString(); } + private void appendProducerText(StringBuilder sb, ManagedProducerMBean mp) { + sb.append(String.format("%n Uri: %s", mp.getEndpointUri())); + sb.append(String.format("%n State: %s", mp.getState())); + sb.append(String.format("%n Class: %s", mp.getServiceType())); + sb.append(String.format("%n Remote: %b", mp.isRemoteEndpoint())); + sb.append(String.format("%n Singleton: %b", mp.isSingleton())); + if (mp.getRouteId() != null) { + sb.append(String.format("%n Route Id: %s", mp.getRouteId())); + } + } + @Override protected JsonObject doCallJson(Map options) { final JsonObject root = new JsonObject(); final List list = new ArrayList<>(); root.put("producers", list); - MBeanServer mbeanServer = getCamelContext().getManagementStrategy().getManagementAgent().getMBeanServer(); - if (mbeanServer != null) { - try { - String jmxDomain - = getCamelContext().getManagementStrategy().getManagementAgent().getMBeanObjectDomainName(); - String prefix - = getCamelContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; - ObjectName query = ObjectName.getInstance( - jmxDomain + ":context=" + prefix + getCamelContext().getManagementName() + ",type=producers,*"); - Set set = mbeanServer.queryNames(query, null); - if (set != null && !set.isEmpty()) { - for (ObjectName on : set) { - ManagedProducerMBean mp = getManagedProducer(getCamelContext(), on); - JsonObject jo = new JsonObject(); - jo.put("uri", mp.getEndpointUri()); - jo.put("state", mp.getState()); - jo.put("class", mp.getServiceType()); - jo.put("remote", mp.isRemoteEndpoint()); - jo.put("singleton", mp.isSingleton()); - if (mp.getRouteId() != null) { - jo.put("routeId", mp.getRouteId()); - } - list.add(jo); - } - } - } catch (Exception e) { - // ignore - } + Set producers = queryProducerMBeans(); + if (producers == null) { + return root; + } + + for (ObjectName on : producers) { + ManagedProducerMBean mp = getManagedProducer(getCamelContext(), on); + list.add(buildProducerJson(mp)); } + return root; } + private JsonObject buildProducerJson(ManagedProducerMBean mp) { + JsonObject jo = new JsonObject(); + jo.put("uri", mp.getEndpointUri()); + jo.put("state", mp.getState()); + jo.put("class", mp.getServiceType()); + jo.put("remote", mp.isRemoteEndpoint()); + jo.put("singleton", mp.isSingleton()); + if (mp.getRouteId() != null) { + jo.put("routeId", mp.getRouteId()); + } + return jo; + } + + private Set queryProducerMBeans() { + MBeanServer mbeanServer = getCamelContext().getManagementStrategy().getManagementAgent().getMBeanServer(); + if (mbeanServer == null) { + return null; + } + + try { + String jmxDomain = getCamelContext().getManagementStrategy().getManagementAgent().getMBeanObjectDomainName(); + String prefix = getCamelContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; + ObjectName query = ObjectName.getInstance( + jmxDomain + ":context=" + prefix + getCamelContext().getManagementName() + ",type=producers,*"); + Set set = mbeanServer.queryNames(query, null); + return (set != null && !set.isEmpty()) ? set : null; + } catch (Exception e) { + return null; + } + } + private static ManagedProducerMBean getManagedProducer(CamelContext camelContext, ObjectName on) { return camelContext.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedProducerMBean.class); } diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/ReceiveDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/ReceiveDevConsole.java index 81946c834198c..6adad482401d5 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/ReceiveDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/ReceiveDevConsole.java @@ -280,66 +280,81 @@ private void addMessage(Exchange exchange) { } protected static Endpoint findMatchingEndpoint(CamelContext camelContext, String endpoint) { - Endpoint target = null; boolean scheme = endpoint.contains(":"); boolean pattern = endpoint.endsWith("*"); - if (!scheme || pattern) { - if (!scheme && !endpoint.endsWith("*")) { - endpoint = endpoint + "*"; + + if (scheme && !pattern) { + return findDirectEndpoint(camelContext, endpoint); + } + + return findEndpointViaJmx(camelContext, endpoint, scheme); + } + + private static Endpoint findDirectEndpoint(CamelContext camelContext, String endpoint) { + Endpoint target = camelContext.getEndpoint(endpoint); + org.apache.camel.spi.UriEndpoint ann = ObjectHelper.getAnnotationDeep(target, org.apache.camel.spi.UriEndpoint.class); + if (ann != null && ann.producerOnly()) { + throw new IllegalArgumentException("Cannot consume from endpoint: " + endpoint); + } + return target; + } + + private static Endpoint findEndpointViaJmx(CamelContext camelContext, String endpoint, boolean scheme) { + String searchPattern = scheme || endpoint.endsWith("*") ? endpoint : endpoint + "*"; + + MBeanServer mbeanServer = camelContext.getManagementStrategy().getManagementAgent().getMBeanServer(); + if (mbeanServer == null) { + return null; + } + + try { + Set set = queryProducerMBeans(camelContext, mbeanServer); + if (set == null || set.isEmpty()) { + return null; } - // find all producers for this camel context via JMX mbeans (this allows to find also producers created via dynamic EIPs) - MBeanServer mbeanServer = camelContext.getManagementStrategy().getManagementAgent().getMBeanServer(); - if (mbeanServer != null) { - try { - String jmxDomain - = camelContext.getManagementStrategy().getManagementAgent().getMBeanObjectDomainName(); - String prefix - = camelContext.getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; - ObjectName query = ObjectName.getInstance( - jmxDomain + ":context=" + prefix + camelContext.getManagementName() + ",type=producers,*"); - Set set = mbeanServer.queryNames(query, null); - if (set != null && !set.isEmpty()) { - for (ObjectName on : set) { - String uri = (String) mbeanServer.getAttribute(on, "EndpointUri"); - if (PatternHelper.matchPattern(uri, endpoint)) { - // is the endpoint able to create a consumer - target = camelContext.getEndpoint(uri); - // is the target able to create a consumer - org.apache.camel.spi.UriEndpoint ann - = ObjectHelper.getAnnotationDeep(target, org.apache.camel.spi.UriEndpoint.class); - if (ann != null) { - if (ann.producerOnly()) { - // skip if the endpoint cannot consume (we need to be able to consume to receive) - target = null; - } - if ("*".equals(endpoint) && !ann.remote()) { - // skip internal when matching everything - target = null; - } - } - if (target != null) { - break; - } - } - } - } - } catch (Exception e) { - // ignore - } + return findFirstMatchingEndpoint(camelContext, mbeanServer, set, searchPattern); + } catch (Exception e) { + return null; + } + } + + private static Set queryProducerMBeans(CamelContext camelContext, MBeanServer mbeanServer) throws Exception { + String jmxDomain = camelContext.getManagementStrategy().getManagementAgent().getMBeanObjectDomainName(); + String prefix = camelContext.getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; + ObjectName query = ObjectName.getInstance( + jmxDomain + ":context=" + prefix + camelContext.getManagementName() + ",type=producers,*"); + return mbeanServer.queryNames(query, null); + } + + private static Endpoint findFirstMatchingEndpoint( + CamelContext camelContext, MBeanServer mbeanServer, Set set, String searchPattern) + throws Exception { + for (ObjectName on : set) { + String uri = (String) mbeanServer.getAttribute(on, "EndpointUri"); + if (!PatternHelper.matchPattern(uri, searchPattern)) { + continue; } - } else { - target = camelContext.getEndpoint(endpoint); - // is the target able to create a consumer - org.apache.camel.spi.UriEndpoint ann - = ObjectHelper.getAnnotationDeep(target, org.apache.camel.spi.UriEndpoint.class); - if (ann != null) { - if (ann.producerOnly()) { - // skip if the endpoint cannot consume (we need to be able to consume to receive) - throw new IllegalArgumentException("Cannot consume from endpoint: " + endpoint); - } + + Endpoint target = camelContext.getEndpoint(uri); + if (isValidConsumerEndpoint(target, searchPattern)) { + return target; } } - return target; + return null; + } + + private static boolean isValidConsumerEndpoint(Endpoint target, String searchPattern) { + org.apache.camel.spi.UriEndpoint ann = ObjectHelper.getAnnotationDeep(target, org.apache.camel.spi.UriEndpoint.class); + if (ann == null) { + return true; + } + if (ann.producerOnly()) { + return false; + } + if ("*".equals(searchPattern) && !ann.remote()) { + return false; + } + return true; } } diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/ReloadDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/ReloadDevConsole.java index 14ca45ed3e422..bf7e0f8eaa5d3 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/ReloadDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/ReloadDevConsole.java @@ -56,102 +56,116 @@ protected String doCallText(Map options) { StringBuilder sb = new StringBuilder(); Set rs = getCamelContext().hasServices(ReloadStrategy.class); - boolean failed = false; - for (ReloadStrategy r : rs) { - if (trigger) { - int before = r.getFailedCounter(); - Future f = getOrCreateReloadTask().submit(() -> r.onReload("ReloadDevConsole")); - if (wait) { - try { - f.get(30, TimeUnit.SECONDS); - failed |= r.getFailedCounter() > before; - } catch (Exception e) { - // ignore - } - } - } else { - sb.append(String.format("%nReloadStrategy: %s", r.getClass().getName())); - sb.append(String.format("%n Reloaded: %s", r.getReloadCounter())); - sb.append(String.format("%n Failed: %s", r.getFailedCounter())); - Exception cause = r.getLastError(); - if (cause != null) { - sb.append(String.format("%n Error Message: %s", cause.getMessage())); - final String stackTrace = ExceptionHelper.stackTraceToString(cause); - sb.append("\n\n"); - sb.append(stackTrace); - sb.append("\n\n"); - } - } - } + if (trigger) { - if (wait) { - if (failed) { - sb.append("Status: Reload failed"); - } else { - sb.append("Status: Reload success"); - } - } else { - sb.append("Status: Reloading in progress"); - } + boolean failed = triggerReload(rs, wait); + sb.append(getReloadStatusText(wait, failed)); + } else { + appendReloadStrategiesText(sb, rs); } + sb.append("\n"); return sb.toString(); } + private void appendReloadStrategiesText(StringBuilder sb, Set rs) { + for (ReloadStrategy r : rs) { + sb.append(String.format("%nReloadStrategy: %s", r.getClass().getName())); + sb.append(String.format("%n Reloaded: %s", r.getReloadCounter())); + sb.append(String.format("%n Failed: %s", r.getFailedCounter())); + appendLastErrorText(sb, r.getLastError()); + } + } + + private void appendLastErrorText(StringBuilder sb, Exception cause) { + if (cause == null) { + return; + } + sb.append(String.format("%n Error Message: %s", cause.getMessage())); + final String stackTrace = ExceptionHelper.stackTraceToString(cause); + sb.append("\n\n"); + sb.append(stackTrace); + sb.append("\n\n"); + } + + private String getReloadStatusText(boolean wait, boolean failed) { + if (!wait) { + return "Status: Reloading in progress"; + } + return failed ? "Status: Reload failed" : "Status: Reload success"; + } + protected JsonObject doCallJson(Map options) { boolean trigger = "true".equals(options.getOrDefault(RELOAD, "false")); boolean wait = "true".equals(options.getOrDefault(RELOAD_WAIT, "false")); JsonObject root = new JsonObject(); - JsonArray arr = new JsonArray(); Set rs = getCamelContext().hasServices(ReloadStrategy.class); + + if (trigger) { + boolean failed = triggerReload(rs, wait); + root.put("status", getReloadStatusValue(wait, failed)); + } else { + addReloadStrategiesJson(root, rs); + } + + return root; + } + + private boolean triggerReload(Set rs, boolean wait) { boolean failed = false; for (ReloadStrategy r : rs) { - if (trigger) { - int before = r.getFailedCounter(); - Future f = getOrCreateReloadTask().submit(() -> r.onReload("ReloadDevConsole")); - if (wait) { - try { - f.get(30, TimeUnit.SECONDS); - failed |= r.getFailedCounter() > before; - } catch (Exception e) { - // ignore - } - } - } else { - if (root.isEmpty()) { - root.put("reloadStrategies", arr); - } - JsonObject jo = new JsonObject(); - arr.add(jo); - jo.put("className", r.getClass().getName()); - jo.put("reloaded", r.getReloadCounter()); - jo.put("failed", r.getFailedCounter()); - Throwable cause = r.getLastError(); - if (cause != null) { - JsonObject eo = new JsonObject(); - eo.put("message", cause.getMessage()); - JsonArray arr2 = new JsonArray(); - final String trace = ExceptionHelper.stackTraceToString(cause); - eo.put("stackTrace", arr2); - Collections.addAll(arr2, trace.split("\n")); - jo.put("lastError", eo); + int before = r.getFailedCounter(); + Future f = getOrCreateReloadTask().submit(() -> r.onReload("ReloadDevConsole")); + if (wait) { + try { + f.get(30, TimeUnit.SECONDS); + failed |= r.getFailedCounter() > before; + } catch (Exception e) { + // ignore } } } + return failed; + } - if (trigger) { - if (wait) { - if (failed) { - root.put("status", "failed"); - } else { - root.put("status", "success"); - } - } else { - root.put("status", "reloading"); - } + private String getReloadStatusValue(boolean wait, boolean failed) { + if (!wait) { + return "reloading"; } - return root; + return failed ? "failed" : "success"; + } + + private void addReloadStrategiesJson(JsonObject root, Set rs) { + JsonArray arr = new JsonArray(); + for (ReloadStrategy r : rs) { + arr.add(buildReloadStrategyJson(r)); + } + if (!arr.isEmpty()) { + root.put("reloadStrategies", arr); + } + } + + private JsonObject buildReloadStrategyJson(ReloadStrategy r) { + JsonObject jo = new JsonObject(); + jo.put("className", r.getClass().getName()); + jo.put("reloaded", r.getReloadCounter()); + jo.put("failed", r.getFailedCounter()); + addLastErrorJson(jo, r.getLastError()); + return jo; + } + + private void addLastErrorJson(JsonObject jo, Throwable cause) { + if (cause == null) { + return; + } + JsonObject eo = new JsonObject(); + eo.put("message", cause.getMessage()); + JsonArray arr2 = new JsonArray(); + final String trace = ExceptionHelper.stackTraceToString(cause); + eo.put("stackTrace", arr2); + Collections.addAll(arr2, trace.split("\n")); + jo.put("lastError", eo); } protected ExecutorService getOrCreateReloadTask() { diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/RestDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/RestDevConsole.java index 878b099c363df..221af1b7519c9 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/RestDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/RestDevConsole.java @@ -48,70 +48,74 @@ protected void doInit() throws Exception { protected String doCallText(Map options) { StringBuilder sb = new StringBuilder(); - if (rr != null) { - for (RestRegistry.RestService rs : rr.listAllRestServices()) { - if (!sb.isEmpty()) { - sb.append("\n"); - } - sb.append(String.format("%n Url: %s", rs.getUrl())); - sb.append(String.format("%n Method: %s", rs.getMethod())); - sb.append(String.format("%n State: %s", rs.getState())); - if (rs.getConsumes() != null) { - sb.append(String.format("%n Consumes: %s", rs.getConsumes())); - } - if (rs.getProduces() != null) { - sb.append(String.format("%n Produces: %s", rs.getProduces())); - } - if (rs.getInType() != null) { - sb.append(String.format("%n In Type: %s", rs.getInType())); - } - if (rs.getOutType() != null) { - sb.append(String.format("%n Out Type: %s", rs.getOutType())); - } - if (rs.getDescription() != null) { - sb.append(String.format("%n Description: %s", rs.getDescription())); - } + if (rr == null) { + return sb.toString(); + } + + for (RestRegistry.RestService rs : rr.listAllRestServices()) { + if (!sb.isEmpty()) { + sb.append("\n"); } - sb.append("\n"); + appendRestServiceText(sb, rs); } + sb.append("\n"); return sb.toString(); } + private void appendRestServiceText(StringBuilder sb, RestRegistry.RestService rs) { + sb.append(String.format("%n Url: %s", rs.getUrl())); + sb.append(String.format("%n Method: %s", rs.getMethod())); + sb.append(String.format("%n State: %s", rs.getState())); + appendOptionalText(sb, "Consumes", rs.getConsumes()); + appendOptionalText(sb, "Produces", rs.getProduces()); + appendOptionalText(sb, "In Type", rs.getInType()); + appendOptionalText(sb, "Out Type", rs.getOutType()); + appendOptionalText(sb, "Description", rs.getDescription()); + } + + private void appendOptionalText(StringBuilder sb, String label, String value) { + if (value != null) { + sb.append(String.format("%n %s: %s", label, value)); + } + } + @Override protected Map doCallJson(Map options) { JsonObject root = new JsonObject(); - if (rr != null) { - List list = new ArrayList<>(); - root.put("rests", list); - - for (RestRegistry.RestService rs : rr.listAllRestServices()) { - JsonObject jo = new JsonObject(); - jo.put("url", rs.getUrl()); - jo.put("method", rs.getMethod()); - jo.put("contractFirst", rs.isContractFirst()); - jo.put("state", rs.getState()); - if (rs.getConsumes() != null) { - jo.put("consumes", rs.getConsumes()); - } - if (rs.getProduces() != null) { - jo.put("produces", rs.getProduces()); - } - if (rs.getInType() != null) { - jo.put("inType", rs.getInType()); - } - if (rs.getOutType() != null) { - jo.put("outType", rs.getOutType()); - } - if (rs.getDescription() != null) { - jo.put("description", rs.getDescription()); - } - list.add(jo); - } + if (rr == null) { + return root; + } + + List list = new ArrayList<>(); + root.put("rests", list); + + for (RestRegistry.RestService rs : rr.listAllRestServices()) { + list.add(buildRestServiceJson(rs)); } return root; } + private JsonObject buildRestServiceJson(RestRegistry.RestService rs) { + JsonObject jo = new JsonObject(); + jo.put("url", rs.getUrl()); + jo.put("method", rs.getMethod()); + jo.put("contractFirst", rs.isContractFirst()); + jo.put("state", rs.getState()); + putIfNotNull(jo, "consumes", rs.getConsumes()); + putIfNotNull(jo, "produces", rs.getProduces()); + putIfNotNull(jo, "inType", rs.getInType()); + putIfNotNull(jo, "outType", rs.getOutType()); + putIfNotNull(jo, "description", rs.getDescription()); + return jo; + } + + private void putIfNotNull(JsonObject jo, String key, String value) { + if (value != null) { + jo.put(key, value); + } + } + } diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDevConsole.java index 3c0384da59cf5..b0d63b5f6c41d 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDevConsole.java @@ -439,57 +439,85 @@ private String calculateRouteCoverage(ManagedRouteMBean mrb, boolean percent) { } protected void doAction(CamelContext camelContext, String command, String filter) { - if (filter == null) { - filter = "*"; - } - String[] patterns = filter.split(","); - // find matching IDs + String effectiveFilter = filter != null ? filter : "*"; + String[] patterns = effectiveFilter.split(","); + List ids = camelContext.getRoutes() .stream() - .filter(r -> { - for (String p : patterns) { - String source = r.getRouteId(); - if (p.startsWith("group:")) { - source = r.getGroup(); - p = p.substring(6); - } - if (PatternHelper.matchPattern(source, p)) { - return true; - } - } - return false; - }) - .map(Route::getRouteId).toList(); + .filter(r -> matchesAnyPattern(r, patterns)) + .map(Route::getRouteId) + .toList(); + for (String id : ids) { - try { - if ("start".equals(command)) { - if ("*".equals(id)) { - camelContext.getRouteController().startAllRoutes(); - } else { - camelContext.getRouteController().startRoute(id); - } - } else if ("stop".equals(command)) { - if ("*".equals(id)) { - camelContext.getRouteController().stopAllRoutes(); - } else { - camelContext.getRouteController().stopRoute(id); - } - } else if ("suspend".equals(command)) { - if ("*".equals(id)) { - camelContext.suspend(); - } else { - camelContext.getRouteController().suspendRoute(id); - } - } else if ("resume".equals(command)) { - if ("*".equals(id)) { - camelContext.resume(); - } else { - camelContext.getRouteController().resumeRoute(id); - } + executeRouteCommand(camelContext, command, id); + } + } + + private boolean matchesAnyPattern(Route route, String[] patterns) { + for (String p : patterns) { + if (routeMatchesPattern(route, p)) { + return true; + } + } + return false; + } + + private boolean routeMatchesPattern(Route route, String pattern) { + String source = route.getRouteId(); + String effectivePattern = pattern; + + if (pattern.startsWith("group:")) { + source = route.getGroup(); + effectivePattern = pattern.substring(6); + } + + return PatternHelper.matchPattern(source, effectivePattern); + } + + private void executeRouteCommand(CamelContext camelContext, String command, String id) { + try { + switch (command) { + case "start" -> executeStart(camelContext, id); + case "stop" -> executeStop(camelContext, id); + case "suspend" -> executeSuspend(camelContext, id); + case "resume" -> executeResume(camelContext, id); + default -> { } - } catch (Exception e) { - LOG.warn("Error {} route: {} due to: {}. This exception is ignored.", command, id, e.getMessage(), e); } + } catch (Exception e) { + LOG.warn("Error {} route: {} due to: {}. This exception is ignored.", command, id, e.getMessage(), e); + } + } + + private void executeStart(CamelContext camelContext, String id) throws Exception { + if ("*".equals(id)) { + camelContext.getRouteController().startAllRoutes(); + } else { + camelContext.getRouteController().startRoute(id); + } + } + + private void executeStop(CamelContext camelContext, String id) throws Exception { + if ("*".equals(id)) { + camelContext.getRouteController().stopAllRoutes(); + } else { + camelContext.getRouteController().stopRoute(id); + } + } + + private void executeSuspend(CamelContext camelContext, String id) throws Exception { + if ("*".equals(id)) { + camelContext.suspend(); + } else { + camelContext.getRouteController().suspendRoute(id); + } + } + + private void executeResume(CamelContext camelContext, String id) throws Exception { + if ("*".equals(id)) { + camelContext.resume(); + } else { + camelContext.getRouteController().resumeRoute(id); } } diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDumpDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDumpDevConsole.java index a69a503ddf57a..cdb5e05c4276d 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDumpDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDumpDevConsole.java @@ -72,81 +72,58 @@ public RouteDumpDevConsole() { @Override protected String doCallText(Map options) { - final String uriAsParameters = (String) options.getOrDefault(URI_AS_PARAMETERS, "false"); + final String format = (String) options.get(FORMAT); + final boolean useUriAsParameters = "true".equals(options.getOrDefault(URI_AS_PARAMETERS, "false")); final StringBuilder sb = new StringBuilder(); Function task = mrb -> { - String dump = null; - try { - String format = (String) options.get(FORMAT); - if (format == null || "xml".equals(format)) { - dump = mrb.dumpRouteAsXml(true); - } else if ("yaml".equals(format)) { - dump = mrb.dumpRouteAsYaml(true, "true".equals(uriAsParameters)); - } - } catch (Exception e) { - // ignore - } - sb.append(String.format(" Id: %s", mrb.getRouteId())); - if (mrb.getSourceLocation() != null) { - sb.append(String.format("%n Source: %s", mrb.getSourceLocation())); - } - if (dump != null && !dump.isEmpty()) { - sb.append("\n\n"); - for (String line : dump.split("\n")) { - sb.append(" ").append(line).append("\n"); - } - sb.append("\n"); - } - - sb.append("\n"); + appendRouteTextDump(sb, mrb, format, useUriAsParameters); return null; }; doCall(options, task); return sb.toString(); } + private void appendRouteTextDump(StringBuilder sb, ManagedRouteMBean mrb, String format, boolean useUriAsParameters) { + String dump = getRouteDumpText(mrb, format, useUriAsParameters); + + sb.append(String.format(" Id: %s", mrb.getRouteId())); + if (mrb.getSourceLocation() != null) { + sb.append(String.format("%n Source: %s", mrb.getSourceLocation())); + } + if (dump != null && !dump.isEmpty()) { + sb.append("\n\n"); + for (String line : dump.split("\n")) { + sb.append(" ").append(line).append("\n"); + } + sb.append("\n"); + } + sb.append("\n"); + } + + private String getRouteDumpText(ManagedRouteMBean mrb, String format, boolean useUriAsParameters) { + try { + if (format == null || "xml".equals(format)) { + return mrb.dumpRouteAsXml(true); + } else if ("yaml".equals(format)) { + return mrb.dumpRouteAsYaml(true, useUriAsParameters); + } + } catch (Exception e) { + // ignore + } + return null; + } + @Override protected JsonObject doCallJson(Map options) { - final String uriAsParameters = (String) options.getOrDefault(URI_AS_PARAMETERS, "false"); + final String format = (String) options.get(FORMAT); + final boolean useUriAsParameters = "true".equals(options.getOrDefault(URI_AS_PARAMETERS, "false")); final JsonObject root = new JsonObject(); final List list = new ArrayList<>(); Function task = mrb -> { - JsonObject jo = new JsonObject(); - list.add(jo); - - jo.put("routeId", mrb.getRouteId()); - jo.put("from", mrb.getEndpointUri()); - if (mrb.getSourceLocation() != null) { - jo.put("source", mrb.getSourceLocation()); - } - - try { - String dump = null; - String format = (String) options.get(FORMAT); - if (format == null || "xml".equals(format)) { - jo.put("format", "xml"); - dump = mrb.dumpRouteAsXml(true, false, true); - } else if ("yaml".equals(format)) { - jo.put("format", "yaml"); - dump = mrb.dumpRouteAsYaml(true, "true".equals(uriAsParameters), false, true); - } - if (dump != null) { - List code; - if (format == null || "xml".equals(format)) { - code = xmlLoadSourceAsJson(new StringReader(dump)); - } else { - code = yamlLoadSourceAsJson(new StringReader(dump)); - } - if (code != null) { - jo.put("code", code); - } - } - } catch (Exception e) { - // ignore - } + list.add(buildRouteJsonDump(mrb, format, useUriAsParameters)); return null; }; doCall(options, task); @@ -154,6 +131,54 @@ protected JsonObject doCallJson(Map options) { return root; } + private JsonObject buildRouteJsonDump(ManagedRouteMBean mrb, String format, boolean useUriAsParameters) { + JsonObject jo = new JsonObject(); + jo.put("routeId", mrb.getRouteId()); + jo.put("from", mrb.getEndpointUri()); + if (mrb.getSourceLocation() != null) { + jo.put("source", mrb.getSourceLocation()); + } + + addRouteDumpCode(jo, mrb, format, useUriAsParameters); + return jo; + } + + private void addRouteDumpCode(JsonObject jo, ManagedRouteMBean mrb, String format, boolean useUriAsParameters) { + try { + String effectiveFormat = format == null ? "xml" : format; + String dump = getRouteDumpJson(mrb, effectiveFormat, useUriAsParameters); + + jo.put("format", effectiveFormat); + if (dump == null) { + return; + } + + List code = parseRouteDumpToCode(dump, effectiveFormat); + if (code != null) { + jo.put("code", code); + } + } catch (Exception e) { + // ignore + } + } + + private String getRouteDumpJson(ManagedRouteMBean mrb, String format, boolean useUriAsParameters) throws Exception { + if ("xml".equals(format)) { + return mrb.dumpRouteAsXml(true, false, true); + } else if ("yaml".equals(format)) { + return mrb.dumpRouteAsYaml(true, useUriAsParameters, false, true); + } + return null; + } + + private List parseRouteDumpToCode(String dump, String format) { + if ("xml".equals(format)) { + return xmlLoadSourceAsJson(new StringReader(dump)); + } else { + return yamlLoadSourceAsJson(new StringReader(dump)); + } + } + protected void doCall(Map options, Function task) { String path = (String) options.get(Exchange.HTTP_PATH); String subPath = path != null ? StringHelper.after(path, "/") : null; diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteGroupDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteGroupDevConsole.java index 25446e421be1a..d1c6ba3319289 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteGroupDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteGroupDevConsole.java @@ -305,42 +305,56 @@ private String calculateRouteCoverage(ManagedRouteGroupMBean mrg, boolean percen } protected void doAction(CamelContext camelContext, String command, String filter) { - if (filter == null) { - filter = "*"; - } - String[] patterns = filter.split(","); - // find matching IDs + String effectiveFilter = filter != null ? filter : "*"; + String[] patterns = effectiveFilter.split(","); + List ids = camelContext.getRoutes() .stream() .map(Route::getGroup) - .filter(group -> { - for (String p : patterns) { - if (PatternHelper.matchPattern(group, p)) { - return true; - } - } - return false; - }) + .filter(group -> matchesAnyPattern(group, patterns)) .distinct() .toList(); + for (String id : ids) { - try { - if ("start".equals(command)) { - if ("*".equals(id)) { - camelContext.getRouteController().startAllRoutes(); - } else { - camelContext.getRouteController().startRouteGroup(id); - } - } else if ("stop".equals(command)) { - if ("*".equals(id)) { - camelContext.getRouteController().stopAllRoutes(); - } else { - camelContext.getRouteController().stopRouteGroup(id); - } + executeGroupCommand(camelContext, command, id); + } + } + + private boolean matchesAnyPattern(String group, String[] patterns) { + for (String p : patterns) { + if (PatternHelper.matchPattern(group, p)) { + return true; + } + } + return false; + } + + private void executeGroupCommand(CamelContext camelContext, String command, String id) { + try { + switch (command) { + case "start" -> executeStartGroup(camelContext, id); + case "stop" -> executeStopGroup(camelContext, id); + default -> { } - } catch (Exception e) { - LOG.warn("Error {} route: {} due to: {}. This exception is ignored.", command, id, e.getMessage(), e); } + } catch (Exception e) { + LOG.warn("Error {} route: {} due to: {}. This exception is ignored.", command, id, e.getMessage(), e); + } + } + + private void executeStartGroup(CamelContext camelContext, String id) throws Exception { + if ("*".equals(id)) { + camelContext.getRouteController().startAllRoutes(); + } else { + camelContext.getRouteController().startRouteGroup(id); + } + } + + private void executeStopGroup(CamelContext camelContext, String id) throws Exception { + if ("*".equals(id)) { + camelContext.getRouteController().stopAllRoutes(); + } else { + camelContext.getRouteController().stopRouteGroup(id); } } diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/SendDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/SendDevConsole.java index a6789ab1d7b70..29ab142e1d71c 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/SendDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/SendDevConsole.java @@ -271,44 +271,57 @@ private Exchange findToTarget( } private Endpoint findTarget(String endpoint) { - Endpoint target = null; if (endpoint == null) { - List routes = getCamelContext().getRoutes(); - if (!routes.isEmpty()) { - // grab endpoint from 1st route - target = routes.get(0).getEndpoint(); + return getFirstRouteEndpoint(); + } + + boolean hasScheme = endpoint.contains(":"); + boolean isPattern = endpoint.endsWith("*"); + + if (hasScheme && !isPattern) { + return getCamelContext().getEndpoint(endpoint); + } + + return findEndpointByPattern(endpoint, hasScheme); + } + + private Endpoint getFirstRouteEndpoint() { + List routes = getCamelContext().getRoutes(); + if (routes.isEmpty()) { + return null; + } + return routes.get(0).getEndpoint(); + } + + private Endpoint findEndpointByPattern(String endpoint, boolean hasScheme) { + String searchPattern = hasScheme ? endpoint : endpoint + "*"; + + Endpoint target = findEndpointByUri(searchPattern); + if (target != null) { + return target; + } + + return findEndpointByRouteId(searchPattern); + } + + private Endpoint findEndpointByUri(String pattern) { + for (Route route : getCamelContext().getRoutes()) { + Endpoint e = route.getEndpoint(); + if (EndpointHelper.matchEndpoint(getCamelContext(), e.getEndpointUri(), pattern)) { + return e; } - } else { - // is the endpoint a pattern or route id - boolean scheme = endpoint.contains(":"); - boolean pattern = endpoint.endsWith("*"); - if (!scheme || pattern) { - if (!scheme) { - endpoint = endpoint + "*"; - } - for (Route route : getCamelContext().getRoutes()) { - Endpoint e = route.getEndpoint(); - if (EndpointHelper.matchEndpoint(getCamelContext(), e.getEndpointUri(), endpoint)) { - target = e; - break; - } - } - if (target == null) { - // okay it may refer to a route id - for (Route route : getCamelContext().getRoutes()) { - String id = route.getRouteId(); - Endpoint e = route.getEndpoint(); - if (EndpointHelper.matchEndpoint(getCamelContext(), id, endpoint)) { - target = e; - break; - } - } - } - } else { - target = getCamelContext().getEndpoint(endpoint); + } + return null; + } + + private Endpoint findEndpointByRouteId(String pattern) { + for (Route route : getCamelContext().getRoutes()) { + String id = route.getRouteId(); + if (EndpointHelper.matchEndpoint(getCamelContext(), id, pattern)) { + return route.getEndpoint(); } } - return target; + return null; } private Object prepareBody(String body) throws Exception { diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/TraceDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/TraceDevConsole.java index dea7aa4b72d7c..e432c973bd7c2 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/TraceDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/TraceDevConsole.java @@ -75,47 +75,63 @@ protected String doCallText(Map options) { String dump = (String) options.get(DUMP); BacklogTracer tracer = getCamelContext().getCamelContextExtension().getContextPlugin(BacklogTracer.class); - if (tracer != null) { - if (dump != null) { - for (BacklogTracerEventMessage t : tracer.dumpAllTracedMessages()) { - addMessage(t); - } - for (BacklogTracerEventMessage t : queue) { - String json = t.toJSon(0); - sb.append(json).append("\n"); - } - } else { - if ("true".equals(enabled)) { - tracer.setEnabled(true); - } else if ("false".equals(enabled)) { - tracer.setEnabled(false); - } - sb.append("Enabled: ").append(tracer.isEnabled()).append("\n"); - sb.append("Standby: ").append(tracer.isStandby()).append("\n"); - sb.append("Trace Counter: ").append(tracer.getTraceCounter()).append("\n"); - sb.append("Backlog Size: ").append(tracer.getBacklogSize()).append("\n"); - sb.append("Queue Size: ").append(tracer.getQueueSize()).append("\n"); - sb.append("Remove On Dump: ").append(tracer.isRemoveOnDump()).append("\n"); - if (tracer.getTraceFilter() != null) { - sb.append("Trace Filter: ").append(tracer.getTraceFilter()).append("\n"); - } - if (tracer.getTracePattern() != null) { - sb.append("Trace Pattern: ").append(tracer.getTracePattern()).append("\n"); - } - sb.append("Trace Rests: ").append(tracer.isTraceRests()).append("\n"); - sb.append("Trace Templates: ").append(tracer.isTraceTemplates()).append("\n"); - sb.append("Body Max Chars: ").append(tracer.getBodyMaxChars()).append("\n"); - sb.append("Body Include Files: ").append(tracer.isBodyIncludeFiles()).append("\n"); - sb.append("Body Include Streams: ").append(tracer.isBodyIncludeStreams()).append("\n"); - sb.append("Include Exchange Properties: ").append(tracer.isIncludeExchangeProperties()).append("\n"); - sb.append("Include Exchange Variables: ").append(tracer.isIncludeExchangeVariables()).append("\n"); - sb.append("Include Exception: ").append(tracer.isIncludeException()).append("\n"); - } + if (tracer == null) { + return sb.toString(); + } + + if (dump != null) { + appendDumpText(sb, tracer); + } else { + applyEnabledSetting(tracer, enabled); + appendTracerStatusText(sb, tracer); } return sb.toString(); } + private void appendDumpText(StringBuilder sb, BacklogTracer tracer) { + for (BacklogTracerEventMessage t : tracer.dumpAllTracedMessages()) { + addMessage(t); + } + for (BacklogTracerEventMessage t : queue) { + String json = t.toJSon(0); + sb.append(json).append("\n"); + } + } + + private void appendTracerStatusText(StringBuilder sb, BacklogTracer tracer) { + sb.append("Enabled: ").append(tracer.isEnabled()).append("\n"); + sb.append("Standby: ").append(tracer.isStandby()).append("\n"); + sb.append("Trace Counter: ").append(tracer.getTraceCounter()).append("\n"); + sb.append("Backlog Size: ").append(tracer.getBacklogSize()).append("\n"); + sb.append("Queue Size: ").append(tracer.getQueueSize()).append("\n"); + sb.append("Remove On Dump: ").append(tracer.isRemoveOnDump()).append("\n"); + appendOptionalLine(sb, "Trace Filter", tracer.getTraceFilter()); + appendOptionalLine(sb, "Trace Pattern", tracer.getTracePattern()); + sb.append("Trace Rests: ").append(tracer.isTraceRests()).append("\n"); + sb.append("Trace Templates: ").append(tracer.isTraceTemplates()).append("\n"); + sb.append("Body Max Chars: ").append(tracer.getBodyMaxChars()).append("\n"); + sb.append("Body Include Files: ").append(tracer.isBodyIncludeFiles()).append("\n"); + sb.append("Body Include Streams: ").append(tracer.isBodyIncludeStreams()).append("\n"); + sb.append("Include Exchange Properties: ").append(tracer.isIncludeExchangeProperties()).append("\n"); + sb.append("Include Exchange Variables: ").append(tracer.isIncludeExchangeVariables()).append("\n"); + sb.append("Include Exception: ").append(tracer.isIncludeException()).append("\n"); + } + + private void appendOptionalLine(StringBuilder sb, String label, String value) { + if (value != null) { + sb.append(label).append(": ").append(value).append("\n"); + } + } + + private void applyEnabledSetting(BacklogTracer tracer, String enabled) { + if ("true".equals(enabled)) { + tracer.setEnabled(true); + } else if ("false".equals(enabled)) { + tracer.setEnabled(false); + } + } + private void addMessage(BacklogTracerEventMessage message) { // ensure there is space on the queue by polling until at least single slot is free int drain = queue.size() - capacity + 1; @@ -133,48 +149,56 @@ protected JsonObject doCallJson(Map options) { String dump = (String) options.get(DUMP); BacklogTracer tracer = getCamelContext().getCamelContextExtension().getContextPlugin(BacklogTracer.class); - if (tracer != null) { - if (dump != null) { - for (BacklogTracerEventMessage t : tracer.dumpAllTracedMessages()) { - addMessage(t); - } - JsonArray arr = new JsonArray(); - root.put("enabled", tracer.isEnabled()); - root.put("traces", arr); - for (BacklogTracerEventMessage t : queue) { - JsonObject jo = (JsonObject) t.asJSon(); - arr.add(jo); - } - } else { - if ("true".equals(enabled)) { - tracer.setEnabled(true); - } else if ("false".equals(enabled)) { - tracer.setEnabled(false); - } - root.put("enabled", tracer.isEnabled()); - root.put("standby", tracer.isStandby()); - root.put("counter", tracer.getTraceCounter()); - root.put("backlogSize", tracer.getBacklogSize()); - root.put("queueSize", tracer.getQueueSize()); - root.put("removeOnDump", tracer.isRemoveOnDump()); - if (tracer.getTraceFilter() != null) { - root.put("traceFilter", tracer.getTraceFilter()); - } - if (tracer.getTracePattern() != null) { - root.put("tracePattern", tracer.getTracePattern()); - } - root.put("traceRests", tracer.isTraceRests()); - root.put("traceTemplates", tracer.isTraceTemplates()); - root.put("bodyMaxChars", tracer.getBodyMaxChars()); - root.put("bodyIncludeFiles", tracer.isBodyIncludeFiles()); - root.put("bodyIncludeStreams", tracer.isBodyIncludeStreams()); - root.put("includeExchangeProperties", tracer.isIncludeExchangeProperties()); - root.put("includeExchangeVariables", tracer.isIncludeExchangeVariables()); - root.put("includeException", tracer.isIncludeException()); - } + if (tracer == null) { + return root; + } + + if (dump != null) { + addDumpJson(root, tracer); + } else { + applyEnabledSetting(tracer, enabled); + addTracerStatusJson(root, tracer); } return root; } + private void addDumpJson(JsonObject root, BacklogTracer tracer) { + for (BacklogTracerEventMessage t : tracer.dumpAllTracedMessages()) { + addMessage(t); + } + JsonArray arr = new JsonArray(); + root.put("enabled", tracer.isEnabled()); + root.put("traces", arr); + for (BacklogTracerEventMessage t : queue) { + JsonObject jo = (JsonObject) t.asJSon(); + arr.add(jo); + } + } + + private void addTracerStatusJson(JsonObject root, BacklogTracer tracer) { + root.put("enabled", tracer.isEnabled()); + root.put("standby", tracer.isStandby()); + root.put("counter", tracer.getTraceCounter()); + root.put("backlogSize", tracer.getBacklogSize()); + root.put("queueSize", tracer.getQueueSize()); + root.put("removeOnDump", tracer.isRemoveOnDump()); + putIfNotNull(root, "traceFilter", tracer.getTraceFilter()); + putIfNotNull(root, "tracePattern", tracer.getTracePattern()); + root.put("traceRests", tracer.isTraceRests()); + root.put("traceTemplates", tracer.isTraceTemplates()); + root.put("bodyMaxChars", tracer.getBodyMaxChars()); + root.put("bodyIncludeFiles", tracer.isBodyIncludeFiles()); + root.put("bodyIncludeStreams", tracer.isBodyIncludeStreams()); + root.put("includeExchangeProperties", tracer.isIncludeExchangeProperties()); + root.put("includeExchangeVariables", tracer.isIncludeExchangeVariables()); + root.put("includeException", tracer.isIncludeException()); + } + + private void putIfNotNull(JsonObject jo, String key, String value) { + if (value != null) { + jo.put(key, value); + } + } + }