mirror of
https://github.com/henrygd/beszel.git
synced 2026-09-21 08:57:48 +02:00
feat: add ZFS monitoring (#2209)
- track pool capacity, health, I/O, scrub status, and vdev errors - report dataset usage and correct ZFS filesystem metrics - add pool charts, detail views, refresh controls, and health alerts - persist pool details and include ZFS usage in disk alerts - support configurable detail intervals and legacy agent compatibility --------- Co-authored-by: hank <hank@henrygd.me>
This commit is contained in:
@@ -33,8 +33,6 @@ type Stats struct {
|
||||
MaxNetworkSent float64 `json:"nsm,omitempty" cbor:"-"`
|
||||
MaxNetworkRecv float64 `json:"nrm,omitempty" cbor:"-"`
|
||||
Temperatures map[string]float64 `json:"t,omitempty" cbor:"20,keyasint,omitempty"`
|
||||
Fans map[string]uint16 `json:"f,omitempty" cbor:"36,keyasint,omitempty"`
|
||||
Batteries map[string]uint8 `json:"bats,omitempty" cbor:"37,keyasint,omitempty"`
|
||||
ExtraFs map[string]*FsStats `json:"efs,omitempty" cbor:"21,keyasint,omitempty"`
|
||||
GPUData map[string]GPUData `json:"g,omitempty" cbor:"22,keyasint,omitempty"`
|
||||
// LoadAvg1 float64 `json:"l1,omitempty" cbor:"23,keyasint,omitempty"`
|
||||
@@ -52,7 +50,20 @@ type Stats struct {
|
||||
CpuCoresUsage Uint8Slice `json:"cpus,omitempty" cbor:"34,keyasint,omitempty"` // per-core busy usage [CPU0..]
|
||||
DiskIoStats [6]float64 `json:"dios,omitzero" cbor:"35,keyasint,omitzero"` // [read time %, write time %, io utilization %, r_await ms, w_await ms, weighted io %]
|
||||
MaxDiskIoStats [6]float64 `json:"diosm,omitzero" cbor:"-"` // max values for DiskIoStats
|
||||
DiskIOTotal [2]uint64 `json:"diot,omitzero" cbor:"38,keyasint,omitzero"` // [total read bytes, total write bytes] cumulative device counters
|
||||
Fans map[string]uint16 `json:"f,omitempty" cbor:"36,keyasint,omitempty"`
|
||||
Batteries map[string]uint8 `json:"bats,omitempty" cbor:"37,keyasint,omitempty"`
|
||||
ZfsPools map[string]*ZfsPool `json:"z,omitempty" cbor:"39,keyasint,omitempty"` // ZFS pool metrics, keyed by pool name
|
||||
DiskIOTotal [2]uint64 `json:"diot,omitzero" cbor:"38,keyasint,omitzero"` // [total read bytes, total write bytes] cumulative device counters
|
||||
|
||||
}
|
||||
|
||||
// ZfsPool holds per-pool ZFS metrics for a single collection interval.
|
||||
type ZfsPool struct {
|
||||
Total float64 `json:"d" cbor:"0,keyasint"` // total capacity in GiB
|
||||
Used float64 `json:"du" cbor:"1,keyasint"` // allocated in GiB
|
||||
ReadBytes uint64 `json:"rb,omitzero" cbor:"2,keyasint,omitzero"` // read throughput in bytes/s
|
||||
WriteBytes uint64 `json:"wb,omitzero" cbor:"3,keyasint,omitzero"` // write throughput in bytes/s
|
||||
Health string `json:"h,omitempty" cbor:"4,keyasint,omitempty"` // ONLINE, DEGRADED, FAULTED, ...
|
||||
}
|
||||
|
||||
// Uint8Slice wraps []uint8 to customize JSON encoding while keeping CBOR efficient.
|
||||
@@ -183,6 +194,7 @@ type Details struct {
|
||||
Podman bool `cbor:"8,keyasint,omitempty"`
|
||||
MemoryTotal uint64 `cbor:"9,keyasint"`
|
||||
SmartInterval time.Duration `cbor:"10,keyasint,omitempty"`
|
||||
ZfsInterval time.Duration `cbor:"11,keyasint,omitempty"` // interval for ZFS detail refresh
|
||||
}
|
||||
|
||||
// Final data structure to return to the hub
|
||||
|
||||
45
internal/entities/zfs/zfs.go
Normal file
45
internal/entities/zfs/zfs.go
Normal file
@@ -0,0 +1,45 @@
|
||||
// Package zfs defines the ZFS detail data exchanged between agent and hub.
|
||||
package zfs
|
||||
|
||||
// ZfsData is the detail payload returned by the agent for the GetZfsData action.
|
||||
type ZfsData struct {
|
||||
Pools []*PoolDetail `json:"pools,omitempty"`
|
||||
Complete bool `json:"complete,omitempty"`
|
||||
}
|
||||
|
||||
// PoolDetail holds the verbose state of a single pool: capacity, health,
|
||||
// scrub, vdev, and dataset information.
|
||||
type PoolDetail struct {
|
||||
Name string `json:"name"`
|
||||
Health string `json:"health,omitempty"`
|
||||
Size uint64 `json:"size,omitempty"` // bytes
|
||||
Alloc uint64 `json:"alloc,omitempty"` // bytes
|
||||
Free uint64 `json:"free,omitempty"` // bytes
|
||||
Scrub *Scrub `json:"scrub,omitempty"`
|
||||
Vdevs []*Vdev `json:"vdevs,omitempty"`
|
||||
Datasets []*Dataset `json:"datasets,omitempty"`
|
||||
}
|
||||
|
||||
// Scrub holds the scrub (or resilver) status of a pool.
|
||||
type Scrub struct {
|
||||
State string `json:"state,omitempty"` // NONE, SCANNING, FINISHED, CANCELED
|
||||
Progress string `json:"progress,omitempty"`
|
||||
Errors uint64 `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
// Vdev is a single vdev (mirror, raidz, or leaf disk) with error counters.
|
||||
type Vdev struct {
|
||||
Name string `json:"name"`
|
||||
State string `json:"state,omitempty"`
|
||||
ReadErrs uint64 `json:"readErrs,omitempty"`
|
||||
WriteErrs uint64 `json:"writeErrs,omitempty"`
|
||||
ChecksumErrs uint64 `json:"checksumErrs,omitempty"`
|
||||
}
|
||||
|
||||
// Dataset is a single ZFS dataset with usage information.
|
||||
type Dataset struct {
|
||||
Name string `json:"name"`
|
||||
Used uint64 `json:"used,omitempty"`
|
||||
Avail uint64 `json:"avail,omitempty"`
|
||||
Mountpoint string `json:"mount,omitempty"`
|
||||
}
|
||||
Reference in New Issue
Block a user