Skip to content

Commit b2c0618

Browse files
authored
Merge pull request #245 from kubero-dev/243-show-buildlogs
Feature / Add fetch and build logs viewe
2 parents 62ac09b + f992add commit b2c0618

File tree

4 files changed

+89
-53
lines changed

4 files changed

+89
-53
lines changed

client/src/components/apps/logs.vue

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
<template>
2-
<div class="console" id="console" style="height: 100%;">
2+
<div style="height: 90%;">
3+
<v-tabs>
4+
<template>
5+
<v-tab @click="getLogHistory('web')">web</v-tab>
6+
<v-tab @click="getLogHistory('builder')">build</v-tab>
7+
<v-tab @click="getLogHistory('fetcher')">fetch</v-tab>
8+
</template>
9+
</v-tabs>
10+
<div class="console" id="console">
311
<div v-for="line in loglines" :key="line.id">
412
{{ new Date(line.time).toISOString()}}<span :style="'color:' +line.color">[{{ line.podID }}/{{ line.container.replace('kuberoapp-', '') }}]</span>
513
{{ line.log }}
614
</div>
715
</div>
16+
</div>
817
</template>
918

1019
<script>
@@ -16,7 +25,7 @@ export default {
1625
},
1726
},
1827
mounted() {
19-
this.getLogHistory()
28+
this.getLogHistory('web')
2029
this.socketJoin()
2130
this.startLogs()
2231
},
@@ -70,8 +79,8 @@ export default {
7079
console.log("logs started");
7180
});
7281
},
73-
getLogHistory() {
74-
axios.get(`/api/logs/${this.pipeline}/${this.phase}/${this.app}/history`).then((response) => {
82+
getLogHistory(container) {
83+
axios.get(`/api/logs/${this.pipeline}/${this.phase}/${this.app}/${container}/history`).then((response) => {
7584
this.loglines = response.data;
7685
});
7786
},

src/kubero.ts

Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import debug from 'debug';
22
import { Server } from "socket.io";
3-
import { IApp, IPipeline, IPipelineList, IKubectlAppList, IDeployKeyPair, IKubectlPipelineList, IKubectlApp, IPodSize, IKuberoConfig} from './types';
3+
import { IApp, IPipeline, IPipelineList, IKubectlAppList, IDeployKeyPair, IKubectlPipelineList, IKubectlApp, ILoglines, IKuberoConfig} from './types';
44
import { IPullrequest } from './git/types';
55
import { App } from './modules/application';
66
import { Buildpack } from './modules/config';
@@ -842,65 +842,78 @@ export class Kubero {
842842
}
843843
}
844844

845-
public async getLogsHistory(pipelineName: string, phaseName: string, appName: string) {
845+
public async getLogsHistory(pipelineName: string, phaseName: string, appName: string, container: string) {
846846
const contextName = this.getContext(pipelineName, phaseName);
847847
const namespace = pipelineName+'-'+phaseName;
848848

849-
const logStream = new Stream.PassThrough();
850-
let logs: String = '';
851-
logStream.on('data', (chunk: any) => {
852-
//console.log(chunk.toString());
853-
logs += chunk.toString();
854-
});
855-
856-
let loglines: any[] = [];
849+
let loglines: ILoglines[] = [];
857850
if (contextName) {
858851
const pods = await this.kubectl.getPods(namespace, contextName);
859852
for (const pod of pods) {
860853

861854
if (pod.metadata?.name?.startsWith(appName)) {
862-
for (const container of pod.spec?.containers || []) {
863-
console.log('getting logs for '+pod.metadata.name+' '+container.name);
864-
try {
865-
await this.kubectl.log.log(namespace, pod.metadata.name, container.name, logStream, {follow: false, tailLines: 80, pretty: false, timestamps: true})
866-
} catch (error) {
867-
console.log("error getting logs for "+pod.metadata.name+" "+container.name);
868-
return loglines;
869-
}
870-
871-
872-
// sleep for 1 second to wait for all logs to be collected
873-
await new Promise(r => setTimeout(r, 1000));
874-
875-
// split loglines into array
876-
const loglinesArray = logs.split('\n').reverse();
877-
for (const logline of loglinesArray) {
878-
if (logline.length > 0) {
879-
// split after first whitespace
880-
const loglineArray = logline.split(/(?<=^\S+)\s/);
881-
const loglineDate = new Date(loglineArray[0]);
882-
const loglineText = loglineArray[1];
883-
884-
885-
886-
loglines.push({
887-
id: uuidv4(),
888-
time: loglineDate.getTime(),
889-
pipeline: pipelineName,
890-
phase: phaseName,
891-
app: appName,
892-
pod: pod.metadata.name,
893-
podID: pod.metadata.name.split('-')[3]+'-'+pod.metadata.name.split('-')[4],
894-
container: container.name,
895-
color: this.logcolor(pod.metadata.name),
896-
log: loglineText
897-
});
898-
}
855+
if (container == 'web') {
856+
for (const container of pod.spec?.containers || []) {
857+
const ll = await this.fetchLogs(namespace, pod.metadata.name, container.name, pipelineName, phaseName, appName)
858+
loglines = loglines.concat(ll);
899859
}
860+
} else if (container == 'builder' || container == 'fetcher') {
861+
const ll = await this.fetchLogs(namespace, pod.metadata.name, "kuberoapp-"+container, pipelineName, phaseName, appName)
862+
loglines = loglines.concat(ll);
863+
} else {
864+
// leace the loglines empty
865+
console.log('unknown container: '+container);
900866
}
901867
}
902868
}
903869
}
870+
return loglines;
871+
}
872+
873+
private async fetchLogs(namespace: string, podName: string, containerName: string, pipelineName: string, phaseName: string, appName: string): Promise<ILoglines[]> {
874+
let loglines: ILoglines[] = [];
875+
876+
const logStream = new Stream.PassThrough();
877+
let logs: String = '';
878+
logStream.on('data', (chunk: any) => {
879+
//console.log(chunk.toString());
880+
logs += chunk.toString();
881+
});
882+
883+
console.log('getting logs for '+podName+' '+containerName);
884+
try {
885+
await this.kubectl.log.log(namespace, podName, containerName, logStream, {follow: false, tailLines: 80, pretty: false, timestamps: true})
886+
} catch (error) {
887+
console.log("error getting logs for "+podName+" "+containerName);
888+
return [];
889+
}
890+
891+
// sleep for 1 second to wait for all logs to be collected
892+
await new Promise(r => setTimeout(r, 1000));
893+
894+
// split loglines into array
895+
const loglinesArray = logs.split('\n').reverse();
896+
for (const logline of loglinesArray) {
897+
if (logline.length > 0) {
898+
// split after first whitespace
899+
const loglineArray = logline.split(/(?<=^\S+)\s/);
900+
const loglineDate = new Date(loglineArray[0]);
901+
const loglineText = loglineArray[1];
902+
903+
loglines.push({
904+
id: uuidv4(),
905+
time: loglineDate.getTime(),
906+
pipeline: pipelineName,
907+
phase: phaseName,
908+
app: appName,
909+
pod: podName,
910+
podID: podName.split('-')[3]+'-'+podName.split('-')[4],
911+
container: containerName,
912+
color: this.logcolor(podName),
913+
log: loglineText
914+
});
915+
}
916+
}
904917

905918
return loglines;
906919
}

src/routes/logs.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Router.get('/logs/:pipeline/:phase/:app', authMiddleware, async function (req: R
2626
res.send('ok');
2727
});
2828

29-
Router.get('/logs/:pipeline/:phase/:app/history', authMiddleware, async function (req: Request, res: Response) {
29+
Router.get('/logs/:pipeline/:phase/:app/:container/history', authMiddleware, async function (req: Request, res: Response) {
3030
// #swagger.tags = ['UI']
3131
// #swagger.summary = 'Get logs history for a specific app'
3232
// #swagger.description = 'Get logs history for a specific app'
@@ -37,7 +37,8 @@ Router.get('/logs/:pipeline/:phase/:app/history', authMiddleware, async function
3737
const logs = await req.app.locals.kubero.getLogsHistory(
3838
req.params.pipeline,
3939
req.params.phase,
40-
req.params.app
40+
req.params.app,
41+
req.params.container
4142
);
4243
res.send(logs);
4344
});

src/types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,4 +316,17 @@ export interface IDeployKeyPair {
316316
pubKeyBase64: string;
317317
privKey: string;
318318
privKeyBase64: string;
319+
}
320+
321+
export interface ILoglines {
322+
id: string,
323+
time: number,
324+
pipeline: string,
325+
phase: string,
326+
app: string,
327+
pod: string,
328+
podID: string,
329+
container: string,
330+
color: string,
331+
log: string,
319332
}

0 commit comments

Comments
 (0)