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  }