diff --git a/beszel/internal/agent/agent.go b/beszel/internal/agent/agent.go index 6117263..e7b2030 100644 --- a/beszel/internal/agent/agent.go +++ b/beszel/internal/agent/agent.go @@ -84,18 +84,22 @@ func (a *Agent) Run(pubKey []byte, addr string) { func (a *Agent) gatherStats() system.CombinedData { slog.Debug("Getting stats") - systemData := system.CombinedData{ - Stats: a.getSystemStats(), - Info: a.systemInfo, - } - slog.Debug("System stats", "data", systemData) - // add docker stats + // systemData := system.CombinedData{ + // Stats: a.getSystemStats(), + // Info: a.systemInfo, + // } + systemData := system.CombinedData{} + // add docker stats (testing doing this first for docker 24) if containerStats, err := a.dockerManager.getDockerStats(); err == nil { systemData.Containers = containerStats slog.Debug("Docker stats", "data", systemData.Containers) } else { slog.Debug("Error getting docker stats", "err", err) } + systemData.Stats = a.getSystemStats() + systemData.Info = a.systemInfo + slog.Debug("System stats", "data", systemData) + // add extra filesystems systemData.Stats.ExtraFs = make(map[string]*system.FsStats) for name, stats := range a.fsStats { diff --git a/beszel/internal/agent/docker.go b/beszel/internal/agent/docker.go index 178951c..6fab85d 100644 --- a/beszel/internal/agent/docker.go +++ b/beszel/internal/agent/docker.go @@ -25,18 +25,23 @@ type dockerManager struct { apiContainerList *[]container.ApiInfo // List of containers from Docker API containerStatsMap map[string]*container.Stats // Keeps track of container stats validIds map[string]struct{} // Map of valid container ids, used to prune invalid containers from containerStatsMap + goodDockerVersion bool // Whether docker version is at least 25.0.0 (one-shot works correctly) } // Add goroutine to the queue func (d *dockerManager) queue() { - d.sem <- struct{}{} d.wg.Add(1) + if d.goodDockerVersion { + d.sem <- struct{}{} + } } // Remove goroutine from the queue func (d *dockerManager) dequeue() { - <-d.sem d.wg.Done() + if d.goodDockerVersion { + <-d.sem + } } // Returns stats for all running containers @@ -47,6 +52,11 @@ func (dm *dockerManager) getDockerStats() ([]*container.Stats, error) { } defer resp.Body.Close() + // test sleeping for 1 second if docker 24 + if !dm.goodDockerVersion { + time.Sleep(time.Millisecond * 1100) + } + if err := json.NewDecoder(resp.Body).Decode(&dm.apiContainerList); err != nil { return nil, err } @@ -89,11 +99,11 @@ func (dm *dockerManager) getDockerStats() ([]*container.Stats, error) { // retry failed containers separately so we can run them in parallel (docker 24 bug) if len(failedContainters) > 0 { slog.Debug("Retrying failed containers", "count", len(failedContainters)) - // time.Sleep(time.Millisecond * 1100) + time.Sleep(time.Millisecond * 1100) // this is a test for docker 24 bug for _, ctr := range failedContainters { - dm.wg.Add(1) + dm.queue() go func() { - defer dm.wg.Done() + defer dm.dequeue() err = dm.updateContainerStats(ctr) if err != nil { slog.Error("Error getting container stats", "err", err) @@ -251,12 +261,9 @@ func newDockerManager() *dockerManager { Transport: transport, }, containerStatsMap: make(map[string]*container.Stats), + sem: make(chan struct{}, 5), } - // Make sure sem is initialized - concurrency := 200 - defer func() { dockerClient.sem = make(chan struct{}, concurrency) }() - // Check docker version // (versions before 25.0.0 have a bug with one-shot which requires all requests to be made in one batch) var versionInfo struct { @@ -273,9 +280,10 @@ func newDockerManager() *dockerManager { // if version > 24, one-shot works correctly and we can limit concurrent operations if dockerVersion, err := semver.Parse(versionInfo.Version); err == nil && dockerVersion.Major > 24 { - concurrency = 5 + dockerClient.goodDockerVersion = true + } else { + slog.Info(fmt.Sprintf("Docker %s is outdated. Upgrade if possible. See https://github.com/henrygd/beszel/issues/58", versionInfo.Version)) } - slog.Debug("Docker", "version", versionInfo.Version, "concurrency", concurrency) return dockerClient } diff --git a/beszel/site/bun.lockb b/beszel/site/bun.lockb index 6d9583e..fdb646c 100755 Binary files a/beszel/site/bun.lockb and b/beszel/site/bun.lockb differ diff --git a/beszel/site/index.html b/beszel/site/index.html index 726bf8b..e772f4b 100644 --- a/beszel/site/index.html +++ b/beszel/site/index.html @@ -1,5 +1,5 @@ - + diff --git a/beszel/site/package-lock.json b/beszel/site/package-lock.json index 873fedb..24c81eb 100644 --- a/beszel/site/package-lock.json +++ b/beszel/site/package-lock.json @@ -14,6 +14,7 @@ "@radix-ui/react-alert-dialog": "^1.1.2", "@radix-ui/react-checkbox": "^1.1.2", "@radix-ui/react-dialog": "^1.1.2", + "@radix-ui/react-direction": "^1.1.0", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-select": "^2.1.2", @@ -31,7 +32,6 @@ "cmdk": "^1.0.0", "d3-time": "^3.1.0", "i18next": "^23.16.4", - "i18next-browser-languagedetector": "^8.0.0", "lucide-react": "^0.452.0", "nanostores": "^0.11.3", "pocketbase": "^0.21.5", @@ -50,6 +50,7 @@ "autoprefixer": "^10.4.20", "postcss": "^8.4.47", "tailwindcss": "^3.4.14", + "tailwindcss-rtl": "^0.9.0", "typescript": "^5.6.3", "vite": "^5.4.9" }, @@ -4153,15 +4154,6 @@ "@babel/runtime": "^7.23.2" } }, - "node_modules/i18next-browser-languagedetector": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz", - "integrity": "sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.23.2" - } - }, "node_modules/internmap": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", @@ -5344,6 +5336,13 @@ "tailwindcss": ">=3.0.0 || insiders" } }, + "node_modules/tailwindcss-rtl": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/tailwindcss-rtl/-/tailwindcss-rtl-0.9.0.tgz", + "integrity": "sha512-y7yC8QXjluDBEFMSX33tV6xMYrf0B3sa+tOB5JSQb6/G6laBU313a+Z+qxu55M1Qyn8tDMttjomsA8IsJD+k+w==", + "dev": true, + "license": "MIT" + }, "node_modules/tailwindcss/node_modules/picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", diff --git a/beszel/site/package.json b/beszel/site/package.json index 140b812..7535aed 100644 --- a/beszel/site/package.json +++ b/beszel/site/package.json @@ -15,6 +15,7 @@ "@radix-ui/react-alert-dialog": "^1.1.2", "@radix-ui/react-checkbox": "^1.1.2", "@radix-ui/react-dialog": "^1.1.2", + "@radix-ui/react-direction": "^1.1.0", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-select": "^2.1.2", @@ -50,6 +51,7 @@ "autoprefixer": "^10.4.20", "postcss": "^8.4.47", "tailwindcss": "^3.4.14", + "tailwindcss-rtl": "^0.9.0", "typescript": "^5.6.3", "vite": "^5.4.9" }, diff --git a/beszel/site/src/components/add-system.tsx b/beszel/site/src/components/add-system.tsx index cc27dad..f90d846 100644 --- a/beszel/site/src/components/add-system.tsx +++ b/beszel/site/src/components/add-system.tsx @@ -41,8 +41,7 @@ export function AddSystemButton({ className }: { className?: string }) { # - /mnt/disk1/.beszel:/extra-filesystems/disk1:ro environment: PORT: ${port} - KEY: "${publicKey}" - # FILESYSTEM: /dev/sda1 # override the root partition / device for disk I/O stats`) + KEY: "${publicKey}"`) } function copyInstallCommand(port: string) { @@ -73,7 +72,7 @@ export function AddSystemButton({ className }: { className?: string }) { variant="outline" className={cn("flex gap-1 max-xs:h-[2.4rem]", className, isReadOnlyUser() && "hidden")} > - + {t("add")} {t("system")} @@ -104,31 +103,31 @@ export function AddSystemButton({ className }: { className?: string }) {
-
-
-
-
{/* Docker */} - + @@ -161,7 +160,7 @@ export function AddSystemButton({ className }: { className?: string }) { {/* Binary */} - + diff --git a/beszel/site/src/components/alerts/alert-button.tsx b/beszel/site/src/components/alerts/alert-button.tsx index 660775a..e62bb50 100644 --- a/beszel/site/src/components/alerts/alert-button.tsx +++ b/beszel/site/src/components/alerts/alert-button.tsx @@ -78,11 +78,11 @@ function TheContent({ - + {system.name} - + {t("all_systems")} diff --git a/beszel/site/src/components/command-palette.tsx b/beszel/site/src/components/command-palette.tsx index a5efe2c..b360fad 100644 --- a/beszel/site/src/components/command-palette.tsx +++ b/beszel/site/src/components/command-palette.tsx @@ -59,7 +59,7 @@ export default function CommandPalette({ open, setOpen }: { open: boolean; setOp setOpen(false) }} > - + {system.name} {system.host} @@ -76,7 +76,7 @@ export default function CommandPalette({ open, setOpen }: { open: boolean; setOp setOpen(false) }} > - + {t("command.dashboard")} {t("command.page")} @@ -86,7 +86,7 @@ export default function CommandPalette({ open, setOpen }: { open: boolean; setOp setOpen(false) }} > - + {t("settings.settings")} {t("settings.settings")} @@ -97,7 +97,7 @@ export default function CommandPalette({ open, setOpen }: { open: boolean; setOp setOpen(false) }} > - + {t("settings.notifications.title")} {t("settings.settings")} @@ -107,7 +107,7 @@ export default function CommandPalette({ open, setOpen }: { open: boolean; setOp window.location.href = "https://github.com/henrygd/beszel/blob/main/readme.md" }} > - + {t("command.documentation")} GitHub @@ -123,7 +123,7 @@ export default function CommandPalette({ open, setOpen }: { open: boolean; setOp window.open("/_/", "_blank") }} > - + {t("user_dm.users")} {t("command.admin")} @@ -133,7 +133,7 @@ export default function CommandPalette({ open, setOpen }: { open: boolean; setOp window.open("/_/#/logs", "_blank") }} > - + {t("user_dm.logs")} {t("command.admin")} @@ -143,7 +143,7 @@ export default function CommandPalette({ open, setOpen }: { open: boolean; setOp window.open("/_/#/settings/backups", "_blank") }} > - + {t("user_dm.backups")} {t("command.admin")} @@ -154,7 +154,7 @@ export default function CommandPalette({ open, setOpen }: { open: boolean; setOp window.open("/_/#/settings/auth-providers", "_blank") }} > - + {t("user_dm.auth_providers")} {t("command.admin")} @@ -165,7 +165,7 @@ export default function CommandPalette({ open, setOpen }: { open: boolean; setOp window.open("/_/#/settings/mail", "_blank") }} > - + {t("command.SMTP_settings")} {t("command.admin")} diff --git a/beszel/site/src/components/logo.tsx b/beszel/site/src/components/logo.tsx index e85e657..07bf3df 100644 --- a/beszel/site/src/components/logo.tsx +++ b/beszel/site/src/components/logo.tsx @@ -2,7 +2,16 @@ export function Logo({ className }: { className?: string }) { return ( // Righteous - + {/* + + + + + */} + ) } diff --git a/beszel/site/src/components/navbar.tsx b/beszel/site/src/components/navbar.tsx index 47299d3..fa25d61 100644 --- a/beszel/site/src/components/navbar.tsx +++ b/beszel/site/src/components/navbar.tsx @@ -38,13 +38,12 @@ export default function Navbar() { const { t } = useTranslation() return (
- - + + - -
+
- +
) @@ -125,14 +124,14 @@ function SearchButton({ t }: { t: TFunction<"translation", undefined> }) { <>
@@ -122,7 +122,7 @@ export default function () { {hubVersion && ( -
+
{configContent && (