package app import ( "sync" "gitea.sinav-lab.com/sinav/keenetic-exporter-v2/internal/collector" "gitea.sinav-lab.com/sinav/keenetic-exporter-v2/internal/device" "github.com/prometheus/client_golang/prometheus" ) type Coordinator struct { deviceManager *device.Manager registry *collector.Registry } func NewCoordinator(dm *device.Manager, reg *collector.Registry) *Coordinator { return &Coordinator{ deviceManager: dm, registry: reg, } } // Реализация интерфейса prometheus.Collector func (c *Coordinator) Describe(ch chan<- *prometheus.Desc) { collectors := c.registry.GetCollectors() for _, col := range collectors { col.Describe(ch) } } func (c *Coordinator) Collect(ch chan<- prometheus.Metric) { c.Scrape(ch) } func (c *Coordinator) Scrape(ch chan<- prometheus.Metric) { devices := c.deviceManager.GetDevices() collectors := c.registry.GetCollectors() var wg sync.WaitGroup for _, d := range devices { wg.Add(1) go func(dev *device.Device) { defer wg.Done() c.scrapeDevice(dev, collectors, ch) }(d) } wg.Wait() } func (c *Coordinator) scrapeDevice(dev *device.Device, collectors []collector.Collector, ch chan<- prometheus.Metric) { for _, col := range collectors { if shouldSkipCollector(dev, col.Name()) { continue } if err := col.Collect(dev, ch); err != nil { // TODO: handle error metric continue } } } func shouldSkipCollector(dev *device.Device, name string) bool { for _, skip := range dev.SkipCollectors { if skip == name { return true } } return false }