package file
import (
"context"
"sync"
"time"
"github.com/grafana/agent/component/discovery"
"github.com/go-kit/log/level"
"github.com/grafana/agent/component"
)
func init() {
component.Register(component.Registration{
Name: "discovery.file",
Args: Arguments{},
Exports: discovery.Exports{},
Build: func(opts component.Options, args component.Arguments) (component.Component, error) {
return New(opts, args.(Arguments))
},
})
}
type Arguments struct {
PathTargets []discovery.Target `river:"path_targets,attr"`
SyncPeriod time.Duration `river:"sync_period,attr,optional"`
}
var _ component.Component = (*Component)(nil)
type Component struct {
opts component.Options
mut sync.RWMutex
args Arguments
watches []watch
watchDog *time.Ticker
}
func New(o component.Options, args Arguments) (*Component, error) {
c := &Component{
opts: o,
mut: sync.RWMutex{},
args: args,
watches: make([]watch, 0),
watchDog: time.NewTicker(args.SyncPeriod),
}
if err := c.Update(args); err != nil {
return nil, err
}
return c, nil
}
func getDefault() Arguments {
return Arguments{SyncPeriod: 10 * time.Second}
}
func (a *Arguments) UnmarshalRiver(f func(interface{}) error) error {
*a = getDefault()
type arguments Arguments
return f((*arguments)(a))
}
func (c *Component) Update(args component.Arguments) error {
c.mut.Lock()
defer c.mut.Unlock()
if args.(Arguments).SyncPeriod != c.args.SyncPeriod {
c.watchDog.Reset(c.args.SyncPeriod)
}
c.args = args.(Arguments)
c.watches = c.watches[:0]
for _, v := range c.args.PathTargets {
c.watches = append(c.watches, watch{
target: v,
log: c.opts.Logger,
})
}
return nil
}
func (c *Component) Run(ctx context.Context) error {
update := func() {
c.mut.Lock()
defer c.mut.Unlock()
paths := c.getWatchedFiles()
c.opts.OnStateChange(discovery.Exports{Targets: paths})
}
update()
defer c.watchDog.Stop()
for {
select {
case <-c.watchDog.C:
update()
case <-ctx.Done():
return nil
}
}
}
func (c *Component) getWatchedFiles() []discovery.Target {
paths := make([]discovery.Target, 0)
for _, w := range c.watches {
newPaths, err := w.getPaths()
if err != nil {
level.Error(c.opts.Logger).Log("msg", "error getting paths", "path", w.getPath(), "excluded", w.getExcludePath(), "err", err)
}
paths = append(paths, newPaths...)
}
return paths
}