123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- package analytic
- import (
- "fmt"
- "github.com/dustin/go-humanize"
- "github.com/pkg/errors"
- "github.com/shirou/gopsutil/v4/disk"
- "github.com/spf13/cast"
- )
- func GetDiskStat() (DiskStat, error) {
- // Get all partitions
- partitions, err := disk.Partitions(false)
- if err != nil {
- return DiskStat{}, errors.Wrap(err, "error analytic getDiskStat - getting partitions")
- }
- var totalSize uint64
- var totalUsed uint64
- var partitionStats []PartitionStat
- // Track partitions to avoid double counting same partition with multiple mount points
- partitionUsage := make(map[string]*disk.UsageStat)
- // Get usage for each partition
- for _, partition := range partitions {
- usage, err := disk.Usage(partition.Mountpoint)
- if err != nil {
- // Skip partitions that can't be accessed
- continue
- }
- // Skip virtual filesystems and special filesystems
- if isVirtualFilesystem(partition.Fstype) {
- continue
- }
- // Create partition stat for display purposes
- partitionStat := PartitionStat{
- Mountpoint: partition.Mountpoint,
- Device: partition.Device,
- Fstype: partition.Fstype,
- Total: humanize.Bytes(usage.Total),
- Used: humanize.Bytes(usage.Used),
- Free: humanize.Bytes(usage.Free),
- Percentage: cast.ToFloat64(fmt.Sprintf("%.2f", usage.UsedPercent)),
- }
- partitionStats = append(partitionStats, partitionStat)
- // Only count each partition device once for total calculation
- // This handles cases where same partition is mounted multiple times (e.g., bind mounts, overlayfs)
- if _, exists := partitionUsage[partition.Device]; !exists {
- partitionUsage[partition.Device] = usage
- totalSize += usage.Total
- totalUsed += usage.Used
- }
- }
- // Calculate overall percentage
- var overallPercentage float64
- if totalSize > 0 {
- overallPercentage = cast.ToFloat64(fmt.Sprintf("%.2f", float64(totalUsed)/float64(totalSize)*100))
- }
- return DiskStat{
- Used: humanize.Bytes(totalUsed),
- Total: humanize.Bytes(totalSize),
- Percentage: overallPercentage,
- Writes: DiskWriteRecord[len(DiskWriteRecord)-1],
- Reads: DiskReadRecord[len(DiskReadRecord)-1],
- Partitions: partitionStats,
- }, nil
- }
- // isVirtualFilesystem checks if the filesystem type is virtual
- func isVirtualFilesystem(fstype string) bool {
- virtualFSTypes := map[string]bool{
- "proc": true,
- "sysfs": true,
- "devfs": true,
- "devpts": true,
- "tmpfs": true,
- "debugfs": true,
- "securityfs": true,
- "cgroup": true,
- "cgroup2": true,
- "pstore": true,
- "bpf": true,
- "tracefs": true,
- "hugetlbfs": true,
- "mqueue": true,
- "overlay": true,
- "autofs": true,
- "binfmt_misc": true,
- "configfs": true,
- "fusectl": true,
- "rpc_pipefs": true,
- "selinuxfs": true,
- "systemd-1": true,
- "none": true,
- }
- return virtualFSTypes[fstype]
- }
|