-
Notifications
You must be signed in to change notification settings - Fork 486
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
document the changes and add to CL run lint better wording in docs for disabling auto reload Co-authored-by: Clayton Cornell <[email protected]> handle inline instead of throwing around channels gofmt-ed prrevent main proc from finishing before watcher is closed Co-authored-by: Robert Fratto <[email protected]> allow polling with override and rework to a separate utility for clean adding in force polling option is too granular rely on the context for sig events
- Loading branch information
1 parent
a2226c1
commit 2138d10
Showing
3 changed files
with
111 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package util | ||
|
||
import ( | ||
"context" | ||
"os" | ||
"time" | ||
|
||
"github.com/fsnotify/fsnotify" | ||
"github.com/go-kit/log/level" | ||
"github.com/grafana/agent/pkg/flow/logging" | ||
) | ||
|
||
type ReloadFunc func() error | ||
|
||
type FileWatcher struct { | ||
filePath string | ||
reloadFunc ReloadFunc | ||
pollInterval time.Duration | ||
} | ||
|
||
// NewFileWatcher creates a new file watcher that will call reloadFunc when the file at filePath is modified. | ||
func NewFileWatcher(filePath string, reloadFunc ReloadFunc, pollInterval time.Duration) *FileWatcher { | ||
return &FileWatcher{ | ||
filePath: filePath, | ||
reloadFunc: reloadFunc, | ||
pollInterval: pollInterval, | ||
} | ||
} | ||
|
||
// Watch starts watching the file for changes and calls reloadFunc when the file is modified. | ||
func (fw *FileWatcher) Watch(l *logging.Logger, ctx context.Context) { | ||
watcher, err := fsnotify.NewWatcher() | ||
if err != nil { | ||
level.Error(l).Log("msg", "failed to create watcher", "err", err) | ||
return | ||
} | ||
defer watcher.Close() | ||
|
||
err = watcher.Add(fw.filePath) | ||
if err != nil { | ||
level.Error(l).Log("msg", "failed to add file to watcher", "err", err) | ||
return | ||
} | ||
|
||
ticker := time.NewTicker(fw.pollInterval) | ||
defer ticker.Stop() | ||
|
||
var lastModTime time.Time | ||
if fileInfo, err := os.Stat(fw.filePath); err == nil { | ||
lastModTime = fileInfo.ModTime() | ||
} | ||
|
||
for { | ||
select { | ||
case <-ctx.Done(): | ||
return | ||
case event := <-watcher.Events: | ||
if event.Op&fsnotify.Write == fsnotify.Write { | ||
if err := fw.reloadFunc(); err != nil { | ||
level.Error(l).Log("msg", "failed to reload", "err", err) | ||
} | ||
} | ||
case err := <-watcher.Errors: | ||
level.Error(l).Log("msg", "watcher error", "err", err) | ||
case <-ticker.C: | ||
if fileInfo, err := os.Stat(fw.filePath); err == nil { | ||
modTime := fileInfo.ModTime() | ||
if modTime.After(lastModTime) { | ||
lastModTime = modTime | ||
if err := fw.reloadFunc(); err != nil { | ||
level.Error(l).Log("msg", "failed to reload", "err", err) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |