mirror of
https://github.com/henrygd/beszel.git
synced 2026-01-14 06:10:23 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0fc4a6daed | ||
|
|
af0c1d3af7 | ||
|
|
9ad3cd0ab9 | ||
|
|
00def272b0 | ||
|
|
383913505f | ||
|
|
ca8cb78c29 | ||
|
|
8821fb5dd0 | ||
|
|
3279a6ca53 | ||
|
|
6a1a98d73f |
@@ -76,6 +76,18 @@ builds:
|
||||
- goos: windows
|
||||
goarch: riscv64
|
||||
|
||||
- id: beszel-agent-linux-amd64-glibc
|
||||
binary: beszel-agent
|
||||
main: internal/cmd/agent/agent.go
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
flags:
|
||||
- -tags=glibc
|
||||
goos:
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
|
||||
archives:
|
||||
- id: beszel-agent
|
||||
formats: [tar.gz]
|
||||
@@ -89,6 +101,15 @@ archives:
|
||||
- goos: windows
|
||||
formats: [zip]
|
||||
|
||||
- id: beszel-agent-linux-amd64-glibc
|
||||
formats: [tar.gz]
|
||||
ids:
|
||||
- beszel-agent-linux-amd64-glibc
|
||||
name_template: >-
|
||||
{{ .Binary }}_
|
||||
{{- .Os }}_
|
||||
{{- .Arch }}_glibc
|
||||
|
||||
- id: beszel
|
||||
formats: [tar.gz]
|
||||
ids:
|
||||
|
||||
22
agent/gpu.go
22
agent/gpu.go
@@ -5,6 +5,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"maps"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
@@ -14,8 +15,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/henrygd/beszel/internal/entities/system"
|
||||
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -137,10 +136,10 @@ func (gm *GPUManager) getJetsonParser() func(output []byte) bool {
|
||||
// use closure to avoid recompiling the regex
|
||||
ramPattern := regexp.MustCompile(`RAM (\d+)/(\d+)MB`)
|
||||
gr3dPattern := regexp.MustCompile(`GR3D_FREQ (\d+)%`)
|
||||
tempPattern := regexp.MustCompile(`tj@(\d+\.?\d*)C`)
|
||||
tempPattern := regexp.MustCompile(`(?:tj|GPU)@(\d+\.?\d*)C`)
|
||||
// Orin Nano / NX do not have GPU specific power monitor
|
||||
// TODO: Maybe use VDD_IN for Nano / NX and add a total system power chart
|
||||
powerPattern := regexp.MustCompile(`(GPU_SOC|CPU_GPU_CV) (\d+)mW`)
|
||||
powerPattern := regexp.MustCompile(`(GPU_SOC|CPU_GPU_CV)\s+(\d+)mW|VDD_SYS_GPU\s+(\d+)/\d+`)
|
||||
|
||||
// jetson devices have only one gpu so we'll just initialize here
|
||||
gpuData := &system.GPUData{Name: "GPU"}
|
||||
@@ -169,7 +168,13 @@ func (gm *GPUManager) getJetsonParser() func(output []byte) bool {
|
||||
// Parse power usage
|
||||
powerMatches := powerPattern.FindSubmatch(output)
|
||||
if powerMatches != nil {
|
||||
power, _ := strconv.ParseFloat(string(powerMatches[2]), 64)
|
||||
// powerMatches[2] is the "(GPU_SOC|CPU_GPU_CV) <N>mW" capture
|
||||
// powerMatches[3] is the "VDD_SYS_GPU <N>/<N>" capture
|
||||
powerStr := string(powerMatches[2])
|
||||
if powerStr == "" {
|
||||
powerStr = string(powerMatches[3])
|
||||
}
|
||||
power, _ := strconv.ParseFloat(powerStr, 64)
|
||||
gpuData.Power += power / milliwattsInAWatt
|
||||
}
|
||||
gpuData.Count++
|
||||
@@ -232,10 +237,11 @@ func (gm *GPUManager) parseAmdData(output []byte) bool {
|
||||
totalMemory, _ := strconv.ParseFloat(v.MemoryTotal, 64)
|
||||
usage, _ := strconv.ParseFloat(v.Usage, 64)
|
||||
|
||||
if _, ok := gm.GpuDataMap[v.ID]; !ok {
|
||||
gm.GpuDataMap[v.ID] = &system.GPUData{Name: v.Name}
|
||||
id := v.ID
|
||||
if _, ok := gm.GpuDataMap[id]; !ok {
|
||||
gm.GpuDataMap[id] = &system.GPUData{Name: v.Name}
|
||||
}
|
||||
gpu := gm.GpuDataMap[v.ID]
|
||||
gpu := gm.GpuDataMap[id]
|
||||
gpu.Temperature, _ = strconv.ParseFloat(v.Temperature, 64)
|
||||
gpu.MemoryUsed = bytesToMegabytes(memoryUsage)
|
||||
gpu.MemoryTotal = bytesToMegabytes(totalMemory)
|
||||
|
||||
@@ -27,10 +27,11 @@ func (gm *GPUManager) updateIntelFromStats(sample *intelGpuStats) bool {
|
||||
defer gm.Unlock()
|
||||
|
||||
// only one gpu for now - cmd doesn't provide all by default
|
||||
gpuData, ok := gm.GpuDataMap["0"]
|
||||
id := "i0" // prefix with i to avoid conflicts with nvidia card ids
|
||||
gpuData, ok := gm.GpuDataMap[id]
|
||||
if !ok {
|
||||
gpuData = &system.GPUData{Name: "GPU", Engines: make(map[string]float64)}
|
||||
gm.GpuDataMap["0"] = gpuData
|
||||
gm.GpuDataMap[id] = gpuData
|
||||
}
|
||||
|
||||
gpuData.Power += sample.PowerGPU
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build (linux || windows) && (amd64 || arm64)
|
||||
//go:build amd64 && (windows || (linux && glibc))
|
||||
|
||||
package agent
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build linux && (amd64 || arm64)
|
||||
//go:build glibc && linux && amd64
|
||||
|
||||
package agent
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build (!linux && !windows) || (!amd64 && !arm64)
|
||||
//go:build (!linux && !windows) || !amd64 || (linux && !glibc)
|
||||
|
||||
package agent
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build windows && (amd64 || arm64)
|
||||
//go:build windows && amd64
|
||||
|
||||
package agent
|
||||
|
||||
|
||||
@@ -307,6 +307,19 @@ func TestParseJetsonData(t *testing.T) {
|
||||
Count: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "orin-style output with GPU@ temp and VDD_SYS_GPU power",
|
||||
input: "RAM 3276/7859MB (lfb 5x4MB) SWAP 1626/12122MB (cached 181MB) CPU [44%@1421,49%@2031,67%@2034,17%@1420,25%@1419,8%@1420] EMC_FREQ 1%@1866 GR3D_FREQ 0%@114 APE 150 MTS fg 1% bg 1% PLL@42.5C MCPU@42.5C PMIC@50C Tboard@38C GPU@39.5C BCPU@42.5C thermal@41.3C Tdiode@39.25C VDD_SYS_GPU 182/182 VDD_SYS_SOC 730/730 VDD_4V0_WIFI 0/0 VDD_IN 5297/5297 VDD_SYS_CPU 1917/1917 VDD_SYS_DDR 1241/1241",
|
||||
wantMetrics: &system.GPUData{
|
||||
Name: "GPU",
|
||||
MemoryUsed: 3276.0,
|
||||
MemoryTotal: 7859.0,
|
||||
Usage: 0.0,
|
||||
Power: 0.182, // 182mW -> 0.182W
|
||||
Temperature: 39.5,
|
||||
Count: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -1372,7 +1385,7 @@ func TestIntelUpdateFromStats(t *testing.T) {
|
||||
ok := gm.updateIntelFromStats(&sample1)
|
||||
assert.True(t, ok)
|
||||
|
||||
gpu := gm.GpuDataMap["0"]
|
||||
gpu := gm.GpuDataMap["i0"]
|
||||
require.NotNil(t, gpu)
|
||||
assert.Equal(t, "GPU", gpu.Name)
|
||||
assert.EqualValues(t, 10.5, gpu.Power)
|
||||
@@ -1394,7 +1407,7 @@ func TestIntelUpdateFromStats(t *testing.T) {
|
||||
ok = gm.updateIntelFromStats(&sample2)
|
||||
assert.True(t, ok)
|
||||
|
||||
gpu = gm.GpuDataMap["0"]
|
||||
gpu = gm.GpuDataMap["i0"]
|
||||
require.NotNil(t, gpu)
|
||||
assert.EqualValues(t, 10.5, gpu.Power)
|
||||
assert.EqualValues(t, 30.0, gpu.Engines["Render/3D"]) // 20 + 10
|
||||
@@ -1433,7 +1446,7 @@ echo "298 295 278 51 2.20 3.12 1675 942 5.75 1 2 9.50
|
||||
t.Fatalf("collectIntelStats error: %v", err)
|
||||
}
|
||||
|
||||
gpu := gm.GpuDataMap["0"]
|
||||
gpu := gm.GpuDataMap["i0"]
|
||||
require.NotNil(t, gpu)
|
||||
// Power should be sum of samples 2-4 (first is skipped): 2.0 + 1.8 + 2.2 = 6.0
|
||||
assert.EqualValues(t, 6.0, gpu.Power)
|
||||
|
||||
@@ -19,11 +19,11 @@ func TestSystemdManagerGetServiceStats(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test with refresh = true
|
||||
result := manager.getServiceStats(true)
|
||||
result := manager.getServiceStats("any-service", true)
|
||||
assert.Nil(t, result)
|
||||
|
||||
// Test with refresh = false
|
||||
result = manager.getServiceStats(false)
|
||||
result = manager.getServiceStats("any-service", false)
|
||||
assert.Nil(t, result)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import "github.com/blang/semver"
|
||||
|
||||
const (
|
||||
// Version is the current version of the application.
|
||||
Version = "0.18.1"
|
||||
Version = "0.18.2"
|
||||
// AppName is the name of the application.
|
||||
AppName = "beszel"
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM --platform=$BUILDPLATFORM golang:alpine AS builder
|
||||
FROM --platform=$BUILDPLATFORM golang:bookworm AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -10,7 +10,7 @@ COPY . ./
|
||||
|
||||
# Build
|
||||
ARG TARGETOS TARGETARCH
|
||||
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./internal/cmd/agent
|
||||
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -tags glibc -ldflags "-w -s" -o /agent ./internal/cmd/agent
|
||||
|
||||
# --------------------------
|
||||
# Smartmontools builder stage
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
@@ -345,5 +346,32 @@ func archiveSuffix(binaryName, goos, goarch string) string {
|
||||
if goos == "windows" {
|
||||
return fmt.Sprintf("%s_%s_%s.zip", binaryName, goos, goarch)
|
||||
}
|
||||
// Use glibc build for agent on glibc systems (includes NVML support via purego)
|
||||
if binaryName == "beszel-agent" && goos == "linux" && goarch == "amd64" && isGlibc() {
|
||||
return fmt.Sprintf("%s_%s_%s_glibc.tar.gz", binaryName, goos, goarch)
|
||||
}
|
||||
return fmt.Sprintf("%s_%s_%s.tar.gz", binaryName, goos, goarch)
|
||||
}
|
||||
|
||||
func isGlibc() bool {
|
||||
for _, path := range []string{
|
||||
"/lib64/ld-linux-x86-64.so.2", // common on many distros
|
||||
"/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2", // Debian/Ubuntu
|
||||
"/lib/ld-linux-x86-64.so.2", // alternate
|
||||
} {
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
// Fallback to ldd output when present (musl ldd reports musl, glibc reports GNU libc/glibc).
|
||||
if lddPath, err := exec.LookPath("ldd"); err == nil {
|
||||
out, err := exec.Command(lddPath, "--version").CombinedOutput()
|
||||
if err == nil {
|
||||
s := strings.ToLower(string(out))
|
||||
if strings.Contains(s, "gnu libc") || strings.Contains(s, "glibc") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
4
internal/site/package-lock.json
generated
4
internal/site/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "beszel",
|
||||
"version": "0.18.1",
|
||||
"version": "0.18.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "beszel",
|
||||
"version": "0.18.1",
|
||||
"version": "0.18.2",
|
||||
"dependencies": {
|
||||
"@henrygd/queue": "^1.0.7",
|
||||
"@henrygd/semaphore": "^0.0.2",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "beszel",
|
||||
"private": true,
|
||||
"version": "0.18.1",
|
||||
"version": "0.18.2",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
|
||||
@@ -407,23 +407,20 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
let hasGpuPowerData = false
|
||||
|
||||
if (lastGpus) {
|
||||
// check if there are any GPUs with engines
|
||||
for (const id in lastGpus) {
|
||||
hasGpuData = true
|
||||
if (lastGpus[id].e !== undefined) {
|
||||
hasGpuEnginesData = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// check if there are any GPUs with power data
|
||||
for (let i = 0; i < systemStats.length && !hasGpuPowerData; i++) {
|
||||
// check if there are any GPUs at all
|
||||
hasGpuData = Object.keys(lastGpus).length > 0
|
||||
// check if there are any GPUs with engines or power data
|
||||
for (let i = 0; i < systemStats.length && (!hasGpuEnginesData || !hasGpuPowerData); i++) {
|
||||
const gpus = systemStats[i].stats?.g
|
||||
if (!gpus) continue
|
||||
for (const id in gpus) {
|
||||
if (gpus[id].p !== undefined || gpus[id].pp !== undefined) {
|
||||
hasGpuPowerData = true
|
||||
break
|
||||
if (!hasGpuEnginesData && gpus[id].e !== undefined) {
|
||||
hasGpuEnginesData = true
|
||||
}
|
||||
if (!hasGpuPowerData && (gpus[id].p !== undefined || gpus[id].pp !== undefined)) {
|
||||
hasGpuPowerData = true
|
||||
}
|
||||
if (hasGpuEnginesData && hasGpuPowerData) break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -891,16 +888,30 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
})
|
||||
|
||||
function GpuEnginesChart({ chartData }: { chartData: ChartData }) {
|
||||
const dataPoints: DataPoint[] = []
|
||||
const engines = Object.keys(chartData.systemStats?.at(-1)?.stats.g?.[0]?.e ?? {}).sort()
|
||||
for (const engine of engines) {
|
||||
dataPoints.push({
|
||||
label: engine,
|
||||
dataKey: ({ stats }: SystemStatsRecord) => stats?.g?.[0]?.e?.[engine] ?? 0,
|
||||
color: `hsl(${140 + (((engines.indexOf(engine) * 360) / engines.length) % 360)}, 65%, 52%)`,
|
||||
opacity: 0.35,
|
||||
})
|
||||
const { gpuId, engines } = useMemo(() => {
|
||||
for (let i = chartData.systemStats.length - 1; i >= 0; i--) {
|
||||
const gpus = chartData.systemStats[i].stats?.g
|
||||
if (!gpus) continue
|
||||
for (const id in gpus) {
|
||||
if (gpus[id].e) {
|
||||
return { gpuId: id, engines: Object.keys(gpus[id].e).sort() }
|
||||
}
|
||||
}
|
||||
}
|
||||
return { gpuId: null, engines: [] }
|
||||
}, [chartData.systemStats])
|
||||
|
||||
if (!gpuId) {
|
||||
return null
|
||||
}
|
||||
|
||||
const dataPoints: DataPoint[] = engines.map((engine, i) => ({
|
||||
label: engine,
|
||||
dataKey: ({ stats }: SystemStatsRecord) => stats?.g?.[gpuId]?.e?.[engine] ?? 0,
|
||||
color: `hsl(${140 + (((i * 360) / engines.length) % 360)}, 65%, 52%)`,
|
||||
opacity: 0.35,
|
||||
}))
|
||||
|
||||
return (
|
||||
<LineChartDefault
|
||||
legend={true}
|
||||
|
||||
@@ -22,7 +22,7 @@ msgstr ""
|
||||
#. placeholder {1}: table.getFilteredRowModel().rows.length
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "{0} of {1} row(s) selected."
|
||||
msgstr "{0} dari {1} baris dipilih."
|
||||
msgstr "{0} dari {1} baris terpilih."
|
||||
|
||||
#: src/components/routes/system/info-bar.tsx
|
||||
msgid "{cores, plural, one {# core} other {# cores}}"
|
||||
@@ -125,11 +125,11 @@ msgstr "Tambah URL"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Adjust display options for charts."
|
||||
msgstr "Sesuaikan pengaturan tampilan untuk untuk grafik."
|
||||
msgstr "Sesuaikan tampilan grafik."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Adjust the width of the main layout"
|
||||
msgstr "Sesuaikan lebar layout utama"
|
||||
msgstr "Sesuaikan lebar layar utama"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
@@ -180,7 +180,7 @@ msgstr "Apakah anda yakin?"
|
||||
|
||||
#: src/components/copy-to-clipboard.tsx
|
||||
msgid "Automatic copy requires a secure context."
|
||||
msgstr "Menyalin otomatis memerlukan konteks yang aman."
|
||||
msgstr "Copy memerlukan https."
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Average"
|
||||
@@ -215,7 +215,7 @@ msgstr "Rata-rata utilisasi {0}"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Average utilization of GPU engines"
|
||||
msgstr "Rata-rata utilisasi mesin GPU"
|
||||
msgstr "Rata-rata utilisasi GPU"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
@@ -225,12 +225,12 @@ msgstr "Cadangan"
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Bandwidth"
|
||||
msgstr "Pita lebar"
|
||||
msgstr "Bandwith"
|
||||
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr "Baterai"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -258,7 +258,7 @@ msgstr "Di bawah {0}{1} dalam {2, plural, one {# menit} other {# menit}} terakhi
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
|
||||
msgstr "Beszel mendukung OpenID Connecnt dan banyak penyedia autentikasi OAuth2."
|
||||
msgstr "Beszel mendukung OpenID Connect dan OAuth2 dari berbagai penyedia layanan."
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Beszel uses <0>Shoutrrr</0> to integrate with popular notification services."
|
||||
@@ -330,7 +330,7 @@ msgstr "Ubah pengaturan umum aplikasi."
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Charge"
|
||||
msgstr "Isi"
|
||||
msgstr "Isi baterai"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
@@ -339,19 +339,19 @@ msgstr "Sedang mengisi"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Chart options"
|
||||
msgstr "Pengaturan grafik"
|
||||
msgstr "Pilihan grafik"
|
||||
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
msgid "Check {email} for a reset link."
|
||||
msgstr "Periksa {email} untuk tautan atur ulang."
|
||||
msgstr "Periksa {email} untuk tautan atur ulang password."
|
||||
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Check logs for more details."
|
||||
msgstr "Periksa catatan untuk lebih detail."
|
||||
msgstr "Periksa riwayat untuk lebih detail."
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Check your notification service"
|
||||
msgstr "Periksa penyedia jasa notifikasi anda"
|
||||
msgstr "Periksa jasa penyedia notifikasi anda"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
@@ -500,11 +500,11 @@ msgstr "Kritis (%)"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Cumulative Download"
|
||||
msgstr "Download Kumulatif"
|
||||
msgstr "Akumulasi Download"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Cumulative Upload"
|
||||
msgstr "Upload Kumulatif"
|
||||
msgstr "Akumulasi Upload"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/components/routes/system.tsx
|
||||
@@ -523,7 +523,7 @@ msgstr "Harian"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Default time period"
|
||||
msgstr "Periode waktu default"
|
||||
msgstr "Standar waktu"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
@@ -534,7 +534,7 @@ msgstr "Hapus"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Hapus sidik jari"
|
||||
msgstr "Hapus fingerprint"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Description"
|
||||
@@ -551,7 +551,7 @@ msgstr "Perangkat"
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
msgstr "Sedang mengosongkan"
|
||||
msgstr "Sedang tidak di charge"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Disk"
|
||||
@@ -615,12 +615,12 @@ msgstr "Durasi"
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Edit"
|
||||
msgstr "Edit"
|
||||
msgstr "Ubah"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Edit {foo}"
|
||||
msgstr "Edit {foo}"
|
||||
msgstr "Ubah {foo}"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
@@ -652,7 +652,7 @@ msgstr "Masukkan alamat email..."
|
||||
|
||||
#: src/components/login/otp-forms.tsx
|
||||
msgid "Enter your one-time password."
|
||||
msgstr "Masukkan kata sandi satu kali anda."
|
||||
msgstr "Masukkan otp anda."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Ephemeral"
|
||||
@@ -694,15 +694,15 @@ msgstr "Kedaluwarsa setelah satu jam atau saat restart hub."
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Export"
|
||||
msgstr "Ekspor"
|
||||
msgstr "Export"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "Export configuration"
|
||||
msgstr "Ekspor konfigurasi"
|
||||
msgstr "Export konfigurasi"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "Export your current systems configuration."
|
||||
msgstr "Ekspor konfigurasi sistem anda saat ini."
|
||||
msgstr "Export konfigurasi sistem anda saat ini."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Fahrenheit (°F)"
|
||||
@@ -728,7 +728,7 @@ msgstr "Gagal menyimpan pengaturan"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Failed to send test notification"
|
||||
msgstr "Gagal mengirim notifikasi tes"
|
||||
msgstr "Gagal mengirim tes notifikasi"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "Failed to update alert"
|
||||
@@ -750,7 +750,7 @@ msgstr "Filter..."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Fingerprint"
|
||||
msgstr "Sidik jari"
|
||||
msgstr "Fingerprint"
|
||||
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
msgid "Firmware"
|
||||
@@ -787,7 +787,7 @@ msgstr "Global"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "GPU Engines"
|
||||
msgstr "Mesin GPU"
|
||||
msgstr "GPU"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "GPU Power Draw"
|
||||
@@ -799,7 +799,7 @@ msgstr "Penggunaan GPU"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Grid"
|
||||
msgstr "Grid"
|
||||
msgstr "Kartu"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
@@ -843,11 +843,11 @@ msgstr "Bahasa"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Layout"
|
||||
msgstr "Layout"
|
||||
msgstr "Tampilan"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Layout width"
|
||||
msgstr "Lebar layout"
|
||||
msgstr "Lebar tampilan"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Lifecycle"
|
||||
@@ -877,11 +877,11 @@ msgstr "Rata-rata Beban 5m"
|
||||
#. Short label for load average
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Load Avg"
|
||||
msgstr "Rata Beban"
|
||||
msgstr "Rata-rata Beban"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Load state"
|
||||
msgstr "Status beban"
|
||||
msgstr "Beban saat ini"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Loading..."
|
||||
@@ -889,7 +889,7 @@ msgstr "Memuat..."
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Log Out"
|
||||
msgstr "Keluar"
|
||||
msgstr "Log Out"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Login"
|
||||
@@ -969,7 +969,7 @@ msgstr "Nama"
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Net"
|
||||
msgstr "Jaringan"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Network traffic of docker containers"
|
||||
@@ -1014,7 +1014,7 @@ msgstr "Tidak ada atribut S.M.A.R.T. yang tersedia untuk perangkat ini."
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "No systems found."
|
||||
msgstr "Tidak ada sistem ditemukan."
|
||||
msgstr "Sistem tidak ditemukan."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
@@ -1033,11 +1033,11 @@ msgstr "Pada setiap restart, sistem dalam database akan diperbarui untuk mencoco
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "One-time"
|
||||
msgstr "Sekali"
|
||||
msgstr "Sekali pakai"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "One-time password"
|
||||
msgstr "Kata sandi sekali pakai"
|
||||
msgstr "Kata sandi sekali pakai (OTP)"
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
@@ -1123,7 +1123,7 @@ msgstr "Permanen"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Persistence"
|
||||
msgstr "Ketekunan"
|
||||
msgstr "Tetap berlaku"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
|
||||
@@ -1174,7 +1174,7 @@ msgstr "Utilisasi tepat pada waktu yang direkam"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Preferred Language"
|
||||
msgstr "Bahasa Pilihan"
|
||||
msgstr "Pilihan Bahasa"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Process started"
|
||||
@@ -1203,7 +1203,7 @@ msgstr "Diterima"
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Refresh"
|
||||
msgstr "Muat ulang"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Relationships"
|
||||
@@ -1250,7 +1250,7 @@ msgstr "Root"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Rotate token"
|
||||
msgstr "Putar token"
|
||||
msgstr "Ganti ulang token"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Rows per page"
|
||||
@@ -1291,7 +1291,7 @@ msgstr "Jadwal"
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Schedule quiet hours where notifications will not be sent, such as during maintenance periods."
|
||||
msgstr "Jadwalkan jam tenang dimana notifikasi tidak akan dikirim, seperti selama periode pemeliharaan."
|
||||
msgstr "Jadwalkan jam tenang dimana notifikasi tidak akan dikirim, seperti saat periode pemeliharaan."
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Schedule quiet hours where notifications will not be sent."
|
||||
@@ -1430,7 +1430,7 @@ msgstr "Tugas"
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Temp"
|
||||
msgstr "Temp"
|
||||
msgstr "Temperatur"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1459,7 +1459,7 @@ msgstr "Kemudian masuk ke backend dan reset kata sandi akun pengguna anda di tab
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "This action cannot be undone. This will permanently delete all current records for {name} from the database."
|
||||
msgstr ""
|
||||
msgstr "Aksi ini tidak dapat di kembalikan. ini akan menghapus permanen semua record {name} dari database"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "This will permanently delete all selected records from the database."
|
||||
@@ -1484,11 +1484,11 @@ msgstr "Ke email"
|
||||
#: src/components/routes/system/info-bar.tsx
|
||||
#: src/components/routes/system/info-bar.tsx
|
||||
msgid "Toggle grid"
|
||||
msgstr "Toggle grid"
|
||||
msgstr "Ganti tampilan"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Toggle tema"
|
||||
msgstr "Ganti tema"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
@@ -1499,15 +1499,15 @@ msgstr "Token"
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens & Fingerprints"
|
||||
msgstr "Token & Sidik Jari"
|
||||
msgstr "Token & Fingerprint"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens allow agents to connect and register. Fingerprints are stable identifiers unique to each system, set on first connection."
|
||||
msgstr "Token memungkinkan agen untuk terhubung dan mendaftar. Sidik jari adalah pengidentifikasi stabil unik untuk setiap sistem, ditetapkan pada koneksi pertama."
|
||||
msgstr "Token memungkinkan agen untuk terhubung dan mendaftar. Fingerprint adalah sistem indentifikasi yang stabil dan unik untuk setiap sistem, diatur pada koneksi pertama."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
|
||||
msgstr "Token dan sidik jari digunakan untuk mengautentikasi koneksi WebSocket ke hub."
|
||||
msgstr "Token dan Fingerprint digunakan untuk mengautentikasi koneksi WebSocket ke hub."
|
||||
|
||||
#: src/components/ui/chart.tsx
|
||||
#: src/components/ui/chart.tsx
|
||||
@@ -1553,11 +1553,11 @@ msgstr "Dipicu ketika sensor apa pun melebihi ambang batas"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when battery charge drops below a threshold"
|
||||
msgstr "Dipicu ketika muatan baterai turun di bawah ambang batas"
|
||||
msgstr "Dipicu ketika baterai turun di bawah ambang batas"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when combined up/down exceeds a threshold"
|
||||
msgstr "Dipicu ketika kombinasi up/down melebihi ambang batas"
|
||||
msgstr "Dipicu ketika up atau down melebihi ambang batas"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when CPU usage exceeds a threshold"
|
||||
@@ -1592,7 +1592,7 @@ msgstr "File unit"
|
||||
#. Temperature / network units
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Unit preferences"
|
||||
msgstr "Preferensi unit"
|
||||
msgstr "Pengaturan satuan"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
@@ -1613,11 +1613,11 @@ msgstr "Tidak terbatas"
|
||||
#: src/components/routes/system/info-bar.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Up"
|
||||
msgstr "Up"
|
||||
msgstr "Nyala"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Up ({upSystemsLength})"
|
||||
msgstr "Nyala selama ({upSystemsLength})"
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Update"
|
||||
@@ -1682,7 +1682,7 @@ msgstr "Lihat 200 peringatan terbaru anda."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Visible Fields"
|
||||
msgstr "Field yang Terlihat"
|
||||
msgstr "Metrik yang Terlihat"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Waiting for enough records to display"
|
||||
@@ -1706,11 +1706,11 @@ msgstr "Ambang peringatan"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Webhook / Push notifications"
|
||||
msgstr "Notifikasi Webhook / Push"
|
||||
msgstr "Webhook / Push notifikasi"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "When enabled, this token allows agents to self-register without prior system creation."
|
||||
msgstr "Ketika diaktifkan, token ini memungkinkan agen untuk mendaftar sendiri tanpa pembuatan sistem sebelumnya."
|
||||
msgstr "Ketika diaktifkan, token ini memungkinkan agen untuk mendaftar sendiri tanpa pembuatan sistem."
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
## 0.18.2
|
||||
|
||||
- Add separate dynamically linked glibc build for Linux. (#1618)
|
||||
|
||||
- Fix GPU ID collision between Intel and NVIDIA collectors. (#1522)
|
||||
|
||||
- Only hide GPU engine graph if entire usage is 0%. (#1624)
|
||||
|
||||
- Add Jetson tegrastats regex support for pre-Jetpack 5 versions. (#1631)
|
||||
|
||||
- Improve Indonesian translations. (#1625)
|
||||
|
||||
## 0.18.1
|
||||
|
||||
- Fix bug in 0.18.0 where all containers were cleared from the "All Containers" page when any system returned no containers.
|
||||
|
||||
## 0.18.0
|
||||
|
||||
- Add experimental NVML GPU collector. (#1522, #1587)
|
||||
|
||||
@@ -12,6 +12,24 @@ is_freebsd() {
|
||||
[ "$(uname -s)" = "FreeBSD" ]
|
||||
}
|
||||
|
||||
is_glibc() {
|
||||
# Prefer glibc-enabled agent (NVML via purego) on linux/amd64 glibc systems.
|
||||
# Check common dynamic loader paths first (fast + reliable).
|
||||
for p in \
|
||||
/lib64/ld-linux-x86-64.so.2 \
|
||||
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 \
|
||||
/lib/ld-linux-x86-64.so.2; do
|
||||
[ -e "$p" ] && return 0
|
||||
done
|
||||
|
||||
# Fallback to ldd output if available.
|
||||
if command -v ldd >/dev/null 2>&1; then
|
||||
ldd --version 2>&1 | grep -qiE 'gnu libc|glibc' && return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
# If SELinux is enabled, set the context of the binary
|
||||
set_selinux_context() {
|
||||
@@ -598,6 +616,9 @@ echo "Downloading and installing the agent..."
|
||||
OS=$(uname -s | sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/')
|
||||
ARCH=$(detect_architecture)
|
||||
FILE_NAME="beszel-agent_${OS}_${ARCH}.tar.gz"
|
||||
if [ "$OS" = "linux" ] && [ "$ARCH" = "amd64" ] && is_glibc; then
|
||||
FILE_NAME="beszel-agent_${OS}_${ARCH}_glibc.tar.gz"
|
||||
fi
|
||||
|
||||
# Determine version to install
|
||||
if [ "$VERSION" = "latest" ]; then
|
||||
|
||||
Reference in New Issue
Block a user