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
commit 903c066453a6dc1bbb11c2c1c5b6518c7649354f Author: Claus Ibsen <[email protected]> AuthorDate: Wed Jan 4 18:03:54 2023 +0100 CAMEL-18538: camel-jbang - Log command --- .../modules/ROOT/pages/camel-jbang.adoc | 16 +++ .../dsl/jbang/core/commands/CamelJBangMain.java | 2 + .../jbang/core/commands/action/CamelLogAction.java | 138 +++++++++++++++++++++ .../src/main/resources/log4j2.properties | 3 +- 4 files changed, 158 insertions(+), 1 deletion(-) diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc index c84bad7e13c..9f1d67efa00 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc @@ -779,6 +779,22 @@ camel top route TIP: Use `camel top --help` to display all the available commands as additional will be added in upcoming releases. +==== Tailing logs + +When you run Camel integrations then they will by default run in the foreground and output logs. + +You can from another terminal access the logs from any Camel integration with the `log` command, as follows: + +[source,bash] +---- +camel log chuck +2023-01-04 17:59:19.288 INFO 44619 --- [ main] org.apache.camel.main.MainSupport : Apache Camel (JBang) 3.21.0 is starting +2023-01-04 17:59:19.395 INFO 44619 --- [ main] org.apache.camel.main.MainSupport : Using Java 17.0.5 with PID 44619. Started by davsclaus in /Users/davsclaus/workspace/ +... +---- + +You can also watch logs for all Camel integrations by `camel log`, or you can specify by name/pids (separate by comma) `camel log bar,chuck`. + ==== Starting and Stopping routes The `camel cmd` is intended for executing miscellaneous commands in the running Camel integrations. 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 d35972a8fe7..5176926abe2 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 @@ -22,6 +22,7 @@ import org.apache.camel.catalog.CamelCatalog; import org.apache.camel.catalog.DefaultCamelCatalog; import org.apache.camel.dsl.jbang.core.commands.action.CamelAction; import org.apache.camel.dsl.jbang.core.commands.action.CamelGCAction; +import org.apache.camel.dsl.jbang.core.commands.action.CamelLogAction; import org.apache.camel.dsl.jbang.core.commands.action.CamelReloadAction; import org.apache.camel.dsl.jbang.core.commands.action.CamelResetStatsAction; import org.apache.camel.dsl.jbang.core.commands.action.CamelRouteStartAction; @@ -72,6 +73,7 @@ public class CamelJBangMain implements Callable<Integer> { commandLine = new CommandLine(main) .addSubcommand("init", new CommandLine(new Init(main))) .addSubcommand("run", new CommandLine(new Run(main))) + .addSubcommand("log", new CommandLine(new CamelLogAction(main))) .addSubcommand("ps", new CommandLine(new ListProcess(main))) .addSubcommand("stop", new CommandLine(new StopProcess(main))) .addSubcommand("get", new CommandLine(new CamelStatus(main)) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelLogAction.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelLogAction.java new file mode 100644 index 00000000000..39d00a28829 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelLogAction.java @@ -0,0 +1,138 @@ +/* + * 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.action; + +import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; +import org.apache.camel.dsl.jbang.core.common.RuntimeUtil; +import org.apache.camel.util.IOHelper; +import org.apache.camel.util.json.JsonObject; +import org.fusesource.jansi.Ansi; +import picocli.CommandLine; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.LineNumberReader; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + [email protected](name = "log", + description = "Tail logs from running Camel integrations") +public class CamelLogAction extends ActionBaseCommand { + + private static final char FIRST_ESC_CHAR = 27; + private static final char SECOND_ESC_CHAR = '['; + +// private static final String ANSI_ESCAPE = ("" + FIRST_ESC_CHAR) + ("" + SECOND_ESC_CHAR) + ("" + '\\') + ("" + 'd') + ("" + '+') + ("" + 'm'); + + private static final String ANSI_ESCAPE = "0x1b\\[\\d*m"; + + @CommandLine.Parameters(description = "Name or pid of running Camel integration. (default selects all)", arity = "0..1") + String name = "*"; + + @CommandLine.Option(names = { "--logging-color" }, defaultValue = "true", description = "Use colored logging") + boolean loggingColor = true; + + @CommandLine.Option(names = { "--tail" }, + description = "The number of lines from the end of the logs to show. Defaults to showing all logs.") + int tail; + + public CamelLogAction(CamelJBangMain main) { + super(main); + } + + @Override + public Integer call() throws Exception { + List<Long> pids = findPids(name); + + if (pids.size() == 1) { + // single log file then no need to interleave logs + File log = logFile(pids.get(0)); + if (log.exists()) { + LineNumberReader lnr = new LineNumberReader(new FileReader(log)); + String line; + + // dump only last N lines + if (tail > 0) { + Queue<String> fifo = new ArrayBlockingQueue<>(tail); + do { + line = lnr.readLine(); + if (line != null) { + while (!fifo.offer(line)) { + fifo.poll(); + } + } + } while (line != null); + fifo.forEach(this::printLine); + } + + // continue read new log lines + do { + line = lnr.readLine(); + if (line != null) { + printLine(line); + } else { + Thread.sleep(50); + } + } while (true); + } + } else { + // TODO: interleave logs based on PID + timestamp + System.out.println("Logs from multiple Camel integrations is currently not yet implemented"); + } + return 0; + } + + protected void printLine(String line) { + if (loggingColor) { + System.out.println(line); + } else { + // unescape ANSI colors + StringBuilder sb = new StringBuilder(); + boolean escaping = false; + char[] arr = line.toCharArray(); + for (int i = 0; i < arr.length; i++) { + char ch = arr[i]; + if (escaping) { + if (ch == 'm') { + escaping = false; + } + continue; + } + char ch2 = i < arr.length - 1 ? arr[i + 1] : 0; + if (ch == 27 && ch2 == '[') { + escaping = true; + continue; + } + + sb.append(ch); + } + line = sb.toString(); + System.out.println(line); + } + } + + private static File logFile(long pid) { + File dir = new File(System.getProperty("user.home"), ".camel"); + String name = pid + ".log"; + return new File(dir, name); + } + +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/log4j2.properties b/dsl/camel-jbang/camel-jbang-core/src/main/resources/log4j2.properties index e92faa54332..6da5d257de8 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/log4j2.properties +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/log4j2.properties @@ -30,7 +30,8 @@ appender.file.createOnDemand = true appender.file.append = false appender.file.layout.type = PatternLayout # logging style that is similar to spring boot (no color) -appender.file.layout.pattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %5p %pid --- [%15.15t] %-40.40c : %m%n +#appender.file.layout.pattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %5p %pid --- [%15.15t] %-40.40c : %m%n +appender.file.layout.pattern = %style{%d{yyyy-MM-dd HH:mm:ss.SSS}}{Dim} %highlight{%5p} %style{%pid}{Magenta} %style{---}{Dim} %style{[%15.15t]}{Dim} %style{%-40.40c}{Cyan} : %m%n # log to console and file rootLogger = INFO,out,file
