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  }