This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch ra in repository https://gitbox.apache.org/repos/asf/camel.git
commit 360b8de82743e2c5243fad98d4e0c9fc30b964be Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Mon May 27 14:59:29 2024 +0200 CAMEL-20798: Add RemoteAddress to endpoints so they can tell the url/hostname etc for the system it connects. This is needed for better monitoring, tracing and management. Add this information into camel-tracer as tags. --- .../camel/impl/console/ServiceDevConsole.java | 8 + .../dsl/jbang/core/commands/CamelJBangMain.java | 1 - .../jbang/core/commands/process/ListAddress.java | 246 --------------------- .../jbang/core/commands/process/ListService.java | 114 +++++----- 4 files changed, 67 insertions(+), 302 deletions(-) diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/ServiceDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/ServiceDevConsole.java index fa990f17114..0ea70a63362 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/ServiceDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/ServiceDevConsole.java @@ -157,6 +157,10 @@ public class ServiceDevConsole extends AbstractDevConsole { jo.put("address", adr); jo.put("endpointUri", uri); stat.ifPresent(s -> jo.put("totalMessages", s.getHits())); + var map = raa.getServiceMetadata(); + if (map != null) { + jo.put("metadata", map); + } list.add(jo); } } @@ -185,6 +189,10 @@ public class ServiceDevConsole extends AbstractDevConsole { jo.put("address", adr); jo.put("endpointUri", uri); stat.ifPresent(s -> jo.put("totalMessages", s.getHits())); + var map = raa.getServiceMetadata(); + if (map != null) { + jo.put("metadata", map); + } list.add(jo); } } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java index 8dd7c5eaf98..60844e1e3af 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java @@ -90,7 +90,6 @@ public class CamelJBangMain implements Callable<Integer> { .addSubcommand("variable", new CommandLine(new ListVariable(main))) .addSubcommand("consumer", new CommandLine(new ListConsumer(main))) .addSubcommand("endpoint", new CommandLine(new ListEndpoint(main))) - .addSubcommand("address", new CommandLine(new ListAddress(main))) .addSubcommand("event", new CommandLine(new ListEvent(main))) .addSubcommand("inflight", new CommandLine(new ListInflight(main))) .addSubcommand("blocked", new CommandLine(new ListBlocked(main))) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListAddress.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListAddress.java deleted file mode 100644 index d0680e9760e..00000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListAddress.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * 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.dsl.jbang.core.commands.process; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.StringJoiner; - -import com.github.freva.asciitable.AsciiTable; -import com.github.freva.asciitable.Column; -import com.github.freva.asciitable.HorizontalAlign; -import com.github.freva.asciitable.OverflowBehaviour; -import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; -import org.apache.camel.dsl.jbang.core.common.PidNameAgeCompletionCandidates; -import org.apache.camel.dsl.jbang.core.common.ProcessHelper; -import org.apache.camel.support.PatternHelper; -import org.apache.camel.util.TimeUtils; -import org.apache.camel.util.json.JsonArray; -import org.apache.camel.util.json.JsonObject; -import picocli.CommandLine; -import picocli.CommandLine.Command; - -@Command(name = "address", description = "Get usage of Camel service addresses (hosted and external)", sortOptions = false) -@Deprecated // TODO: protocol -public class ListAddress extends ProcessWatchCommand { - - @CommandLine.Parameters(description = "Name or pid of running Camel integration", arity = "0..1") - String name = "*"; - - @CommandLine.Option(names = { "--sort" }, completionCandidates = PidNameAgeCompletionCandidates.class, - description = "Sort by pid, name or total", defaultValue = "pid") - String sort; - - @CommandLine.Option(names = { "--limit" }, - description = "Filter addresses by limiting to the given number of rows") - int limit; - - @CommandLine.Option(names = { "--filter" }, - description = "Filter addresses") - String filter; - - @CommandLine.Option(names = { "--filter-direction" }, - description = "Filter by direction (in or out)") - String filterDirection; - - @CommandLine.Option(names = { "--wide-uri" }, - description = "List endpoint URI in full details") - boolean wideUri; - - // TODO: Hosted is on consumer - - public ListAddress(CamelJBangMain main) { - super(main); - } - - @Override - public Integer doProcessWatchCall() throws Exception { - List<Row> rows = new ArrayList<>(); - - // make it easier to filter - if (filter != null && !filter.endsWith("*")) { - filter += "*"; - } - - List<Long> pids = findPids(name); - ProcessHandle.allProcesses() - .filter(ph -> pids.contains(ph.pid())) - .forEach(ph -> { - JsonObject root = loadStatus(ph.pid()); - if (root != null) { - JsonObject context = (JsonObject) root.get("context"); - JsonObject jo = (JsonObject) root.get("endpoints"); - if (context != null && jo != null) { - JsonArray array = (JsonArray) jo.get("endpoints"); - for (int i = 0; i < array.size(); i++) { - JsonObject o = (JsonObject) array.get(i); - Row row = new Row(); - row.name = context.getString("name"); - if ("CamelJBang".equals(row.name)) { - row.name = ProcessHelper.extractName(root, ph); - } - row.pid = Long.toString(ph.pid()); - row.endpoint = o.getString("uri"); - JsonObject ro = (JsonObject) o.get("location"); - if (ro != null) { - row.address = ro; - } - row.direction = o.getString("direction"); - row.total = o.getString("hits"); - row.uptime = extractSince(ph); - row.age = TimeUtils.printSince(row.uptime); - boolean add = true; - if (filterDirection != null && !filterDirection.equals(row.direction)) { - add = false; - } - if (row.address == null) { - add = false; - } - if (filter != null) { - String f = filter; - boolean negate = filter.startsWith("-"); - if (negate) { - f = f.substring(1); - } - boolean match = PatternHelper.matchPattern(row.endpoint, f); - if (negate) { - match = !match; - } - if (!match) { - add = false; - } - } - if (limit > 0 && rows.size() >= limit) { - add = false; - } - if (add) { - rows.add(row); - } - } - } - } - }); - - // sort rows - rows.sort(this::sortRow); - - if (!rows.isEmpty()) { - printTable(rows); - } - - return 0; - } - - protected void printTable(List<Row> rows) { - printer().println(AsciiTable.getTable(AsciiTable.NO_BORDERS, rows, Arrays.asList( - new Column().header("PID").headerAlign(HorizontalAlign.CENTER).with(r -> r.pid), - new Column().header("NAME").dataAlign(HorizontalAlign.LEFT).maxWidth(30, OverflowBehaviour.ELLIPSIS_RIGHT) - .with(r -> r.name), - new Column().header("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.age), - new Column().header("DIR").with(this::getDirection), - new Column().header("TOTAL").with(r -> r.total), - // new Column().header("HOSTED").dataAlign(HorizontalAlign.CENTER).with(this::getHosted), - new Column().header("URI").visible(!wideUri).dataAlign(HorizontalAlign.LEFT) - .maxWidth(90, OverflowBehaviour.ELLIPSIS_RIGHT) - .with(this::getUri), - new Column().header("URI").visible(wideUri).dataAlign(HorizontalAlign.LEFT) - .maxWidth(140, OverflowBehaviour.NEWLINE) - .with(this::getUri), - new Column().header("ADDRESS").dataAlign(HorizontalAlign.LEFT) - .maxWidth(90, OverflowBehaviour.ELLIPSIS_RIGHT) - .with(this::getAddress)))); - } - - private String getUri(Row r) { - String u = r.endpoint; - if (!wideUri) { - int pos = u.indexOf('?'); - if (pos > 0) { - u = u.substring(0, pos); - } - } - return u; - } - - private String getDirection(Row r) { - String dir = r.direction; - if (dir == null || dir.isEmpty()) { - // hosted is always in - dir = "x".equals(getHosted(r)) ? "in" : "out"; - } - return dir; - } - - private String getAddress(Row r) { - String a = ""; - if (r.address != null) { - a = r.address.getString("address"); - if (r.address.size() > 1) { - StringJoiner sj = new StringJoiner(" "); - r.address.forEach((k, v) -> { - if (!"address".equals(k) && !"hosted".equals(k) && !"remote".equals(k)) { - sj.add(k + "=" + v); - } - }); - if (sj.length() > 0) { - a = a + " (" + sj + ")"; - } - } - } - return a; - } - - private String getHosted(Row r) { - boolean hosted = false; - if (r.address != null) { - hosted = r.address.getBooleanOrDefault("hosted", false); - } - return hosted ? "x" : ""; - } - - protected int sortRow(Row o1, Row o2) { - String s = sort; - int negate = 1; - if (s.startsWith("-")) { - s = s.substring(1); - negate = -1; - } - switch (s) { - case "pid": - return Long.compare(Long.parseLong(o1.pid), Long.parseLong(o2.pid)) * negate; - case "name": - return o1.name.compareToIgnoreCase(o2.name) * negate; - case "age": - return Long.compare(o1.uptime, o2.uptime) * negate; - default: - return 0; - } - } - - static class Row { - String pid; - String name; - long uptime; - String age; - String endpoint; - String direction; - String total; - JsonObject address; - } - -} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListService.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListService.java index d5696444ca5..b49f224cf98 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListService.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListService.java @@ -19,6 +19,7 @@ package org.apache.camel.dsl.jbang.core.commands.process; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.StringJoiner; import com.github.freva.asciitable.AsciiTable; import com.github.freva.asciitable.Column; @@ -33,8 +34,6 @@ import org.apache.camel.util.json.JsonObject; import picocli.CommandLine; import picocli.CommandLine.Command; - -// TODO: protocol @Command(name = "service", description = "Get services of Camel integrations", sortOptions = false) public class ListService extends ProcessWatchCommand { @@ -46,6 +45,18 @@ public class ListService extends ProcessWatchCommand { description = "Sort by pid, name or age", defaultValue = "pid") String sort; + @CommandLine.Option(names = { "--metadata" }, + description = "Show service metadata (only available for some services)") + boolean metadata; + + @CommandLine.Option(names = { "--short-uri" }, + description = "List endpoint URI without query parameters (short)") + boolean shortUri; + + @CommandLine.Option(names = { "--wide-uri" }, + description = "List endpoint URI in full details") + boolean wideUri; + public ListService(CamelJBangMain main) { super(main); } @@ -77,26 +88,23 @@ public class ListService extends ProcessWatchCommand { // platform-http is special JsonObject jo = (JsonObject) root.get("services"); if (jo != null) { - jo = (JsonObject) jo.get("platform-http"); - } - if (jo != null) { - JsonArray arr = (JsonArray) jo.get("endpoints"); + JsonArray arr = (JsonArray) jo.get("services"); if (arr != null) { for (int i = 0; i < arr.size(); i++) { row = row.copy(); jo = (JsonObject) arr.get(i); - row.component = "platform-http"; - row.protocol = "http"; - row.service = jo.getString("url"); - row.verbs = jo.getString("verbs"); + row.component = jo.getString("component"); + row.direction = jo.getString("direction"); + row.hosted = jo.getBooleanOrDefault("hosted", false); + row.protocol = jo.getString("protocol"); + row.address = jo.getString("address"); + row.endpoint = jo.getString("endpointUri"); + row.hits = jo.getLongOrDefault("totalMessages", 0); + row.metadata = jo.getMap("metadata"); rows.add(row); } } } - fetchServices(root, row, "netty", rows); - fetchServices(root, row, "mina", rows); - fetchServices(root, row, "mllp", rows); - fetchServices(root, row, "knative", rows); } }); @@ -109,42 +117,22 @@ public class ListService extends ProcessWatchCommand { new Column().header("NAME").dataAlign(HorizontalAlign.LEFT).maxWidth(30, OverflowBehaviour.ELLIPSIS_RIGHT) .with(r -> r.name), new Column().header("COMPONENT").dataAlign(HorizontalAlign.LEFT).with(r -> r.component), + new Column().header("DIR").dataAlign(HorizontalAlign.LEFT).with(r -> r.direction), new Column().header("PROTOCOL").dataAlign(HorizontalAlign.LEFT).with(this::getProtocol), - new Column().header("SERVICE").dataAlign(HorizontalAlign.LEFT).with(this::getService)))); + new Column().header("SERVICE").dataAlign(HorizontalAlign.LEFT).with(this::getService), + new Column().header("METADATA").visible(metadata).dataAlign(HorizontalAlign.LEFT).with(this::getMetadata), + new Column().header("TOTAL").dataAlign(HorizontalAlign.RIGHT).with(r -> "" + r.hits), + new Column().header("ENDPOINT").visible(!wideUri).dataAlign(HorizontalAlign.LEFT) + .maxWidth(90, OverflowBehaviour.ELLIPSIS_RIGHT) + .with(this::getUri), + new Column().header("ENDPOINT").visible(wideUri).dataAlign(HorizontalAlign.LEFT) + .maxWidth(140, OverflowBehaviour.NEWLINE) + .with(this::getUri)))); } return 0; } - private static void fetchServices(JsonObject root, Row row, String component, List<Row> rows) { - JsonObject jo = (JsonObject) root.get("services"); - if (jo != null) { - jo = (JsonObject) jo.get(component); - } - if (jo != null) { - JsonArray arr = (JsonArray) jo.get("consumers"); - if (arr != null) { - for (Object o : arr) { - row = row.copy(); - jo = (JsonObject) o; - row.component = component; - row.protocol = jo.getString("protocol"); - String p = row.protocol + ":"; - if (p.startsWith("http")) { - // we want double slashes for http protocols - p = p + "//"; - } - row.service = p + jo.getString("host") + ":" + jo.getInteger("port"); - String path = jo.getString("path"); - if (path != null) { - row.service += "/" + path; - } - rows.add(row); - } - } - } - } - protected int sortRow(Row o1, Row o2) { String s = sort; int negate = 1; @@ -164,20 +152,32 @@ public class ListService extends ProcessWatchCommand { } } - private String getProtocol(Row r) { - String s = r.protocol; - if (r.verbs != null) { - s = "rest"; + private String getUri(Row r) { + String u = r.endpoint; + if (shortUri) { + int pos = u.indexOf('?'); + if (pos > 0) { + u = u.substring(0, pos); + } } - return s; + return u; + } + + private String getProtocol(Row r) { + return r.protocol; } private String getService(Row r) { - String s = r.service; - if (r.verbs != null) { - s += " (" + r.verbs + ")"; + return r.address; + } + + private String getMetadata(Row r) { + if (r.metadata != null) { + StringJoiner sj = new StringJoiner(" "); + r.metadata.forEach((k, v) -> sj.add(k + "=" + v)); + return sj.toString(); } - return s; + return ""; } private static class Row implements Cloneable { @@ -186,9 +186,13 @@ public class ListService extends ProcessWatchCommand { String age; long uptime; String component; + String direction; + boolean hosted; String protocol; - String service; - String verbs; + String address; + String endpoint; + long hits; + JsonObject metadata; Row copy() { try {