fix: 磁盘采集支持多硬盘,修复只采集系统盘的问题
- 默认采集所有真实存储设备而非仅根分区 - 通过设备路径白名单识别真实磁盘(块设备/网络存储) - 排除 tmpfs、proc、cgroup 等虚拟文件系统 - 排除 macOS APFS 冗余系统卷(Preboot/VM/Update 等)
This commit is contained in:
1 parent
47c9a515a2
commit
cfde75e21e
2 files changed
+69
-13
No files matched your search
@@ -1,11 +1,24 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/dushixiang/pika/internal/protocol"
|
||||
"github.com/dushixiang/pika/pkg/agent/config"
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
)
|
||||
|
||||
// 不以 /dev/ 开头但仍是真实存储的文件系统类型
|
||||
var realFSTypes = map[string]bool{
|
||||
"nfs": true,
|
||||
"nfs4": true,
|
||||
"cifs": true,
|
||||
"smbfs": true,
|
||||
"zfs": true,
|
||||
"glusterfs": true,
|
||||
"cephfs": true,
|
||||
}
|
||||
|
||||
// DiskCollector 磁盘监控采集器
|
||||
type DiskCollector struct {
|
||||
config *config.Config
|
||||
@@ -18,6 +31,43 @@ func NewDiskCollector(cfg *config.Config) *DiskCollector {
|
||||
}
|
||||
}
|
||||
|
||||
// isRealDisk 判断是否为真实存储设备
|
||||
func isRealDisk(device, fstype string) bool {
|
||||
// Windows 盘符
|
||||
if len(device) == 2 && device[1] == ':' {
|
||||
return true
|
||||
}
|
||||
// Unix 块设备
|
||||
if strings.HasPrefix(device, "/dev/") {
|
||||
return true
|
||||
}
|
||||
// 网络/集群存储
|
||||
return realFSTypes[fstype]
|
||||
}
|
||||
|
||||
// macOS APFS 容器内与数据卷共享物理空间的系统辅助卷
|
||||
var macosSystemVolumes = map[string]bool{
|
||||
"Preboot": true,
|
||||
"VM": true,
|
||||
"Update": true,
|
||||
"xarts": true,
|
||||
"iSCPreboot": true,
|
||||
"Hardware": true,
|
||||
}
|
||||
|
||||
// isMacOSRedundant 判断是否为 macOS APFS 冗余系统卷
|
||||
func isMacOSRedundant(mountPoint, fstype string) bool {
|
||||
if fstype != "apfs" {
|
||||
return false
|
||||
}
|
||||
const prefix = "/System/Volumes/"
|
||||
if !strings.HasPrefix(mountPoint, prefix) {
|
||||
return false
|
||||
}
|
||||
volumeName := strings.TrimPrefix(mountPoint, prefix)
|
||||
return macosSystemVolumes[volumeName]
|
||||
}
|
||||
|
||||
// Collect 采集磁盘数据
|
||||
// 只采集配置的 DiskInclude 白名单中的挂载点
|
||||
func (d *DiskCollector) Collect() ([]protocol.DiskData, error) {
|
||||
@@ -28,6 +78,16 @@ func (d *DiskCollector) Collect() ([]protocol.DiskData, error) {
|
||||
|
||||
var diskDataList []protocol.DiskData
|
||||
for _, partition := range partitions {
|
||||
// 跳过虚拟文件系统
|
||||
if !isRealDisk(partition.Device, partition.Fstype) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 跳过 macOS APFS 冗余系统卷(与 Data 共享物理空间)
|
||||
if isMacOSRedundant(partition.Mountpoint, partition.Fstype) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 检查是否在白名单中
|
||||
if !d.config.ShouldIncludeDiskMountPoint(partition.Mountpoint) {
|
||||
continue
|
||||
@@ -39,12 +99,12 @@ func (d *DiskCollector) Collect() ([]protocol.DiskData, error) {
|
||||
continue // 跳过无法访问的分区
|
||||
}
|
||||
|
||||
// 跳过容量为 0 的分区(可能是虚拟文件系统)
|
||||
// 跳过容量为 0 的分区
|
||||
if usage.Total == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
diskData := protocol.DiskData{
|
||||
diskDataList = append(diskDataList, protocol.DiskData{
|
||||
MountPoint: partition.Mountpoint,
|
||||
Device: partition.Device,
|
||||
Fstype: partition.Fstype,
|
||||
@@ -52,9 +112,7 @@ func (d *DiskCollector) Collect() ([]protocol.DiskData, error) {
|
||||
Used: usage.Used,
|
||||
Free: usage.Free,
|
||||
UsagePercent: usage.UsedPercent,
|
||||
}
|
||||
|
||||
diskDataList = append(diskDataList, diskData)
|
||||
})
|
||||
}
|
||||
|
||||
// 所有白名单分区均采集失败时,返回空列表表示异常
|
||||
|
||||
@@ -388,23 +388,21 @@ func (c *Config) ShouldExcludeNetworkInterface(interfaceName string) bool {
|
||||
}
|
||||
|
||||
// GetDiskInclude 获取磁盘包含的挂载点列表(白名单)
|
||||
// 如果配置为空,返回默认的根分区匹配规则
|
||||
// Linux/macOS: ["/"]
|
||||
// Windows: ["C:"]
|
||||
// 返回 nil 表示未配置白名单,采集所有挂载点
|
||||
func (c *Config) GetDiskInclude() []string {
|
||||
if len(c.Collector.DiskInclude) == 0 {
|
||||
if runtime.GOOS == "windows" {
|
||||
return []string{"C:"}
|
||||
}
|
||||
return []string{"/"}
|
||||
return nil
|
||||
}
|
||||
return c.Collector.DiskInclude
|
||||
}
|
||||
|
||||
// ShouldIncludeDiskMountPoint 检查挂载点是否应该被采集
|
||||
// 只有在 DiskInclude 白名单中的挂载点才会被采集
|
||||
// 未配置白名单时采集所有挂载点
|
||||
func (c *Config) ShouldIncludeDiskMountPoint(mountPoint string) bool {
|
||||
includeMounts := c.GetDiskInclude()
|
||||
if len(includeMounts) == 0 {
|
||||
return true // 未配置白名单,采集所有
|
||||
}
|
||||
for _, mount := range includeMounts {
|
||||
if mountPoint == mount {
|
||||
return true
|
||||
|
||||
Reference in new issue
Block a user