package agent import ( "context" "math/rand" "time" "git.opencomputing.cn/yumoqing/host-metrics-collector/internal/model" ) // collectFn 是某一指标组的采集函数。 type collectFn func() ([]model.Sample, error) // runGroup 按固定间隔运行采集,并把样本投递到 out 通道。 // // - 启动时加入随机 jitter(0 ~ interval/2),避免大量主机同秒上报(惊群)。 // - 每次采集带超时控制,超时或出错时记录错误并继续下一轮。 func runGroup(ctx context.Context, interval, timeout time.Duration, name string, fn collectFn, out chan<- model.Sample, errc chan<- error) { // 首次延迟打散。 first := time.Duration(rand.Int63n(int64(interval / 2))) timer := time.NewTimer(first) defer timer.Stop() for { select { case <-ctx.Done(): return case <-timer.C: } samples, err := collectWithTimeout(ctx, timeout, fn) if err != nil { select { case errc <- err: default: } } for _, s := range samples { select { case out <- s: case <-ctx.Done(): return } } timer.Reset(interval) } } // collectWithTimeout 在超时约束下执行采集函数。 func collectWithTimeout(ctx context.Context, timeout time.Duration, fn collectFn) ([]model.Sample, error) { type result struct { samples []model.Sample err error } ch := make(chan result, 1) go func() { samples, err := fn() ch <- result{samples: samples, err: err} }() select { case r := <-ch: return r.samples, r.err case <-ctx.Done(): return nil, ctx.Err() case <-time.After(timeout): return nil, context.DeadlineExceeded } }