This is an automated email from the ASF dual-hosted git repository.

marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git

commit f90b524b1d1b54d4c1871b95a9253daa1f623f03
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Sun Jul 23 12:55:41 2023 -0400

    Log in UI with Docker #817
---
 .../apache/camel/karavan/api/LogWatchResource.java | 33 +++++++++++++++++++---
 .../camel/karavan/docker/DockerEventListener.java  |  2 +-
 .../apache/camel/karavan/docker/DockerService.java |  6 ++--
 .../apache/camel/karavan/docker/LogCallback.java   | 11 ++++----
 .../apache/camel/karavan/service/EventService.java |  1 -
 .../camel/karavan/service/ProjectService.java      |  9 +++++-
 .../camel/karavan/service/ScheduledService.java    | 17 +++++++++--
 .../src/main/resources/application.properties      |  7 +++--
 .../src/main/webui/src/api/ProjectStore.ts         | 17 ++++++++---
 .../src/main/webui/src/project/ProjectToolbar.tsx  |  9 +-----
 .../camel/karavan/headless/HeadlessService.java    |  2 +-
 .../src/main/resources/application.properties      |  2 +-
 12 files changed, 80 insertions(+), 36 deletions(-)

diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/LogWatchResource.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/LogWatchResource.java
index 3a235592..40cbc79a 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/LogWatchResource.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/LogWatchResource.java
@@ -17,10 +17,15 @@
 package org.apache.camel.karavan.api;
 
 import io.fabric8.kubernetes.client.dsl.LogWatch;
+import io.smallrye.context.api.ManagedExecutorConfig;
+import io.smallrye.context.api.NamedInstance;
+import org.apache.camel.karavan.docker.DockerService;
+import org.apache.camel.karavan.docker.LogCallback;
 import org.apache.camel.karavan.infinispan.InfinispanService;
 import org.apache.camel.karavan.kubernetes.KubernetesService;
 import org.apache.camel.karavan.shared.ConfigService;
 import org.eclipse.microprofile.context.ManagedExecutor;
+import org.eclipse.microprofile.context.ThreadContext;
 import org.jboss.logging.Logger;
 
 import javax.inject.Inject;
@@ -30,11 +35,13 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.sse.Sse;
 import javax.ws.rs.sse.SseEventSink;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 
 @Path("/api/logwatch")
