@@ -2,65 +2,13 @@ package analytic
22
33import (
44 "fmt"
5- "math"
65
76 "github.com/dustin/go-humanize"
87 "github.com/pkg/errors"
98 "github.com/shirou/gopsutil/v4/disk"
10- "github.com/shirou/gopsutil/v4/mem"
119 "github.com/spf13/cast"
1210)
1311
14- type MemStat struct {
15- Total string `json:"total"`
16- Used string `json:"used"`
17- Cached string `json:"cached"`
18- Free string `json:"free"`
19- SwapUsed string `json:"swap_used"`
20- SwapTotal string `json:"swap_total"`
21- SwapCached string `json:"swap_cached"`
22- SwapPercent float64 `json:"swap_percent"`
23- Pressure float64 `json:"pressure"`
24- }
25-
26- type PartitionStat struct {
27- Mountpoint string `json:"mountpoint"`
28- Device string `json:"device"`
29- Fstype string `json:"fstype"`
30- Total string `json:"total"`
31- Used string `json:"used"`
32- Free string `json:"free"`
33- Percentage float64 `json:"percentage"`
34- }
35-
36- type DiskStat struct {
37- Total string `json:"total"`
38- Used string `json:"used"`
39- Percentage float64 `json:"percentage"`
40- Writes Usage [uint64 ] `json:"writes"`
41- Reads Usage [uint64 ] `json:"reads"`
42- Partitions []PartitionStat `json:"partitions"`
43- }
44-
45- func GetMemoryStat () (MemStat , error ) {
46- memoryStat , err := mem .VirtualMemory ()
47- if err != nil {
48- return MemStat {}, errors .Wrap (err , "error analytic getMemoryStat" )
49- }
50- return MemStat {
51- Total : humanize .Bytes (memoryStat .Total ),
52- Used : humanize .Bytes (memoryStat .Used ),
53- Cached : humanize .Bytes (memoryStat .Cached ),
54- Free : humanize .Bytes (memoryStat .Free ),
55- SwapUsed : humanize .Bytes (memoryStat .SwapTotal - memoryStat .SwapFree ),
56- SwapTotal : humanize .Bytes (memoryStat .SwapTotal ),
57- SwapCached : humanize .Bytes (memoryStat .SwapCached ),
58- SwapPercent : cast .ToFloat64 (fmt .Sprintf ("%.2f" ,
59- 100 * float64 (memoryStat .SwapTotal - memoryStat .SwapFree )/ math .Max (float64 (memoryStat .SwapTotal ), 1 ))),
60- Pressure : cast .ToFloat64 (fmt .Sprintf ("%.2f" , memoryStat .UsedPercent )),
61- }, nil
62- }
63-
6412func GetDiskStat () (DiskStat , error ) {
6513 // Get all partitions
6614 partitions , err := disk .Partitions (false )
@@ -71,6 +19,8 @@ func GetDiskStat() (DiskStat, error) {
7119 var totalSize uint64
7220 var totalUsed uint64
7321 var partitionStats []PartitionStat
22+ // Track partitions to avoid double counting same partition with multiple mount points
23+ partitionUsage := make (map [string ]* disk.UsageStat )
7424
7525 // Get usage for each partition
7626 for _ , partition := range partitions {
@@ -85,6 +35,7 @@ func GetDiskStat() (DiskStat, error) {
8535 continue
8636 }
8737
38+ // Create partition stat for display purposes
8839 partitionStat := PartitionStat {
8940 Mountpoint : partition .Mountpoint ,
9041 Device : partition .Device ,
@@ -94,10 +45,15 @@ func GetDiskStat() (DiskStat, error) {
9445 Free : humanize .Bytes (usage .Free ),
9546 Percentage : cast .ToFloat64 (fmt .Sprintf ("%.2f" , usage .UsedPercent )),
9647 }
97-
9848 partitionStats = append (partitionStats , partitionStat )
99- totalSize += usage .Total
100- totalUsed += usage .Used
49+
50+ // Only count each partition device once for total calculation
51+ // This handles cases where same partition is mounted multiple times (e.g., bind mounts, overlayfs)
52+ if _ , exists := partitionUsage [partition .Device ]; ! exists {
53+ partitionUsage [partition .Device ] = usage
54+ totalSize += usage .Total
55+ totalUsed += usage .Used
56+ }
10157 }
10258
10359 // Calculate overall percentage
0 commit comments