github.com/netdata/go.d.plugin@v0.58.1/modules/filecheck/collect_files.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package filecheck 4 5 import ( 6 "fmt" 7 "os" 8 "path/filepath" 9 "strings" 10 "time" 11 12 "github.com/netdata/go.d.plugin/agent/module" 13 ) 14 15 func (fc *Filecheck) collectFiles(ms map[string]int64) { 16 curTime := time.Now() 17 if time.Since(fc.lastDiscoveryFiles) >= fc.DiscoveryEvery.Duration { 18 fc.lastDiscoveryFiles = curTime 19 fc.curFiles = fc.discoveryFiles() 20 fc.updateFilesCharts(fc.curFiles) 21 } 22 23 for _, path := range fc.curFiles { 24 fc.collectFile(ms, path, curTime) 25 } 26 ms["num_of_files"] = int64(len(fc.curFiles)) 27 } 28 29 func (fc *Filecheck) collectFile(ms map[string]int64, path string, curTime time.Time) { 30 info, err := os.Stat(path) 31 if err != nil { 32 if os.IsNotExist(err) { 33 ms[fileDimID(path, "exists")] = 0 34 } else { 35 ms[fileDimID(path, "exists")] = 1 36 } 37 fc.Debug(err) 38 return 39 } 40 41 if info.IsDir() { 42 return 43 } 44 45 ms[fileDimID(path, "exists")] = 1 46 ms[fileDimID(path, "size_bytes")] = info.Size() 47 ms[fileDimID(path, "mtime_ago")] = int64(curTime.Sub(info.ModTime()).Seconds()) 48 } 49 50 func (fc Filecheck) discoveryFiles() (files []string) { 51 for _, path := range fc.Files.Include { 52 if hasMeta(path) { 53 continue 54 } 55 files = append(files, path) 56 } 57 58 for _, path := range fc.Files.Include { 59 if !hasMeta(path) { 60 continue 61 } 62 matches, _ := filepath.Glob(path) 63 for _, v := range matches { 64 fi, err := os.Lstat(v) 65 if err == nil && fi.Mode().IsRegular() { 66 files = append(files, v) 67 } 68 } 69 } 70 return removeDuplicates(files) 71 } 72 73 func (fc *Filecheck) updateFilesCharts(files []string) { 74 set := make(map[string]bool, len(files)) 75 for _, path := range files { 76 set[path] = true 77 if !fc.collectedFiles[path] { 78 fc.collectedFiles[path] = true 79 fc.addFileToCharts(path) 80 } 81 } 82 for path := range fc.collectedFiles { 83 if !set[path] { 84 delete(fc.collectedFiles, path) 85 fc.removeFileFromCharts(path) 86 } 87 } 88 } 89 90 func (fc *Filecheck) addFileToCharts(path string) { 91 for _, chart := range *fc.Charts() { 92 if !strings.HasPrefix(chart.ID, "file_") { 93 continue 94 } 95 96 var id string 97 switch chart.ID { 98 case fileExistenceChart.ID: 99 id = fileDimID(path, "exists") 100 case fileModTimeAgoChart.ID: 101 id = fileDimID(path, "mtime_ago") 102 case fileSizeChart.ID: 103 id = fileDimID(path, "size_bytes") 104 default: 105 fc.Warningf("add dimension: couldn't dim id for '%s' chart (file '%s')", chart.ID, path) 106 continue 107 } 108 109 dim := &module.Dim{ID: id, Name: reSpace.ReplaceAllString(path, "_")} 110 111 if err := chart.AddDim(dim); err != nil { 112 fc.Warning(err) 113 continue 114 } 115 chart.MarkNotCreated() 116 } 117 } 118 119 func (fc *Filecheck) removeFileFromCharts(path string) { 120 for _, chart := range *fc.Charts() { 121 if !strings.HasPrefix(chart.ID, "file_") { 122 continue 123 } 124 125 var id string 126 switch chart.ID { 127 case fileExistenceChart.ID: 128 id = fileDimID(path, "exists") 129 case fileModTimeAgoChart.ID: 130 id = fileDimID(path, "mtime_ago") 131 case fileSizeChart.ID: 132 id = fileDimID(path, "size_bytes") 133 default: 134 fc.Warningf("remove dimension: couldn't dim id for '%s' chart (file '%s')", chart.ID, path) 135 continue 136 } 137 138 if err := chart.MarkDimRemove(id, true); err != nil { 139 fc.Warning(err) 140 continue 141 } 142 chart.MarkNotCreated() 143 } 144 } 145 146 func fileDimID(path, metric string) string { 147 return fmt.Sprintf("file_%s_%s", reSpace.ReplaceAllString(path, "_"), metric) 148 }