@@ -47,9 +54,11 @@ public class LogWatchResource {
     KubernetesService kubernetesService;
 
     @Inject
-    InfinispanService infinispanService;
+    DockerService dockerService;
 
     @Inject
+    @ManagedExecutorConfig()
+    @NamedInstance("logExecutor")
     ManagedExecutor managedExecutor;
 
     @GET
@@ -57,19 +66,35 @@ public class LogWatchResource {
     @Path("/{type}/{name}")
     public void eventSourcing(@PathParam("type") String type,
                               @PathParam("name") String name,
+                              @Context SecurityContext securityContext,
                               @Context SseEventSink eventSink,
-                              @Context Sse sse
-    ) {
+                              @Context Sse sse) {
+
         managedExecutor.execute(() -> {
             LOGGER.info("LogWatch for " + name + " starting...");
             if (ConfigService.inKubernetes()) {
                 getKubernetesLogs(type, name, eventSink, sse);
             } else {
-//                
infinispanService.sendDevModeCommand(DevModeCommand.createForContainer(DevModeCommandName.LOG,
 name));
+                getDockerLogs(type, name, eventSink, sse);
             }
         });
     }
 
+    private void getDockerLogs(String type, String name, SseEventSink 
eventSink, Sse sse) {
+        LOGGER.info("LogCallback for " + name + " starting");
+        try (SseEventSink sink = eventSink) {
+            LogCallback logCallback = new LogCallback(line -> {
+                sink.send(sse.newEvent(line));
+            });
+            dockerService.logContainer(name, logCallback);
+            logCallback.close();
+            sink.close();
+            LOGGER.info("LogCallback for " + name + " closed");
+        } catch (Exception e) {
+            LOGGER.error(e.getMessage());
+        }
+    }
+
     private void getKubernetesLogs(String type, String name, SseEventSink 
eventSink, Sse sse) {
         try (SseEventSink sink = eventSink) {
             LogWatch logWatch = type.equals("container")
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java
index 0ee8000a..8d4c9cc3 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java
@@ -159,7 +159,7 @@ public class DockerEventListener implements 
ResultCallback<Event> {
 
     @Override
     public void close() throws IOException {
-        LOGGER.error("DockerEventListener close");
+        LOGGER.info("DockerEventListener close");
     }
 
 
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
index 3b380749..9f1f4198 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
@@ -120,6 +120,7 @@ public class DockerService {
 
     public void deleteKaravanHeadlessContainer() {
         try {
+            stopContainer(KARAVAN_CONTAINER_NAME);
             deleteContainer(KARAVAN_CONTAINER_NAME);
         } catch (Exception e) {
             LOGGER.error(e.getMessage());
@@ -252,11 +253,10 @@ public class DockerService {
         startContainer(name);
     }
 
-    public LogCallback logContainer(String containerName) {
+    public void logContainer(String containerName, LogCallback callback) {
         try {
             Container container = getContainerByName(containerName);
             if (container != null) {
-                LogCallback callback = new LogCallback(eventBus);
                 getDockerClient().logContainerCmd(container.getId())
                         .withStdOut(true)
                         .withStdErr(true)
@@ -265,12 +265,10 @@ public class DockerService {
                         .withTailAll()
                         .exec(callback);
                 callback.awaitCompletion();
-                return callback;
             }
         } catch (Exception e) {
             LOGGER.error(e.getMessage());
         }
-        return null;
     }
 
     public void stopContainer(String name) {
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/LogCallback.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/LogCallback.java
index a05efb31..bd0de584 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/LogCallback.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/LogCallback.java
@@ -2,19 +2,20 @@ package org.apache.camel.karavan.docker;
 
 import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.api.model.Frame;
-import io.vertx.core.eventbus.EventBus;
+
+import java.util.function.Consumer;
 
 public class LogCallback extends ResultCallback.Adapter<Frame> {
 
-    private final EventBus eventBus;
+    private final Consumer<String> action;
 
-    public LogCallback(EventBus eventBus) {
-        this.eventBus = eventBus;
+    public LogCallback(Consumer<String> action) {
+        this.action = action;
     }
 
     @Override
     public void onNext(Frame frame) {
-        System.out.println(new String(frame.getPayload()));
+        action.accept(new String(frame.getPayload()));
     }
 
 }
\ No newline at end of file
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java
index fe48ad1c..4d6f0b7a 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java
@@ -49,7 +49,6 @@ public class EventService {
             infinispanService.start(false);
             infinispanService.clearAllStatuses();
             if (!ConfigService.inKubernetes()) {
-                dockerService.deleteKaravanHeadlessContainer();
                 dockerService.startKaravanHeadlessContainer();
                 dockerService.collectContainersStatuses();
             }
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java
index 87c7dbe4..815eab38 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java
@@ -36,6 +36,7 @@ import javax.enterprise.inject.Default;
 import javax.inject.Inject;
 import java.time.Instant;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import static org.apache.camel.karavan.shared.EventType.IMPORT_PROJECTS;
@@ -47,6 +48,9 @@ public class ProjectService implements HealthCheck{
 
     private static final Logger LOGGER = 
Logger.getLogger(ProjectService.class.getName());
 
+    @ConfigProperty(name = "karavan.git.pull.interval")
+    String gitPullInterval;
+
     @Inject
     InfinispanService infinispanService;
 
@@ -91,6 +95,7 @@ public class ProjectService implements HealthCheck{
     void importCommits() {
         LOGGER.info("Import commits...");
         gitService.getAllCommits().forEach(commitInfo -> {
+            System.out.println(commitInfo.getCommitId() + " " + 
Instant.ofEpochSecond(commitInfo.getTime()).toString());
             infinispanService.saveCommit(commitInfo.getCommitId(), 
commitInfo.getTime());
             infinispanService.saveLastCommit(commitInfo.getCommitId());
         });
@@ -103,7 +108,9 @@ public class ProjectService implements HealthCheck{
         }
         addTemplatesProject();
         addServicesProject();
-        importCommits();
+        if (!Objects.equals("disabled", gitPullInterval.toLowerCase()) && 
!Objects.equals("off", gitPullInterval.toLowerCase())) {
+            importCommits();
+        }
     }
 
     private void importAllProjects() {
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java
index d7f32e95..7886a86d 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java
@@ -18,6 +18,7 @@ package org.apache.camel.karavan.service;
 
 import io.quarkus.scheduler.Scheduled;
 import org.apache.camel.karavan.docker.DockerService;
+import org.apache.camel.karavan.infinispan.InfinispanService;
 import org.apache.camel.karavan.shared.ConfigService;
 import org.jboss.logging.Logger;
 
@@ -38,12 +39,22 @@ public class ScheduledService {
     @Inject
     CamelService camelService;
 
-    @Scheduled(every = "{karavan.container.statistics.container}", 
concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
+    @Inject
+    InfinispanService infinispanService;
+
+    @Scheduled(every = "{karavan.container.statistics.interval}", 
concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
     void collectContainersStats() {
         dockerService.collectContainersStats();
     }
 
-    @Scheduled(every = "{karavan.camel.status.pull-interval}", 
concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
+    @Scheduled(every = "{karavan.container.infinispan.interval}", 
concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
+    void checkInfinispanHealth() {
+        if (!infinispanService.isReady()) {
+            dockerService.checkInfinispanHealth();
+        }
+    }
+
+    @Scheduled(every = "{karavan.camel.status.interval}", concurrentExecution 
= Scheduled.ConcurrentExecution.SKIP)
     void collectCamelStatuses() {
         LOGGER.info("Collect info statuses");
         if (ConfigService.inKubernetes()) {
@@ -52,7 +63,7 @@ public class ScheduledService {
         }
     }
 
-    @Scheduled(every = "{karavan.git.pull-interval}", concurrentExecution = 
Scheduled.ConcurrentExecution.SKIP)
+    @Scheduled(every = "{karavan.git.pull.interval}", concurrentExecution = 
Scheduled.ConcurrentExecution.SKIP)
     void pullCommitsFromGit() {
         projectService.pullCommits();
     }
diff --git a/karavan-web/karavan-app/src/main/resources/application.properties 
b/karavan-web/karavan-app/src/main/resources/application.properties
index 76045045..2cee473c 100644
--- a/karavan-web/karavan-app/src/main/resources/application.properties
+++ b/karavan-web/karavan-app/src/main/resources/application.properties
@@ -3,8 +3,9 @@ karavan.environment=dev
 karavan.environments=dev,test,prod
 karavan.default-runtime=quarkus
 karavan.runtimes=quarkus,spring-boot
-karavan.camel.status.pull-interval=off
-karavan.container.statistics.container=3s
+karavan.camel.status.interval=off
+karavan.container.statistics.interval=3s
+karavan.container.infinispan.interval=5s
 karavan.devmode.image=ghcr.io/apache/camel-karavan-runner:3.21.1-snapshot
 karavan.headless.image=entropy1/karavan-headless:3.21.1-SNAPSHOT
 
@@ -13,7 +14,7 @@ karavan.git.repository=${GIT_REPOSITORY}
 karavan.git.username=${GIT_USERNAME}
 karavan.git.password=${GIT_TOKEN}
 karavan.git.branch=main
-karavan.git.pull-interval=disabled
+karavan.git.pull.interval=disabled
 
 # Infinispan container config in Docker
 infinispan.image=quay.io/infinispan/server:14.0.6.Final
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts 
b/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts
index 9a891b3e..b4930ead 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts
+++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts
@@ -191,10 +191,16 @@ export const useLogStore = create<LogState>((set) => ({
         set({data: data})
     },
     addData: (data: string)  => {
-        set((state: LogState) => ({data: 
state.data.concat('\n').concat(data)}))
+        set((state: LogState) => {
+            const delimiter = state.data.endsWith('\n') ? '' : '\n';
+            return ({data: state.data.concat(delimiter, data)})
+        })
     },
     addDataAsync: async (data: string) => {
-        set((state: LogState) => ({data: 
state.data.concat('\n').concat(data)}))
+        set((state: LogState) => {
+            const delimiter = state.data.endsWith('\n') ? '' : '\n';
+            return ({data: state.data.concat(delimiter, data)})
+        })
     },
     currentLine: 0,
     setCurrentLine: (currentLine: number)  => {
@@ -217,8 +223,11 @@ console.log("Start log subscriber");
 const sub = ProjectEventBus.onLog()?.subscribe((result: ["add" | "set", 
string]) => {
     if (result[0] === 'add') {
         unstable_batchedUpdates(() => {
-            useLogStore.setState((state: LogState) =>
-                ({data: state.data ? state.data.concat('\n').concat(result[1]) 
: result[1], currentLine: state.currentLine+1}))
+            useLogStore.setState((state: LogState) => {
+                const delimiter = state.data.endsWith('\n') ? '' : '\n';
+                const newData  = state.data ? state.data.concat(delimiter, 
result[1]) : result[1]
+                return ({data: newData, currentLine: state.currentLine+1});
+            })
         })
     }
     else if (result[0] === 'set') {
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/ProjectToolbar.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/ProjectToolbar.tsx
index 4e6c5704..2f639228 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/ProjectToolbar.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/ProjectToolbar.tsx
@@ -4,13 +4,11 @@ import {
     Checkbox,
     Flex,
     FlexItem,
-    Label,
     ToggleGroup,
     ToggleGroupItem,
     Toolbar,
     ToolbarContent,
-    Tooltip,
-    TooltipPosition
+    Tooltip
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
 import DownloadImageIcon from 
"@patternfly/react-icons/dist/esm/icons/image-icon";
@@ -79,11 +77,6 @@ export const ProjectToolbar = (props: Props) => {
         return <Toolbar id="toolbar-group-types">
             <ToolbarContent>
                 <Flex className="toolbar" direction={{default: "row"}} 
alignItems={{default: "alignItemsCenter"}}>
-                    {isJava() && <FlexItem>
-                        <Tooltip content="File size" 
position={TooltipPosition.bottom}>
-                            <Label>{file?.code?.length}</Label>
-                        </Tooltip>
-                    </FlexItem>}
                     {isRunnable() && <DevModeToolbar reloadOnly={true}/>}
                     {isYaml() && <FlexItem>
                         <ToggleGroup>
diff --git 
a/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/HeadlessService.java
 
b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/HeadlessService.java
index 01b00da7..e6f8624f 100644
--- 
a/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/HeadlessService.java
+++ 
b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/HeadlessService.java
@@ -42,7 +42,7 @@ public class HeadlessService {
         infinispanService.clearAllStatuses();
     }
 
-    @Scheduled(every = "{karavan.camel.status.pull-interval}", 
concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
+    @Scheduled(every = "{karavan.camel.status.interval}", concurrentExecution 
= Scheduled.ConcurrentExecution.SKIP)
     void collectCamelStatuses() {
         LOGGER.info("Collect info statuses");
         // collect Camel statuses
diff --git 
a/karavan-web/karavan-headless/src/main/resources/application.properties 
b/karavan-web/karavan-headless/src/main/resources/application.properties
index dedfb854..ec2c2f7c 100644
--- a/karavan-web/karavan-headless/src/main/resources/application.properties
+++ b/karavan-web/karavan-headless/src/main/resources/application.properties
@@ -1,5 +1,5 @@
 karavan.environment=dev
-karavan.camel.status.pull-interval=3s
+karavan.camel.status.interval=3s
 
 infinispan.hosts=infinispan:11222
 infinispan.username=admin

Reply via email to