You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/10/15 09:09:37 UTC
[camel] branch main updated: camel-core: Route controller dev console
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 45f885347f0 camel-core: Route controller dev console
45f885347f0 is described below
commit 45f885347f02a80fb30c3423758b53d768df0da1
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sat Oct 15 11:09:20 2022 +0200
camel-core: Route controller dev console
---
.../org/apache/camel/dev-console/route-controller | 2 +
.../camel/impl/console/RouteControllerConsole.java | 259 +++++++++++++++++++++
2 files changed, 261 insertions(+)
diff --git a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/route-controller b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/route-controller
new file mode 100644
index 00000000000..d1b1980d681
--- /dev/null
+++ b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/route-controller
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.impl.console.RouteControllerConsole
diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteControllerConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteControllerConsole.java
new file mode 100644
index 00000000000..ce35bb6a5cf
--- /dev/null
+++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteControllerConsole.java
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.camel.Route;
+import org.apache.camel.spi.RouteController;
+import org.apache.camel.spi.SupervisingRouteController;
+import org.apache.camel.spi.annotations.DevConsole;
+import org.apache.camel.util.TimeUtils;
+import org.apache.camel.util.URISupport;
+import org.apache.camel.util.backoff.BackOffTimer;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import org.apache.camel.util.json.Jsoner;
+
+@DevConsole("route-controller")
+public class RouteControllerConsole extends AbstractDevConsole {
+
+ public static final String STACKTRACE = "stacktrace";
+ public static final String ERROR = "error";
+
+ public RouteControllerConsole() {
+ super("camel", "route-controller", "Route Controller", "Route startup information");
+ }
+
+ @Override
+ protected String doCallText(Map<String, Object> options) {
+ boolean includeError = "true".equals(options.getOrDefault(ERROR, "true"));
+ boolean includeStacktrace = "true".equals(options.getOrDefault(STACKTRACE, "true"));
+
+ StringBuilder sb = new StringBuilder();
+
+ RouteController rc = getCamelContext().getRouteController();
+ if (rc instanceof SupervisingRouteController) {
+ SupervisingRouteController src = (SupervisingRouteController) rc;
+
+ Set<Route> routes = new TreeSet<>(Comparator.comparing(Route::getId));
+ routes.addAll(rc.getControlledRoutes());
+ routes.addAll(src.getExhaustedRoutes());
+ routes.addAll(src.getRestartingRoutes());
+ long started = routes.stream().filter(r -> src.getRouteStatus(r.getRouteId()).isStarted())
+ .count();
+
+ sb.append(String.format("Total Routes: %d", routes.size()));
+ sb.append(String.format("\nStarted Routes: %d", started));
+ sb.append(String.format("\nRestarting Routes: %d", src.getRestartingRoutes().size()));
+ sb.append(String.format("\nExhausted Routes: %d", src.getExhaustedRoutes().size()));
+ sb.append(String.format("\nInitial Delay: %d", src.getInitialDelay()));
+ sb.append(String.format("\nBackoff Delay: %d", src.getBackOffDelay()));
+ sb.append(String.format("\nBackoff Max Delay: %d", src.getBackOffMaxDelay()));
+ sb.append(String.format("\nBackoff Max Elapsed Time: %d", src.getBackOffMaxElapsedTime()));
+ sb.append(String.format("\nBackoff Max Attempts: %d", src.getBackOffMaxAttempts()));
+ sb.append(String.format("\nThread Pool Size: %d", src.getThreadPoolSize()));
+ sb.append(String.format("\nUnhealthy On Exhaust: %b", src.isUnhealthyOnExhausted()));
+ sb.append("\n\nRoutes:\n");
+
+ for (Route route : routes) {
+ String routeId = route.getRouteId();
+ String status = src.getRouteStatus(routeId).name();
+ String uri = route.getEndpoint().getEndpointBaseUri();
+ uri = URISupport.sanitizeUri(uri);
+
+ BackOffTimer.Task state = src.getRestartingRouteState(routeId);
+ String supervising = state != null ? state.getStatus().name() : null;
+ long attempts = state != null ? state.getCurrentAttempts() : 0;
+ String elapsed = "";
+ String last = "";
+ String next = "";
+ // we can only track elapsed/time for active supervised routes
+ long time = state != null && BackOffTimer.Task.Status.Active == state.getStatus()
+ ? state.getFirstAttemptTime() : 0;
+ if (time > 0) {
+ elapsed = TimeUtils.printSince(time);
+ }
+ time = state != null && BackOffTimer.Task.Status.Active == state.getStatus() ? state.getLastAttemptTime() : 0;
+ if (time > 0) {
+ last = TimeUtils.printSince(time);
+ }
+ time = state != null && BackOffTimer.Task.Status.Active == state.getStatus() ? state.getNextAttemptTime() : 0;
+ if (time > 0) {
+ next = TimeUtils.printSince(time);
+ }
+ String error = null;
+ String stacktrace = null;
+ Throwable cause = src.getRestartException(routeId);
+ if (includeError && cause != null) {
+ error = cause.getMessage();
+ if (includeStacktrace) {
+ StringWriter writer = new StringWriter();
+ cause.printStackTrace(new PrintWriter(writer));
+ writer.flush();
+ stacktrace = writer.toString();
+ }
+ }
+
+ if (supervising != null) {
+ sb.append(String.format("\n %s %s (%s) ", status, routeId, uri));
+ sb.append(String.format("\n Supervising: %s", supervising));
+ sb.append(String.format("\n Attempts: %s", attempts));
+ sb.append(String.format("\n Last Ago: %s", last));
+ sb.append(String.format("\n Next Attempt: %s", next));
+ sb.append(String.format("\n Elapsed: %s", elapsed));
+ if (error != null) {
+ sb.append(String.format("\n Error: %s", error));
+ if (stacktrace != null) {
+ sb.append(String.format("\n Stacktrace:\n%s", stacktrace));
+ }
+ }
+ } else {
+ sb.append(String.format("\n %s %s (%s) ", status, routeId, uri));
+ }
+ }
+ } else {
+ Set<Route> routes = new TreeSet<>(Comparator.comparing(Route::getId));
+ routes.addAll(rc.getControlledRoutes());
+ sb.append(String.format("Total Routes: %d", routes.size()));
+ sb.append("\nRoutes:\n");
+ for (Route route : routes) {
+ String routeId = route.getRouteId();
+ String status = rc.getRouteStatus(routeId).name();
+ String uri = route.getEndpoint().getEndpointBaseUri();
+ uri = URISupport.sanitizeUri(uri);
+ sb.append(String.format("\n %s %s (%s)", status, routeId, uri));
+ }
+ }
+
+ return sb.toString();
+ }
+
+ @Override
+ protected JsonObject doCallJson(Map<String, Object> options) {
+ boolean includeError = "true".equals(options.getOrDefault(ERROR, "true"));
+ boolean includeStacktrace = "true".equals(options.getOrDefault(STACKTRACE, "true"));
+
+ JsonObject root = new JsonObject();
+ final List<JsonObject> list = new ArrayList<>();
+
+ RouteController rc = getCamelContext().getRouteController();
+ if (rc instanceof SupervisingRouteController) {
+ SupervisingRouteController src = (SupervisingRouteController) rc;
+
+ Set<Route> routes = new TreeSet<>(Comparator.comparing(Route::getId));
+ routes.addAll(rc.getControlledRoutes());
+ routes.addAll(src.getExhaustedRoutes());
+ routes.addAll(src.getRestartingRoutes());
+ long started = routes.stream().filter(r -> src.getRouteStatus(r.getRouteId()).isStarted())
+ .count();
+
+ root.put("totalRoutes", routes.size());
+ root.put("startedRoutes", started);
+ root.put("restartingRoutes", src.getRestartingRoutes().size());
+ root.put("exhaustedRoutes", src.getExhaustedRoutes().size());
+ root.put("initialDelay", src.getInitialDelay());
+ root.put("backoffDelay", src.getBackOffDelay());
+ root.put("backoffMaxDelay", src.getBackOffMaxDelay());
+ root.put("backoffMaxElapsedTime", src.getBackOffMaxElapsedTime());
+ root.put("backoffMaxAttempts", src.getBackOffMaxAttempts());
+ root.put("threadPoolSize", src.getThreadPoolSize());
+ root.put("unhealthyOnExhausted", src.isUnhealthyOnExhausted());
+ root.put("routes", list);
+
+ for (Route route : routes) {
+ String routeId = route.getRouteId();
+ String status = rc.getRouteStatus(routeId).name();
+ String uri = route.getEndpoint().getEndpointBaseUri();
+ uri = URISupport.sanitizeUri(uri);
+
+ BackOffTimer.Task state = src.getRestartingRouteState(routeId);
+ String supervising = state != null ? state.getStatus().name() : null;
+ long attempts = state != null ? state.getCurrentAttempts() : 0;
+ String elapsed = "";
+ String last = "";
+ String next = "";
+ // we can only track elapsed/time for active supervised routes
+ long time = state != null && BackOffTimer.Task.Status.Active == state.getStatus()
+ ? state.getCurrentElapsedTime() : 0;
+ if (time > 0) {
+ elapsed = TimeUtils.printSince(time);
+ }
+ time = state != null && BackOffTimer.Task.Status.Active == state.getStatus() ? state.getLastAttemptTime() : 0;
+ if (time > 0) {
+ last = TimeUtils.printSince(time);
+ }
+ time = state != null && BackOffTimer.Task.Status.Active == state.getStatus() ? state.getNextAttemptTime() : 0;
+ if (time > 0) {
+ next = TimeUtils.printSince(time);
+ }
+ JsonObject jo = new JsonObject();
+ list.add(jo);
+ jo.put("routeId", routeId);
+ jo.put("status", status);
+ jo.put("uri", uri);
+ jo.put("attempts", attempts);
+ jo.put("lastAttemptAgo", last);
+ jo.put("nextAttempt", next);
+ jo.put("elapsed", elapsed);
+ if (supervising != null) {
+ jo.put("supervising", supervising);
+ Throwable cause = src.getRestartException(routeId);
+ if (includeError && cause != null) {
+ String error = cause.getMessage();
+ jo.put("error", Jsoner.escape(error));
+ if (includeStacktrace) {
+ JsonArray arr2 = new JsonArray();
+ jo.put("stackTrace", arr2);
+ for (StackTraceElement e : cause.getStackTrace()) {
+ arr2.add(e.toString());
+ }
+ }
+ }
+ }
+ }
+ } else {
+ Set<Route> routes = new TreeSet<>(Comparator.comparing(Route::getId));
+ routes.addAll(rc.getControlledRoutes());
+
+ root.put("totalRoutes", routes.size());
+ root.put("routes", list);
+ for (Route route : routes) {
+ String routeId = route.getRouteId();
+ String status = rc.getRouteStatus(routeId).name();
+ String uri = route.getEndpoint().getEndpointBaseUri();
+ uri = URISupport.sanitizeUri(uri);
+
+ JsonObject jo = new JsonObject();
+ list.add(jo);
+ jo.put("routeId", routeId);
+ jo.put("status", status);
+ jo.put("uri", uri);
+ }
+ }
+
+ return root;
+ }
+
+}