You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2023/05/03 02:33:07 UTC
[camel-karavan] 04/04: Fix #563
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 <ma...@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>
: <></>);