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 edf46ac538c0beaaaa564971e76734ceec9dad39
Author: Marat Gubaidullin <marat.gubaidul...@gmail.com>
AuthorDate: Tue May 2 22:32:54 2023 -0400

    Fix #563
---
 .../apache/camel/karavan/api/LogWatchResource.java | 23 +++++++------
 .../camel/karavan/service/KubernetesService.java   | 40 +++++-----------------
 karavan-app/src/main/webui/src/api/KaravanApi.tsx  |  2 +-
 .../src/main/webui/src/projects/ProjectLog.tsx     | 36 +++++++++++--------
 4 files changed, 44 insertions(+), 57 deletions(-)

diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/LogWatchResource.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/LogWatchResource.java
index 5fa14161..ae7ef8b6 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/LogWatchResource.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/LogWatchResource.java
@@ -59,26 +59,27 @@ public class LogWatchResource {
     @Produces(MediaType.SERVER_SENT_EVENTS)
     @Path("/{type}/{env}/{name}")
     public void eventSourcing(@PathParam("env") String env,
-                                       @PathParam("type") String type,
-                                       @PathParam("name") String name,
-                                       @Context SseEventSink eventSink,
-                                       @Context Sse sse
-                                       ) {
+                              @PathParam("type") String type,
+                              @PathParam("name") String name,
+                              @Context SseEventSink eventSink,
+                              @Context Sse sse
+    ) {
         managedExecutor.execute(() -> {
+            LOGGER.info("LogWatch for " + name + " starting...");
             try (SseEventSink sink = eventSink) {
-                LogWatch logWatch = kubernetesService.getLogWatch(name);
+                LogWatch logWatch = type.equals("container")
+                        ? kubernetesService.getContainerLogWatch(name)
+                        : kubernetesService.getPipelineRunLogWatch(name);
                 BufferedReader reader = new BufferedReader(new 
InputStreamReader(logWatch.getOutput()));
                 try {
                     for (String line; (line = reader.readLine()) != null && 
!sink.isClosed(); ) {
-                        sink.send(sse.newEvent(line + System.lineSeparator()));
+                        sink.send(sse.newEvent(line));
                     }
                 } catch (IOException e) {
                     LOGGER.error(e.getMessage());
                 }
-                if (sink.isClosed()) {
-                    logWatch.close();
-                    LOGGER.info("LogWatch for " + name + " closed");
-                }
+                logWatch.close();
+                LOGGER.info("LogWatch for " + name + " closed");
             }
         });
     }
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
index 13b4484c..7bbac8ea 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
@@ -185,37 +185,15 @@ public class KubernetesService implements HealthCheck{
         return logText;
     }
 
-    // TODO: implement log watch
-    public LogWatch getLogWatch(String podName) {
-        return 
kubernetesClient().pods().inNamespace(getNamespace()).withName(podName).watchLog();
-    }
-//    public void startContainerLogWatch(String session, String podName) {
-//        Tuple2<CompletableFuture<Void>, LogWatch> old = 
logWatches.get(session);
-//        if (old != null) {
-//            LOGGER.info("Closing old");
-//            old.getItem1().cancel(true);
-//            old.getItem2().close();
-//            logWatches.remove(session);
-//            LOGGER.info("Closed old");
-//        }
-//
-//        LOGGER.info("Starting startContainerLogWatch");
-//        CompletableFuture<Void> future = managedExecutor.runAsync(() -> {
-//            LogWatch logWatch =
-//            BufferedReader reader = new BufferedReader(new 
InputStreamReader(logWatch.getOutput()));
-//            try {
-//                for (String line; (line = reader.readLine()) != null; ) {
-//                    eventBus.publish(session, System.lineSeparator());
-//                    eventBus.publish(session, line);
-//                    System.out.println(line);
-//                }
-//            } catch (IOException e) {
-//                LOGGER.error(e.getMessage());
-//            }
-//        });
-//        logWatches.put(session, Tuple2.of(future, logWatch));
-//        LOGGER.info("Done startContainerLogWatch");
-//    }
+    public LogWatch getContainerLogWatch(String podName) {
+        return 
kubernetesClient().pods().inNamespace(getNamespace()).withName(podName).tailingLines(100).watchLog();
+    }
+
+    public LogWatch getPipelineRunLogWatch(String pipelineRuneName) {
+        List<TaskRun> tasks = getTaskRuns(pipelineRuneName, getNamespace());
+        TaskRun taskRun = tasks.get(0);
+        return 
kubernetesClient().pods().inNamespace(getNamespace()).withName(taskRun.getStatus().getPodName()).tailingLines(100).watchLog();
+    }
 
     public String getPipelineRunLog(String pipelineRuneName, String namespace) 
{
         StringBuilder result = new StringBuilder();
diff --git a/karavan-app/src/main/webui/src/api/KaravanApi.tsx 
b/karavan-app/src/main/webui/src/api/KaravanApi.tsx
index b456a556..5210e0de 100644
--- a/karavan-app/src/main/webui/src/api/KaravanApi.tsx
+++ b/karavan-app/src/main/webui/src/api/KaravanApi.tsx
@@ -1,4 +1,4 @@
-import axios, {AxiosResponse, AxiosRequestConfig, InternalAxiosRequestConfig, 
AxiosRequestHeaders } from "axios";
+import axios, {AxiosResponse } from "axios";
 import {
     CamelStatus,
     DeploymentStatus,
diff --git a/karavan-app/src/main/webui/src/projects/ProjectLog.tsx 
b/karavan-app/src/main/webui/src/projects/ProjectLog.tsx
index 2b81dda5..f9c3e64c 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectLog.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectLog.tsx
@@ -22,7 +22,8 @@ interface State {
     height?: number | string,
     logViewerRef: any,
     isTextWrapped: boolean
-    data: string[]
+    data: string,
+    currentLine: number
 }
 
 export class ProjectLog extends React.Component<Props, State> {
@@ -32,12 +33,14 @@ export class ProjectLog extends React.Component<Props, 
State> {
         height: "30%",
         logViewerRef: React.createRef(),
         isTextWrapped: true,
-        data: []
+        data: '',
+        currentLine: 0
     }
-
+    eventSource?: EventSource;
     sub?: Subscription;
 
     componentDidMount() {
+        this.eventSource?.close();
         this.sub = ProjectEventBus.onShowLog()?.subscribe((log: 
ShowLogCommand) => {
             this.setState({showLog: true, log: log});
             this.showLogs(log.type, log.name, log.environment);
@@ -45,20 +48,20 @@ export class ProjectLog extends React.Component<Props, 
State> {
     }
 
     componentWillUnmount() {
+        this.eventSource?.close();
         this.sub?.unsubscribe();
     }
 
     showLogs = (type: 'container' | 'pipeline', name: string, environment: 
string) => {
-        if (type === 'pipeline') {
-            KaravanApi.getPipelineLog(environment, name, (res: any) => {
-                this.setState({data: res});
-            });
-        } else if (type === 'container') {
-            KaravanApi.getContainerLog(environment, name, (res: any) => {
-                this.setState({data: res});
-            });
+        this.eventSource?.close();
+        this.eventSource = new 
EventSource("/api/logwatch/"+type+"/"+environment+"/"+name);
+        this.eventSource.onerror = (event) => {
+            this.eventSource?.close();
         }
-
+        this.eventSource.onmessage = (event) => {
+            const data = this.state.data.concat('\n').concat(event.data)
+            this.setState({data: data, currentLine: this.state.currentLine + 
1});
+        };
     }
 
     getButtons() {
@@ -76,12 +79,15 @@ export class ProjectLog extends React.Component<Props, 
State> {
                     this.setState({height: h, showLog: true});
                 }} icon={height === "100%" ? <CollapseIcon/> : <ExpandIcon/>}/>
             </Tooltip>
-            <Button variant="plain" onClick={() => this.setState({height: 
"30%", showLog: false})} icon={<CloseIcon/>}/>
+            <Button variant="plain" onClick={() => {
+                this.eventSource?.close();
+                this.setState({height: "30%", showLog: false, data: '', 
currentLine: 0});
+            }} icon={<CloseIcon/>}/>
         </div>);
     }
 
     render() {
-        const {showLog, height, logViewerRef, isTextWrapped, data} = 
this.state;
+        const {showLog, height, logViewerRef, isTextWrapped, data, 
currentLine} = this.state;
         return (showLog ?
             <PageSection className="project-log" padding={{default: 
"noPadding"}} style={{height: height}}>
                 <LogViewer
@@ -92,6 +98,8 @@ export class ProjectLog extends React.Component<Props, State> 
{
                     header={this.getButtons()}
                     height={"100vh"}
                     data={data}
+                    scrollToRow={currentLine}
+                    overScanCount={10}
                     theme={'dark'}/>
             </PageSection>
             : <></>);

Reply via email to