pre release refactoring + update changelog

This commit is contained in:
henrygd
2025-10-25 16:34:32 -04:00
parent a9657f9c00
commit 74b78e96b3
6 changed files with 39 additions and 16 deletions

View File

@@ -46,7 +46,7 @@ func (sm *SmartManager) Refresh() error {
scanErr := sm.ScanDevices()
if scanErr != nil {
slog.Warn("smartctl scan failed", "err", scanErr)
slog.Debug("smartctl scan failed", "err", scanErr)
}
devices := sm.devicesSnapshot()
@@ -56,7 +56,7 @@ func (sm *SmartManager) Refresh() error {
continue
}
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
}
}
@@ -220,7 +220,7 @@ func (sm *SmartManager) parseScan(output []byte) bool {
scan := &scanOutput{}
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
}
@@ -260,7 +260,7 @@ func (sm *SmartManager) parseSmartForSata(output []byte) (bool, int) {
}
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
}
@@ -327,7 +327,7 @@ func (sm *SmartManager) parseSmartForNvme(output []byte) (bool, int) {
}
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
}
@@ -386,7 +386,7 @@ func (sm *SmartManager) detectSmartctl() error {
if _, err := exec.LookPath("smartctl"); err == nil {
return nil
}
return fmt.Errorf("no smartctl found - install smartctl")
return fmt.Errorf("smartctl not found")
}
// NewSmartManager creates and initializes a new SmartManager

View File

@@ -26,7 +26,7 @@ export default memo(function AlertsButton({ system }: { system: SystemRecord })
/>
</Button>
</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} />}
</SheetContent>
</Sheet>

View File

@@ -1003,15 +1003,16 @@ export default memo(function SystemDetail({ id }: { id: string }) {
</div>
)}
{compareSemVer(chartData.agentVersion, parseSemVer("0.15.0")) >= 0 && (
<LazySmartTable systemId={system.id} />
)}
{containerData.length > 0 && compareSemVer(chartData.agentVersion, parseSemVer("0.14.0")) >= 0 && (
<LazyContainersTable systemId={id} />
)}
<LazySmartTable systemId={system.id} />
</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 }} />}
</>
)
@@ -1144,7 +1145,7 @@ const ContainersTable = lazy(() => import("../containers-table/containers-table"
function LazyContainersTable({ systemId }: { systemId: string }) {
const { isIntersecting, ref } = useIntersectionObserver({ rootMargin: "90px" })
return (
<div ref={ref}>
<div ref={ref} className={cn(isIntersecting && "contents")}>
{isIntersecting && <ContainersTable systemId={systemId} />}
</div>
)
@@ -1153,9 +1154,9 @@ function LazyContainersTable({ systemId }: { systemId: string }) {
const SmartTable = lazy(() => import("./system/smart-table"))
function LazySmartTable({ systemId }: { systemId: string }) {
const { isIntersecting, ref } = useIntersectionObserver()
const { isIntersecting, ref } = useIntersectionObserver({ rootMargin: "90px" })
return (
<div ref={ref}>
<div ref={ref} className={cn(isIntersecting && "contents")}>
{isIntersecting && <SmartTable systemId={systemId} />}
</div>
)

View File

@@ -252,7 +252,7 @@ export const columns: ColumnDef<DiskInfo>[] = [
]
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 [rowSelection, setRowSelection] = React.useState({})
const [smartData, setSmartData] = React.useState<Record<string, SmartData> | undefined>(undefined)
@@ -284,19 +284,23 @@ export default function DisksTable({ systemId }: { systemId: string }) {
const table = useReactTable({
data: diskData,
columns: columns,
onSortingChange: setSorting,
// onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onRowSelectionChange: setRowSelection,
state: {
sorting,
// sorting,
columnFilters,
rowSelection,
},
})
if (!diskData.length && !columnFilters.length) {
return null
}
return (
<div>
<Card className="p-6 @container w-full">

View File

@@ -367,6 +367,12 @@ export function formatDuration(
.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 => {
// if (semVer.startsWith("v")) {
// semVer = semVer.slice(1)

View File

@@ -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
- Add `MFA_OTP` environment variable to enable email-based one-time password for users and/or superusers.