summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/filecheck/collect_dirs.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/go/collectors/go.d.plugin/modules/filecheck/collect_dirs.go184
1 files changed, 184 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/filecheck/collect_dirs.go b/src/go/collectors/go.d.plugin/modules/filecheck/collect_dirs.go
new file mode 100644
index 000000000..69a2e2f5c
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/filecheck/collect_dirs.go
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package filecheck
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+)
+
+func (fc *Filecheck) collectDirs(ms map[string]int64) {
+ curTime := time.Now()
+ if time.Since(fc.lastDiscoveryDirs) >= fc.DiscoveryEvery.Duration() {
+ fc.lastDiscoveryDirs = curTime
+ fc.curDirs = fc.discoveryDirs()
+ fc.updateDirsCharts(fc.curDirs)
+ }
+
+ for _, path := range fc.curDirs {
+ fc.collectDir(ms, path, curTime)
+ }
+ ms["num_of_dirs"] = int64(len(fc.curDirs))
+}
+
+func (fc *Filecheck) collectDir(ms map[string]int64, path string, curTime time.Time) {
+ info, err := os.Stat(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ ms[dirDimID(path, "exists")] = 0
+ } else {
+ ms[dirDimID(path, "exists")] = 1
+ }
+ fc.Debug(err)
+ return
+ }
+
+ if !info.IsDir() {
+ return
+ }
+
+ ms[dirDimID(path, "exists")] = 1
+ ms[dirDimID(path, "mtime_ago")] = int64(curTime.Sub(info.ModTime()).Seconds())
+ if num, err := calcDirNumOfFiles(path); err == nil {
+ ms[dirDimID(path, "num_of_files")] = int64(num)
+ }
+ if fc.Dirs.CollectDirSize {
+ if size, err := calcDirSize(path); err == nil {
+ ms[dirDimID(path, "size_bytes")] = size
+ }
+ }
+}
+
+func (fc *Filecheck) discoveryDirs() (dirs []string) {
+ for _, path := range fc.Dirs.Include {
+ if hasMeta(path) {
+ continue
+ }
+ dirs = append(dirs, path)
+ }
+
+ for _, path := range fc.Dirs.Include {
+ if !hasMeta(path) {
+ continue
+ }
+ matches, _ := filepath.Glob(path)
+ for _, v := range matches {
+ fi, err := os.Lstat(v)
+ if err == nil && fi.IsDir() {
+ dirs = append(dirs, v)
+ }
+ }
+ }
+ return removeDuplicates(dirs)
+}
+
+func (fc *Filecheck) updateDirsCharts(dirs []string) {
+ set := make(map[string]bool, len(dirs))
+ for _, path := range dirs {
+ set[path] = true
+ if !fc.collectedDirs[path] {
+ fc.collectedDirs[path] = true
+ fc.addDirToCharts(path)
+ }
+ }
+ for path := range fc.collectedDirs {
+ if !set[path] {
+ delete(fc.collectedDirs, path)
+ fc.removeDirFromCharts(path)
+ }
+ }
+}
+
+func (fc *Filecheck) addDirToCharts(path string) {
+ for _, chart := range *fc.Charts() {
+ if !strings.HasPrefix(chart.ID, "dir_") {
+ continue
+ }
+
+ var id string
+ switch chart.ID {
+ case dirExistenceChart.ID:
+ id = dirDimID(path, "exists")
+ case dirModTimeChart.ID:
+ id = dirDimID(path, "mtime_ago")
+ case dirNumOfFilesChart.ID:
+ id = dirDimID(path, "num_of_files")
+ case dirSizeChart.ID:
+ id = dirDimID(path, "size_bytes")
+ default:
+ fc.Warningf("add dimension: couldn't dim id for '%s' chart (dir '%s')", chart.ID, path)
+ continue
+ }
+
+ dim := &module.Dim{ID: id, Name: reSpace.ReplaceAllString(path, "_")}
+
+ if err := chart.AddDim(dim); err != nil {
+ fc.Warning(err)
+ continue
+ }
+ chart.MarkNotCreated()
+ }
+}
+
+func (fc *Filecheck) removeDirFromCharts(path string) {
+ for _, chart := range *fc.Charts() {
+ if !strings.HasPrefix(chart.ID, "dir_") {
+ continue
+ }
+
+ var id string
+ switch chart.ID {
+ case dirExistenceChart.ID:
+ id = dirDimID(path, "exists")
+ case dirModTimeChart.ID:
+ id = dirDimID(path, "mtime_ago")
+ case dirNumOfFilesChart.ID:
+ id = dirDimID(path, "num_of_files")
+ case dirSizeChart.ID:
+ id = dirDimID(path, "size_bytes")
+ default:
+ fc.Warningf("remove dimension: couldn't dim id for '%s' chart (dir '%s')", chart.ID, path)
+ continue
+ }
+
+ if err := chart.MarkDimRemove(id, true); err != nil {
+ fc.Warning(err)
+ continue
+ }
+ chart.MarkNotCreated()
+ }
+}
+
+func dirDimID(path, metric string) string {
+ return fmt.Sprintf("dir_%s_%s", reSpace.ReplaceAllString(path, "_"), metric)
+}
+
+func calcDirNumOfFiles(dirpath string) (int, error) {
+ f, err := os.Open(dirpath)
+ if err != nil {
+ return 0, err
+ }
+ defer func() { _ = f.Close() }()
+ // TODO: include dirs?
+ names, err := f.Readdirnames(-1)
+ return len(names), err
+}
+
+func calcDirSize(dirpath string) (int64, error) {
+ var size int64
+ err := filepath.Walk(dirpath, func(_ string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ if !info.IsDir() {
+ size += info.Size()
+ }
+ return nil
+ })
+ return size, err
+}