Browse Source

fix(analytic): disk analytic issue #1062

Jacky 1 month ago
parent
commit
80e09a6131
3 changed files with 154 additions and 12 deletions
  1. 11 0
      app/src/api/analytic.ts
  2. 94 12
      internal/analytic/stat.go
  3. 49 0
      internal/analytic/stat_test.go

+ 11 - 0
app/src/api/analytic.ts

@@ -59,12 +59,23 @@ export interface MemStat {
   pressure: number
 }
 
+export interface PartitionStat {
+  mountpoint: string
+  device: string
+  fstype: string
+  total: string
+  used: string
+  free: string
+  percentage: number
+}
+
 export interface DiskStat {
   total: string
   used: string
   percentage: number
   writes: Usage
   reads: Usage
+  partitions: PartitionStat[]
 }
 
 export interface LoadStat {

+ 94 - 12
internal/analytic/stat.go

@@ -2,12 +2,13 @@ package analytic
 
 import (
 	"fmt"
+	"math"
+
 	"github.com/dustin/go-humanize"
 	"github.com/pkg/errors"
 	"github.com/shirou/gopsutil/v4/disk"
 	"github.com/shirou/gopsutil/v4/mem"
 	"github.com/spf13/cast"
-	"math"
 )
 
 type MemStat struct {
@@ -22,12 +23,23 @@ type MemStat struct {
 	Pressure    float64 `json:"pressure"`
 }
 
+type PartitionStat struct {
+	Mountpoint string  `json:"mountpoint"`
+	Device     string  `json:"device"`
+	Fstype     string  `json:"fstype"`
+	Total      string  `json:"total"`
+	Used       string  `json:"used"`
+	Free       string  `json:"free"`
+	Percentage float64 `json:"percentage"`
+}
+
 type DiskStat struct {
-	Total      string        `json:"total"`
-	Used       string        `json:"used"`
-	Percentage float64       `json:"percentage"`
-	Writes     Usage[uint64] `json:"writes"`
-	Reads      Usage[uint64] `json:"reads"`
+	Total      string          `json:"total"`
+	Used       string          `json:"used"`
+	Percentage float64         `json:"percentage"`
+	Writes     Usage[uint64]   `json:"writes"`
+	Reads      Usage[uint64]   `json:"reads"`
+	Partitions []PartitionStat `json:"partitions"`
 }
 
 func GetMemoryStat() (MemStat, error) {
@@ -50,17 +62,87 @@ func GetMemoryStat() (MemStat, error) {
 }
 
 func GetDiskStat() (DiskStat, error) {
-	diskUsage, err := disk.Usage(".")
-
+	// Get all partitions
+	partitions, err := disk.Partitions(false)
 	if err != nil {
-		return DiskStat{}, errors.Wrap(err, "error analytic getDiskStat")
+		return DiskStat{}, errors.Wrap(err, "error analytic getDiskStat - getting partitions")
+	}
+
+	var totalSize uint64
+	var totalUsed uint64
+	var partitionStats []PartitionStat
+
+	// 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
+		}
+
+		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)
+		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(diskUsage.Used),
-		Total:      humanize.Bytes(diskUsage.Total),
-		Percentage: cast.ToFloat64(fmt.Sprintf("%.2f", diskUsage.UsedPercent)),
+		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]
+}

+ 49 - 0
internal/analytic/stat_test.go

@@ -0,0 +1,49 @@
+package analytic
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestGetDiskStat(t *testing.T) {
+	diskStat, err := GetDiskStat()
+
+	// Test that the function doesn't return an error
+	assert.NoError(t, err)
+
+	// Test that partitions are populated
+	assert.NotEmpty(t, diskStat.Partitions)
+
+	// Test that overall stats are calculated
+	assert.NotEmpty(t, diskStat.Total)
+	assert.NotEmpty(t, diskStat.Used)
+	assert.GreaterOrEqual(t, diskStat.Percentage, 0.0)
+	assert.LessOrEqual(t, diskStat.Percentage, 100.0)
+
+	// Test each partition has required fields
+	for _, partition := range diskStat.Partitions {
+		assert.NotEmpty(t, partition.Mountpoint)
+		assert.NotEmpty(t, partition.Device)
+		assert.NotEmpty(t, partition.Fstype)
+		assert.NotEmpty(t, partition.Total)
+		assert.NotEmpty(t, partition.Used)
+		assert.NotEmpty(t, partition.Free)
+		assert.GreaterOrEqual(t, partition.Percentage, 0.0)
+		assert.LessOrEqual(t, partition.Percentage, 100.0)
+	}
+}
+
+func TestIsVirtualFilesystem(t *testing.T) {
+	// Test virtual filesystems
+	assert.True(t, isVirtualFilesystem("proc"))
+	assert.True(t, isVirtualFilesystem("sysfs"))
+	assert.True(t, isVirtualFilesystem("tmpfs"))
+	assert.True(t, isVirtualFilesystem("devpts"))
+
+	// Test real filesystems
+	assert.False(t, isVirtualFilesystem("ext4"))
+	assert.False(t, isVirtualFilesystem("xfs"))
+	assert.False(t, isVirtualFilesystem("ntfs"))
+	assert.False(t, isVirtualFilesystem("fat32"))
+}