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;
+    }
+
+}