github.com/netdata/go.d.plugin@v0.58.1/agent/discovery/file/discovery.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package file 4 5 import ( 6 "context" 7 "errors" 8 "fmt" 9 "log/slog" 10 "sync" 11 12 "github.com/netdata/go.d.plugin/agent/confgroup" 13 "github.com/netdata/go.d.plugin/logger" 14 ) 15 16 var log = logger.New().With( 17 slog.String("component", "discovery file"), 18 ) 19 20 func NewDiscovery(cfg Config) (*Discovery, error) { 21 if err := validateConfig(cfg); err != nil { 22 return nil, fmt.Errorf("file discovery config validation: %v", err) 23 } 24 25 d := Discovery{ 26 Logger: log, 27 } 28 29 if err := d.registerDiscoverers(cfg); err != nil { 30 return nil, fmt.Errorf("file discovery initialization: %v", err) 31 } 32 33 return &d, nil 34 } 35 36 type ( 37 Discovery struct { 38 *logger.Logger 39 discoverers []discoverer 40 } 41 discoverer interface { 42 Run(ctx context.Context, in chan<- []*confgroup.Group) 43 } 44 ) 45 46 func (d *Discovery) String() string { 47 return d.Name() 48 } 49 50 func (d *Discovery) Name() string { 51 return fmt.Sprintf("file discovery: %v", d.discoverers) 52 } 53 54 func (d *Discovery) registerDiscoverers(cfg Config) error { 55 if len(cfg.Read) != 0 { 56 d.discoverers = append(d.discoverers, NewReader(cfg.Registry, cfg.Read)) 57 } 58 if len(cfg.Watch) != 0 { 59 d.discoverers = append(d.discoverers, NewWatcher(cfg.Registry, cfg.Watch)) 60 } 61 if len(d.discoverers) == 0 { 62 return errors.New("zero registered discoverers") 63 } 64 return nil 65 } 66 67 func (d *Discovery) Run(ctx context.Context, in chan<- []*confgroup.Group) { 68 d.Info("instance is started") 69 defer func() { d.Info("instance is stopped") }() 70 71 var wg sync.WaitGroup 72 73 for _, dd := range d.discoverers { 74 wg.Add(1) 75 go func(dd discoverer) { 76 defer wg.Done() 77 d.runDiscoverer(ctx, dd, in) 78 }(dd) 79 } 80 81 wg.Wait() 82 <-ctx.Done() 83 } 84 85 func (d *Discovery) runDiscoverer(ctx context.Context, dd discoverer, in chan<- []*confgroup.Group) { 86 updates := make(chan []*confgroup.Group) 87 go dd.Run(ctx, updates) 88 for { 89 select { 90 case <-ctx.Done(): 91 return 92 case groups, ok := <-updates: 93 if !ok { 94 return 95 } 96 select { 97 case <-ctx.Done(): 98 return 99 case in <- groups: 100 } 101 } 102 } 103 }