Skip to content

Commit 3a988b8

Browse files
authored
feat: updates agents to be more resilient by reconnecting. also adds big performance issues in swarm mode with little updates to the UI. (#3145)
1 parent c87a7b1 commit 3a988b8

29 files changed

+559
-240
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"i18n-ally.localesPaths": ["locales"],
33
"i18n-ally.keystyle": "nested",
4-
"cSpell.words": ["healthcheck", "orderedmap", "stdcopy", "Warnf"],
4+
"cSpell.words": ["healthcheck", "orderedmap", "Retriable", "stdcopy", "Warnf"],
55
"editor.formatOnSave": true,
66
"i18n-ally.extract.autoDetect": true
77
}

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,5 @@ $(GEN_DIR)/%.pb.go: $(PROTO_DIR)/%.proto
5555

5656
.PHONY: push
5757
push: docker
58-
@docker tag amir20/dozzle:latest amir20/dozzle:agent
59-
@docker push amir20/dozzle:agent
58+
@docker tag amir20/dozzle:latest amir20/dozzle:local-test
59+
@docker push amir20/dozzle:local-test

assets/components.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ declare module 'vue' {
4040
FieldList: typeof import('./components/LogViewer/FieldList.vue')['default']
4141
FuzzySearchModal: typeof import('./components/FuzzySearchModal.vue')['default']
4242
GroupedLog: typeof import('./components/GroupedViewer/GroupedLog.vue')['default']
43+
HostIcon: typeof import('./components/common/HostIcon.vue')['default']
4344
HostList: typeof import('./components/HostList.vue')['default']
4445
HostMenu: typeof import('./components/HostMenu.vue')['default']
4546
'Ic:sharpKeyboardReturn': typeof import('~icons/ic/sharp-keyboard-return')['default']
@@ -63,9 +64,12 @@ declare module 'vue' {
6364
'Mdi:chevronRight': typeof import('~icons/mdi/chevron-right')['default']
6465
'Mdi:close': typeof import('~icons/mdi/close')['default']
6566
'Mdi:cog': typeof import('~icons/mdi/cog')['default']
67+
'Mdi:docker': typeof import('~icons/mdi/docker')['default']
6668
'Mdi:hamburgerMenu': typeof import('~icons/mdi/hamburger-menu')['default']
69+
'Mdi:hexagonMultiple': typeof import('~icons/mdi/hexagon-multiple')['default']
6770
'Mdi:keyboardEsc': typeof import('~icons/mdi/keyboard-esc')['default']
6871
'Mdi:magnify': typeof import('~icons/mdi/magnify')['default']
72+
'Mdi:satelliteVariant': typeof import('~icons/mdi/satellite-variant')['default']
6973
MobileMenu: typeof import('./components/common/MobileMenu.vue')['default']
7074
MultiContainerLog: typeof import('./components/MultiContainerViewer/MultiContainerLog.vue')['default']
7175
MultiContainerStat: typeof import('./components/LogViewer/MultiContainerStat.vue')['default']
@@ -80,6 +84,7 @@ declare module 'vue' {
8084
'Ph:computerTower': typeof import('~icons/ph/computer-tower')['default']
8185
'Ph:controlBold': typeof import('~icons/ph/control-bold')['default']
8286
'Ph:cpu': typeof import('~icons/ph/cpu')['default']
87+
'Ph:globeSimple': typeof import('~icons/ph/globe-simple')['default']
8388
'Ph:memory': typeof import('~icons/ph/memory')['default']
8489
'Ph:stack': typeof import('~icons/ph/stack')['default']
8590
'Ph:stackSimple': typeof import('~icons/ph/stack-simple')['default']

assets/components/HostList.vue

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,37 @@
22
<ul class="grid gap-4 md:grid-cols-[repeat(auto-fill,minmax(480px,1fr))]">
33
<li v-for="host in hosts" class="card bg-base-lighter">
44
<div class="card-body grid auto-cols-auto grid-flow-col justify-between gap-4">
5-
<div class="overflow-hidden">
6-
<div class="truncate text-xl font-semibold">
7-
{{ host.name }} <span class="badge badge-error badge-xs p-1.5" v-if="!host.available">offline</span>
5+
<div class="flex flex-col gap-2 overflow-hidden">
6+
<div class="flex items-center gap-1 truncate text-xl font-semibold">
7+
<HostIcon :type="host.type" />
8+
{{ host.name }}
9+
10+
<span class="badge badge-error badge-xs gap-2 p-2" v-if="!host.available">
11+
<carbon:warning />
12+
offline
13+
</span>
14+
<span
15+
class="badge badge-success badge-xs gap-2 p-2"
16+
:class="{ 'badge-warning': config.version != host.agentVersion }"
17+
v-else-if="host.type == 'agent'"
18+
title="Dozzle Agent"
19+
>
20+
{{ host.agentVersion }}
21+
</span>
822
</div>
9-
<ul class="flex flex-row gap-2 text-sm md:gap-4">
10-
<li><ph:cpu class="inline-block" /> {{ host.nCPU }} <span class="mobile-hidden">CPUs</span></li>
11-
<li>
12-
<ph:memory class="inline-block" /> {{ formatBytes(host.memTotal) }}
23+
<ul class="flex flex-row gap-2 text-sm md:gap-3">
24+
<li class="flex items-center gap-1"><ph:cpu /> {{ host.nCPU }} <span class="mobile-hidden">CPUs</span></li>
25+
<li class="flex items-center gap-1">
26+
<ph:memory /> {{ formatBytes(host.memTotal) }}
1327
<span class="mobile-hidden">total</span>
1428
</li>
1529
</ul>
16-
<div class="text-sm">
17-
<octicon:container-24 class="inline-block" /> {{ $t("label.container", hostContainers[host.id]?.length) }}
18-
</div>
30+
<ul class="flex flex-row gap-2 text-sm md:gap-3">
31+
<li class="flex items-center gap-1">
32+
<octicon:container-24 class="inline-block" /> {{ $t("label.container", hostContainers[host.id]?.length) }}
33+
</li>
34+
<li class="flex items-center gap-1"><mdi:docker class="inline-block" /> {{ host.dockerVersion }}</li>
35+
</ul>
1936
</div>
2037

2138
<div class="flex flex-row gap-4 md:gap-8" v-if="weightedStats[host.id]">

assets/components/HostMenu.vue

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<ul class="menu p-0">
1616
<li v-for="host in hosts" :key="host.id">
1717
<a @click.prevent="setHost(host.id)" :class="{ 'pointer-events-none text-base-content/50': !host.available }">
18-
<ph:computer-tower />
18+
<HostIcon :type="host.type" />
1919
{{ host.name }}
2020
<span class="badge badge-error badge-xs p-1.5" v-if="!host.available">offline</span>
2121
</a>
@@ -25,7 +25,6 @@
2525
<template #right>
2626
<ul class="containers menu p-0 [&_li.menu-title]:px-0">
2727
<li v-for="{ label, containers, icon } in menuItems" :key="label">
28-
<!-- @vue-ignore -->
2928
<details :open="!collapsedGroups.has(label)" @toggle="updateCollapsedGroups($event, label)">
3029
<summary class="font-light text-base-content/80">
3130
<component :is="icon" />
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<template>
2+
<mdi:satellite-variant v-if="type == 'agent'" />
3+
<ph:globe-simple v-else-if="type == 'remote'" />
4+
<mdi:hexagon-multiple v-else-if="type == 'swarm'" />
5+
<ph:computer-tower v-else />
6+
</template>
7+
<script setup lang="ts">
8+
import { Host } from "@/stores/hosts";
9+
const { type } = defineProps<{ type: Host["type"] }>();
10+
</script>

assets/main.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
--in: 65% 0.171 249.5;
1818
--inc: 100% 0 0;
1919
--er: 64% 0.218 28.85;
20+
--su: 56% 0.119722 164.12;
2021
--erc: 100% 0 0;
2122
--wa: 70% 0.186 48.13;
2223
--wac: 100% 0 0;

assets/stores/config.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@ import { Host } from "@/stores/hosts";
33

44
const text = document.querySelector("script#config__json")?.textContent || "{}";
55

6-
type HostWithoutAvailable = Omit<Host, "available">;
7-
86
export interface Config {
97
version: string;
108
base: string;
119
maxLogs: number;
1210
hostname: string;
13-
hosts: HostWithoutAvailable[];
11+
hosts: Host[];
1412
authProvider: "simple" | "none" | "forward-proxy";
1513
enableActions: boolean;
1614
user?: {

assets/stores/container.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import { Ref, UnwrapNestedRefs } from "vue";
33
import type { ContainerHealth, ContainerJson, ContainerStat } from "@/types/Container";
44
import { Container } from "@/models/Container";
55
import i18n from "@/modules/i18n";
6+
import { Host } from "./hosts";
67

78
const { showToast, removeToast } = useToast();
8-
const { markHostAvailable } = useHosts();
9+
const { updateHost } = useHosts();
910
// @ts-ignore
1011
const { t } = i18n.global;
1112

@@ -74,9 +75,9 @@ export const useContainerStore = defineStore("container", () => {
7475
}
7576
});
7677

77-
es.addEventListener("host-unavailable", (e) => {
78-
const hostId = (e as MessageEvent).data;
79-
markHostAvailable(hostId, false);
78+
es.addEventListener("update-host", (e) => {
79+
const host = JSON.parse((e as MessageEvent).data) as Host;
80+
updateHost(host);
8081
});
8182

8283
es.addEventListener("container-health", (e) => {

assets/stores/hosts.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,35 @@
11
export type Host = {
2-
name: string;
32
id: string;
3+
name: string;
44
nCPU: number;
55
memTotal: number;
6+
type: "agent" | "local" | "remote" | "swarm";
7+
endpoint: string;
68
available: boolean;
9+
dockerVersion: string;
10+
agentVersion: string;
711
};
8-
const hosts = computed(() =>
9-
config.hosts.reduce(
10-
(acc, item) => {
11-
acc[item.id] = { ...item, available: true };
12-
return acc;
13-
},
14-
{} as Record<string, Host>,
15-
),
16-
);
1712

18-
const markHostAvailable = (id: string, available: boolean) => {
19-
hosts.value[id].available = available;
13+
const hosts = ref(
14+
config.hosts
15+
.sort((a, b) => a.name.localeCompare(b.name))
16+
.reduce(
17+
(acc, item) => {
18+
acc[item.id] = item;
19+
return acc;
20+
},
21+
{} as Record<string, Host>,
22+
),
23+
);
24+
const updateHost = (host: Host) => {
25+
delete hosts.value[host.endpoint];
26+
hosts.value[host.id] = host;
27+
return host;
2028
};
2129

2230
export function useHosts() {
2331
return {
2432
hosts,
25-
markHostAvailable,
33+
updateHost,
2634
};
2735
}

0 commit comments

Comments
 (0)