package auto import ( "path/filepath" "time" cgroupStats "linkfog.com/public/lib/cgroup/stats" "linkfog.com/public/lib/common" "linkfog.com/public/lib/l" "linkfog.com/public/lib/unit" "linkfog.com/public/option" ) type Config struct { EnableDetectMem common.EnableType // 是否采集内存异常时的信息,默认开启,非必填 PProfProfilePath string // 采集pprof数据存放目录,默认值为"/host/dosec/pprof",非必填 DetectInterval time.Duration // 周期检测cpu和内存当前占用,默认值"20s",非必填 DetectCPURateRange time.Duration // 计算cpu稳定占比的区间,默认值"5m",非必填 PProfCollectDura time.Duration // 单次采集时长,默认值为"1m",非必填 RetentionDays int // 采集文件保存天数,默认为"7",非必填 MinTriggerValue string // 最低触发值,默认值"500M",非必填 MaxRecordNumPerHour uint // 每小时最大收集次数,默认值"6",非必填 RecordSensitivity string // 收集灵敏度,默认值"100M" MaxDiskUsage string // 最大磁盘使用,默认值"6G" AbnormalGoroutineNum int // 异常Goroutine数量 } type auto struct { config Config // 采集参数设置 fixedQuotient int // 固定商值,最低的采集底线,灵敏度越低,在超过最低触发值的情况下,固定商值越低,所以采集的次数会有所增加 cgroup *cgroupStats.Stats // 采集cgroup cpu和memory perHourQuotient []int // 每小时收集的动态商值 detectInterval time.Duration // 周期检测时间间隔 recordSensitivity float64 // 采集灵敏度 maxDiskUsage float64 // 磁盘最大占用初始化 periodRecordCount uint // 每小时计数器 } func New() *auto { return NewAutoPProf(Config{}) } func NewAutoPProf(srcConf Config) *auto { var defaultConf = Config{ EnableDetectMem: common.Enabled, PProfProfilePath: filepath.Join(option.HostPrefix, option.NamespacePrefix, option.PProfPrefix), DetectInterval: 20 * time.Second, DetectCPURateRange: 5 * time.Minute, PProfCollectDura: time.Minute, RetentionDays: 7, MinTriggerValue: "500M", MaxRecordNumPerHour: 6, RecordSensitivity: "100M", MaxDiskUsage: "6G", AbnormalGoroutineNum: 150, } finalConfig := mergeConfig(defaultConf, srcConf) l.Info("pprof create cgroup stats") stats := cgroupStats.NewStats(-1, finalConfig.DetectInterval, finalConfig.DetectCPURateRange) return &auto{ config: finalConfig, cgroup: stats, } } func (p *auto) init() error { err := p.cgroup.TryCgroupPath() if err != nil { l.Error("pprof cgroup stats try cgroup path err:", err) return nil } l.Infof("cgroup stats mem dir:%s", p.cgroup.GetMemoryDir()) l.Infof("cgroup stats cpu dir:%s", p.cgroup.GetCPUDir()) l.Infof("cgroup stats io dir:%s", p.cgroup.GetIODir()) minMem, err := unit.ToBytes(p.config.MinTriggerValue) if err != nil { return l.WrapError(err) } recordSensitivity, err := unit.ToBytes(p.config.RecordSensitivity) if err != nil { return l.WrapError(err) } maxDiskUsage, err := unit.ToBytes(p.config.MaxDiskUsage) if err != nil { return l.WrapError(err) } if recordSensitivity < 1 || minMem <= 0 || maxDiskUsage <= 0 || p.config.MaxRecordNumPerHour <= 0 { return l.WrapError("minTriggerValue or recordSensitivity or maxDiskUsage or maxRecordNumPerHour is abnormal", minMem, recordSensitivity, maxDiskUsage, p.config.MaxRecordNumPerHour) } p.maxDiskUsage = float64(maxDiskUsage) // 初始化磁盘最大容量 p.recordSensitivity = float64(recordSensitivity) // 初始化灵敏度 p.fixedQuotient = int(float64(minMem) / p.recordSensitivity) // 初始固定商值,使用限制内存除以采集灵敏度,获取一个固定的商值,用于与后续的动态商值对比, p.detectInterval = time.Hour / time.Duration(p.config.MaxRecordNumPerHour) // 初始化采集时间间隔 p.perHourQuotient = make([]int, 6) // 初始化每小时商值存储切片 return nil } // notice zero value risk func mergeConfig(dst, src Config) Config { err := common.MergeStructExportedFields(&dst, &src) if err != nil { l.Error(err) } return dst }