mirror of
https://github.com/henrygd/beszel.git
synced 2025-12-17 02:36:17 +01:00
pre release refactoring + update changelog
This commit is contained in:
@@ -46,7 +46,7 @@ func (sm *SmartManager) Refresh() error {
|
|||||||
|
|
||||||
scanErr := sm.ScanDevices()
|
scanErr := sm.ScanDevices()
|
||||||
if scanErr != nil {
|
if scanErr != nil {
|
||||||
slog.Warn("smartctl scan failed", "err", scanErr)
|
slog.Debug("smartctl scan failed", "err", scanErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
devices := sm.devicesSnapshot()
|
devices := sm.devicesSnapshot()
|
||||||
@@ -56,7 +56,7 @@ func (sm *SmartManager) Refresh() error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := sm.CollectSmart(deviceInfo); err != nil {
|
if err := sm.CollectSmart(deviceInfo); err != nil {
|
||||||
slog.Info("smartctl collect failed for device, skipping", "device", deviceInfo.Name, "err", err)
|
slog.Debug("smartctl collect failed, skipping", "device", deviceInfo.Name, "err", err)
|
||||||
collectErr = err
|
collectErr = err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,7 +220,7 @@ func (sm *SmartManager) parseScan(output []byte) bool {
|
|||||||
scan := &scanOutput{}
|
scan := &scanOutput{}
|
||||||
|
|
||||||
if err := json.Unmarshal(output, scan); err != nil {
|
if err := json.Unmarshal(output, scan); err != nil {
|
||||||
slog.Warn("Failed to parse smartctl scan JSON", "err", err)
|
slog.Debug("Failed to parse smartctl scan JSON", "err", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ func (sm *SmartManager) parseSmartForSata(output []byte) (bool, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if data.SerialNumber == "" {
|
if data.SerialNumber == "" {
|
||||||
slog.Warn("device has no serial number, skipping", "device", data.Device.Name)
|
slog.Debug("device has no serial number, skipping", "device", data.Device.Name)
|
||||||
return false, data.Smartctl.ExitStatus
|
return false, data.Smartctl.ExitStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +327,7 @@ func (sm *SmartManager) parseSmartForNvme(output []byte) (bool, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if data.SerialNumber == "" {
|
if data.SerialNumber == "" {
|
||||||
slog.Warn("device has no serial number, skipping", "device", data.Device.Name)
|
slog.Debug("device has no serial number, skipping", "device", data.Device.Name)
|
||||||
return false, data.Smartctl.ExitStatus
|
return false, data.Smartctl.ExitStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,7 +386,7 @@ func (sm *SmartManager) detectSmartctl() error {
|
|||||||
if _, err := exec.LookPath("smartctl"); err == nil {
|
if _, err := exec.LookPath("smartctl"); err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("no smartctl found - install smartctl")
|
return fmt.Errorf("smartctl not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSmartManager creates and initializes a new SmartManager
|
// NewSmartManager creates and initializes a new SmartManager
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export default memo(function AlertsButton({ system }: { system: SystemRecord })
|
|||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="max-h-full overflow-auto w-145 !max-w-full p-4 sm:p-6">
|
<SheetContent className="max-h-full overflow-auto w-150 !max-w-full p-4 sm:p-6">
|
||||||
{opened && <AlertDialogContent system={system} />}
|
{opened && <AlertDialogContent system={system} />}
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
</Sheet>
|
</Sheet>
|
||||||
|
|||||||
@@ -1003,15 +1003,16 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{compareSemVer(chartData.agentVersion, parseSemVer("0.15.0")) >= 0 && (
|
||||||
|
<LazySmartTable systemId={system.id} />
|
||||||
|
)}
|
||||||
|
|
||||||
{containerData.length > 0 && compareSemVer(chartData.agentVersion, parseSemVer("0.14.0")) >= 0 && (
|
{containerData.length > 0 && compareSemVer(chartData.agentVersion, parseSemVer("0.14.0")) >= 0 && (
|
||||||
<LazyContainersTable systemId={id} />
|
<LazyContainersTable systemId={id} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<LazySmartTable systemId={system.id} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* add space for tooltip if more than 12 containers */}
|
{/* add space for tooltip if lots of sensors */}
|
||||||
{bottomSpacing > 0 && <span className="block" style={{ height: bottomSpacing }} />}
|
{bottomSpacing > 0 && <span className="block" style={{ height: bottomSpacing }} />}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
@@ -1144,7 +1145,7 @@ const ContainersTable = lazy(() => import("../containers-table/containers-table"
|
|||||||
function LazyContainersTable({ systemId }: { systemId: string }) {
|
function LazyContainersTable({ systemId }: { systemId: string }) {
|
||||||
const { isIntersecting, ref } = useIntersectionObserver({ rootMargin: "90px" })
|
const { isIntersecting, ref } = useIntersectionObserver({ rootMargin: "90px" })
|
||||||
return (
|
return (
|
||||||
<div ref={ref}>
|
<div ref={ref} className={cn(isIntersecting && "contents")}>
|
||||||
{isIntersecting && <ContainersTable systemId={systemId} />}
|
{isIntersecting && <ContainersTable systemId={systemId} />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -1153,9 +1154,9 @@ function LazyContainersTable({ systemId }: { systemId: string }) {
|
|||||||
const SmartTable = lazy(() => import("./system/smart-table"))
|
const SmartTable = lazy(() => import("./system/smart-table"))
|
||||||
|
|
||||||
function LazySmartTable({ systemId }: { systemId: string }) {
|
function LazySmartTable({ systemId }: { systemId: string }) {
|
||||||
const { isIntersecting, ref } = useIntersectionObserver()
|
const { isIntersecting, ref } = useIntersectionObserver({ rootMargin: "90px" })
|
||||||
return (
|
return (
|
||||||
<div ref={ref}>
|
<div ref={ref} className={cn(isIntersecting && "contents")}>
|
||||||
{isIntersecting && <SmartTable systemId={systemId} />}
|
{isIntersecting && <SmartTable systemId={systemId} />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ export const columns: ColumnDef<DiskInfo>[] = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
export default function DisksTable({ systemId }: { systemId: string }) {
|
export default function DisksTable({ systemId }: { systemId: string }) {
|
||||||
const [sorting, setSorting] = React.useState<SortingState>([{ id: "device", desc: false }])
|
// const [sorting, setSorting] = React.useState<SortingState>([{ id: "device", desc: false }])
|
||||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
|
||||||
const [rowSelection, setRowSelection] = React.useState({})
|
const [rowSelection, setRowSelection] = React.useState({})
|
||||||
const [smartData, setSmartData] = React.useState<Record<string, SmartData> | undefined>(undefined)
|
const [smartData, setSmartData] = React.useState<Record<string, SmartData> | undefined>(undefined)
|
||||||
@@ -284,19 +284,23 @@ export default function DisksTable({ systemId }: { systemId: string }) {
|
|||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data: diskData,
|
data: diskData,
|
||||||
columns: columns,
|
columns: columns,
|
||||||
onSortingChange: setSorting,
|
// onSortingChange: setSorting,
|
||||||
onColumnFiltersChange: setColumnFilters,
|
onColumnFiltersChange: setColumnFilters,
|
||||||
getCoreRowModel: getCoreRowModel(),
|
getCoreRowModel: getCoreRowModel(),
|
||||||
getSortedRowModel: getSortedRowModel(),
|
getSortedRowModel: getSortedRowModel(),
|
||||||
getFilteredRowModel: getFilteredRowModel(),
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
onRowSelectionChange: setRowSelection,
|
onRowSelectionChange: setRowSelection,
|
||||||
state: {
|
state: {
|
||||||
sorting,
|
// sorting,
|
||||||
columnFilters,
|
columnFilters,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!diskData.length && !columnFilters.length) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Card className="p-6 @container w-full">
|
<Card className="p-6 @container w-full">
|
||||||
|
|||||||
@@ -367,6 +367,12 @@ export function formatDuration(
|
|||||||
.join(" ")
|
.join(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Parse semver string into major, minor, and patch numbers
|
||||||
|
* @example
|
||||||
|
* const semVer = "1.2.3"
|
||||||
|
* const { major, minor, patch } = parseSemVer(semVer)
|
||||||
|
* console.log(major, minor, patch) // 1, 2, 3
|
||||||
|
*/
|
||||||
export const parseSemVer = (semVer = ""): SemVer => {
|
export const parseSemVer = (semVer = ""): SemVer => {
|
||||||
// if (semVer.startsWith("v")) {
|
// if (semVer.startsWith("v")) {
|
||||||
// semVer = semVer.slice(1)
|
// semVer = semVer.slice(1)
|
||||||
|
|||||||
@@ -1,3 +1,15 @@
|
|||||||
|
## 0.15.0
|
||||||
|
|
||||||
|
- Add initial S.M.A.R.T. support for disk health monitoring. (#962)
|
||||||
|
|
||||||
|
- Add `CONTAINER_DETAILS` environment variable to control access to container logs and info APIs. (#1305)
|
||||||
|
|
||||||
|
- Improve temperature chart by allowing y-axis to start above 0 for better readability. (#1307)
|
||||||
|
|
||||||
|
- Add `henrygd/beszel-agent:alpine` Docker image and include `smartmontools` in all non-base agent images.
|
||||||
|
|
||||||
|
- Improve battery detection logic. (#1287)
|
||||||
|
|
||||||
## 0.14.1
|
## 0.14.1
|
||||||
|
|
||||||
- Add `MFA_OTP` environment variable to enable email-based one-time password for users and/or superusers.
|
- Add `MFA_OTP` environment variable to enable email-based one-time password for users and/or superusers.
|
||||||
|
|||||||
Reference in New Issue
Block a user