feat: Follow logs

This commit is contained in:
Andras Bacsai 2022-02-15 09:38:16 +01:00
parent df31ffd7fb
commit c5b7f92caf
4 changed files with 100 additions and 51 deletions

View File

@ -59,10 +59,14 @@ export async function removeApplication({ id, teamId }) {
const id = containerObj.ID; const id = containerObj.ID;
const preview = containerObj.Image.split('-')[1]; const preview = containerObj.Image.split('-')[1];
await removeDestinationDocker({ id, engine: destinationDocker.engine }); await removeDestinationDocker({ id, engine: destinationDocker.engine });
if (preview) { try {
await removeProxyConfiguration({ domain: `${preview}.${domain}` }); if (preview) {
} else { await removeProxyConfiguration({ domain: `${preview}.${domain}` });
await removeProxyConfiguration({ domain }); } else {
await removeProxyConfiguration({ domain });
}
} catch (error) {
console.log(error);
} }
} }
} }

View File

@ -1,6 +1,5 @@
<script lang="ts"> <script lang="ts">
export let buildId; export let buildId;
export let followingBuild;
import { createEventDispatcher, onDestroy, onMount } from 'svelte'; import { createEventDispatcher, onDestroy, onMount } from 'svelte';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@ -16,11 +15,25 @@
let loading = true; let loading = true;
let currentStatus; let currentStatus;
let streamInterval; let streamInterval;
let followingBuild;
let followingInterval;
let logsEl;
const { id } = $page.params; const { id } = $page.params;
const cleanAnsiCodes = (str: string) => str.replace(/\x1B\[(\d+)m/g, ''); const cleanAnsiCodes = (str: string) => str.replace(/\x1B\[(\d+)m/g, '');
function followBuild() {
followingBuild = !followingBuild;
if (followingBuild) {
followingInterval = setInterval(() => {
logsEl.scrollTop = logsEl.scrollHeight;
window.scrollTo(0, document.body.scrollHeight);
}, 100);
} else {
window.clearInterval(followingInterval);
}
}
async function streamLogs(sequence = 0) { async function streamLogs(sequence = 0) {
try { try {
let { logs: responseLogs, status } = await get( let { logs: responseLogs, status } = await get(
@ -57,7 +70,8 @@
} }
} }
onDestroy(() => { onDestroy(() => {
clearInterval(streamInterval); window.clearInterval(streamInterval);
window.clearInterval(followingInterval);
}); });
onMount(async () => { onMount(async () => {
window.scrollTo(0, 0); window.scrollTo(0, 0);
@ -72,9 +86,33 @@
{#if currentStatus === 'running'} {#if currentStatus === 'running'}
<LoadingLogs /> <LoadingLogs />
{/if} {/if}
<div class="flex justify-end sticky top-0 p-2">
<button
on:click={followBuild}
data-tooltip="Follow logs"
class:text-green-500={followingBuild}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<circle cx="12" cy="12" r="9" />
<line x1="8" y1="12" x2="12" y2="16" />
<line x1="12" y1="8" x2="12" y2="16" />
<line x1="16" y1="12" x2="12" y2="16" />
</svg>
</button>
</div>
<div <div
class="font-mono leading-6 text-left text-md tracking-tighter rounded bg-coolgray-200 py-5 px-6 whitespace-pre-wrap break-words overflow-auto max-h-[80vh]" class="font-mono leading-6 text-left text-md tracking-tighter rounded bg-coolgray-200 py-5 px-6 whitespace-pre-wrap break-words overflow-auto max-h-[80vh] -mt-12"
id="logs" bind:this={logsEl}
> >
{#each logs as log} {#each logs as log}
<div>{log.line + '\n'}</div> <div>{log.line + '\n'}</div>

View File

@ -33,8 +33,6 @@
export let buildCount; export let buildCount;
let buildId; let buildId;
let followingBuild;
$: buildId;
let skip = 0; let skip = 0;
let noMoreBuilds = buildCount < 5 || buildCount <= skip; let noMoreBuilds = buildCount < 5 || buildCount <= skip;
@ -86,15 +84,6 @@
buildId = build; buildId = build;
goto(`/applications/${id}/logs/build?buildId=${buildId}`); goto(`/applications/${id}/logs/build?buildId=${buildId}`);
} }
function followBuild() {
followingBuild = !followingBuild;
if (followingBuild) {
const logEl = document.getElementById('logs');
logEl.scrollTop = logEl.scrollHeight;
window.scrollTo(0, document.body.scrollHeight);
}
}
</script> </script>
<div class="flex space-x-1 p-6 font-bold"> <div class="flex space-x-1 p-6 font-bold">
@ -138,39 +127,16 @@
</div> </div>
{/each} {/each}
</div> </div>
<button <div class="flex space-x-2">
on:click={followBuild} <button disabled={buildCount > 0 && !noMoreBuilds} class="w-full" on:click={loadMoreBuilds}
data-tooltip="Follow logs" >Load More</button
class={followingBuild && 'text-green-500'}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
> >
<path </div>
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 13l-3 3m0 0l-3-3m3 3V8m0 13a9 9 0 110-18 9 9 0 010 18z"
/>
</svg>
</button>
{#if buildCount > 0 && !noMoreBuilds}
<button class="w-full" on:click={loadMoreBuilds}>Load More</button>
{/if}
</div> </div>
<div class="flex-1 md:w-96"> <div class="flex-1 md:w-96">
{#if buildId} {#if buildId}
{#key buildId} {#key buildId}
<svelte:component <svelte:component this={BuildLog} {buildId} on:updateBuildStatus={updateBuildStatus} />
this={BuildLog}
{buildId}
{followingBuild}
on:updateBuildStatus={updateBuildStatus}
/>
{/key} {/key}
{/if} {/if}
</div> </div>

View File

@ -27,19 +27,23 @@
import { getDomain } from '$lib/components/common'; import { getDomain } from '$lib/components/common';
import { get } from '$lib/api'; import { get } from '$lib/api';
import { errorNotification } from '$lib/form'; import { errorNotification } from '$lib/form';
let loadLogsInterval = null; let loadLogsInterval = null;
let logs = []; let logs = [];
let followingBuild;
let followingInterval;
let logsEl;
const { id } = $page.params; const { id } = $page.params;
onMount(async () => { onMount(async () => {
loadLogs(); loadLogs();
loadLogsInterval = setInterval(() => { loadLogsInterval = setInterval(() => {
loadLogs(); loadLogs();
}, 3000); }, 1000);
}); });
onDestroy(() => { onDestroy(() => {
clearInterval(loadLogsInterval); window.clearInterval(loadLogsInterval);
window.clearInterval(followingInterval);
}); });
async function loadLogs() { async function loadLogs() {
try { try {
@ -50,6 +54,18 @@
return errorNotification(error); return errorNotification(error);
} }
} }
function followBuild() {
followingBuild = !followingBuild;
if (followingBuild) {
followingInterval = setInterval(() => {
logsEl.scrollTop = logsEl.scrollHeight;
window.scrollTo(0, document.body.scrollHeight);
}, 100);
} else {
window.clearInterval(followingInterval);
}
}
</script> </script>
<div class="flex space-x-1 p-6 font-bold"> <div class="flex space-x-1 p-6 font-bold">
@ -63,8 +79,33 @@
{:else} {:else}
<div class="relative w-full"> <div class="relative w-full">
<LoadingLogs /> <LoadingLogs />
<div class="flex justify-end sticky top-0 p-2">
<button
on:click={followBuild}
data-tooltip="Follow logs"
class:text-green-500={followingBuild}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<circle cx="12" cy="12" r="9" />
<line x1="8" y1="12" x2="12" y2="16" />
<line x1="12" y1="8" x2="12" y2="16" />
<line x1="16" y1="12" x2="12" y2="16" />
</svg>
</button>
</div>
<div <div
class="font-mono leading-6 text-left text-md tracking-tighter rounded bg-coolgray-200 p-6 whitespace-pre-wrap break-words w-full" class="font-mono leading-6 text-left text-md tracking-tighter rounded bg-coolgray-200 p-6 whitespace-pre-wrap break-words w-full mb-10 -mt-12"
bind:this={logsEl}
> >
{#each logs as log} {#each logs as log}
{log + '\n'} {log + '\n'}