mirror of
				https://github.com/ClusterCockpit/cc-metric-collector.git
				synced 2025-10-25 15:25:07 +02:00 
			
		
		
		
	add only_metrics and exclude_mounts
This commit is contained in:
		| @@ -8,23 +8,38 @@ import ( | |||||||
| 	"syscall" | 	"syscall" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
|  | 	lp "github.com/ClusterCockpit/cc-lib/ccMessage" | ||||||
| 	cclog "github.com/ClusterCockpit/cc-metric-collector/pkg/ccLogger" | 	cclog "github.com/ClusterCockpit/cc-metric-collector/pkg/ccLogger" | ||||||
| 	lp "github.com/ClusterCockpit/cc-energy-manager/pkg/cc-message" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| //	"log" |  | ||||||
|  |  | ||||||
| const MOUNTFILE = `/proc/self/mounts` | const MOUNTFILE = `/proc/self/mounts` | ||||||
|  |  | ||||||
| type DiskstatCollectorConfig struct { | type DiskstatCollectorConfig struct { | ||||||
| 	ExcludeMetrics []string `json:"exclude_metrics,omitempty"` | 	ExcludeMetrics []string `json:"exclude_metrics,omitempty"` | ||||||
|  | 	OnlyMetrics    []string `json:"only_metrics,omitempty"` | ||||||
|  | 	ExcludeMounts  []string `json:"exclude_mounts,omitempty"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type DiskstatCollector struct { | type DiskstatCollector struct { | ||||||
| 	metricCollector | 	metricCollector | ||||||
| 	//matches map[string]int | 	config DiskstatCollectorConfig | ||||||
| 	config IOstatCollectorConfig | } | ||||||
| 	//devices map[string]IOstatCollectorEntry |  | ||||||
|  | func (m *DiskstatCollector) shouldOutput(metricName string) bool { | ||||||
|  | 	if len(m.config.OnlyMetrics) > 0 { | ||||||
|  | 		for _, n := range m.config.OnlyMetrics { | ||||||
|  | 			if n == metricName { | ||||||
|  | 				return true | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	for _, n := range m.config.ExcludeMetrics { | ||||||
|  | 		if n == metricName { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return true | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *DiskstatCollector) Init(config json.RawMessage) error { | func (m *DiskstatCollector) Init(config json.RawMessage) error { | ||||||
| @@ -33,12 +48,11 @@ func (m *DiskstatCollector) Init(config json.RawMessage) error { | |||||||
| 	m.meta = map[string]string{"source": m.name, "group": "Disk"} | 	m.meta = map[string]string{"source": m.name, "group": "Disk"} | ||||||
| 	m.setup() | 	m.setup() | ||||||
| 	if len(config) > 0 { | 	if len(config) > 0 { | ||||||
| 		err := json.Unmarshal(config, &m.config) | 		if err := json.Unmarshal(config, &m.config); err != nil { | ||||||
| 		if err != nil { |  | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	file, err := os.Open(string(MOUNTFILE)) | 	file, err := os.Open(MOUNTFILE) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		cclog.ComponentError(m.name, err.Error()) | 		cclog.ComponentError(m.name, err.Error()) | ||||||
| 		return err | 		return err | ||||||
| @@ -53,7 +67,7 @@ func (m *DiskstatCollector) Read(interval time.Duration, output chan lp.CCMessag | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	file, err := os.Open(string(MOUNTFILE)) | 	file, err := os.Open(MOUNTFILE) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		cclog.ComponentError(m.name, err.Error()) | 		cclog.ComponentError(m.name, err.Error()) | ||||||
| 		return | 		return | ||||||
| @@ -62,6 +76,7 @@ func (m *DiskstatCollector) Read(interval time.Duration, output chan lp.CCMessag | |||||||
|  |  | ||||||
| 	part_max_used := uint64(0) | 	part_max_used := uint64(0) | ||||||
| 	scanner := bufio.NewScanner(file) | 	scanner := bufio.NewScanner(file) | ||||||
|  | mountLoop: | ||||||
| 	for scanner.Scan() { | 	for scanner.Scan() { | ||||||
| 		line := scanner.Text() | 		line := scanner.Text() | ||||||
| 		if len(line) == 0 { | 		if len(line) == 0 { | ||||||
| @@ -71,38 +86,42 @@ func (m *DiskstatCollector) Read(interval time.Duration, output chan lp.CCMessag | |||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		linefields := strings.Fields(line) | 		linefields := strings.Fields(line) | ||||||
| 		if strings.Contains(linefields[0], "loop") { | 		if strings.Contains(linefields[0], "loop") || strings.Contains(linefields[1], "boot") { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		if strings.Contains(linefields[1], "boot") { |  | ||||||
| 			continue | 		mountPath := strings.Replace(linefields[1], `\040`, " ", -1) | ||||||
|  | 		for _, excl := range m.config.ExcludeMounts { | ||||||
|  | 			if strings.Contains(mountPath, excl) { | ||||||
|  | 				continue mountLoop | ||||||
| 			} | 			} | ||||||
| 		path := strings.Replace(linefields[1], `\040`, " ", -1) |  | ||||||
| 		stat := syscall.Statfs_t{ |  | ||||||
| 			Blocks: 0, |  | ||||||
| 			Bsize:  0, |  | ||||||
| 			Bfree:  0, |  | ||||||
| 		} | 		} | ||||||
| 		err := syscall.Statfs(path, &stat) |  | ||||||
| 		if err != nil { | 		stat := syscall.Statfs_t{} | ||||||
|  | 		if err := syscall.Statfs(mountPath, &stat); err != nil { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		if stat.Blocks == 0 || stat.Bsize == 0 { | 		if stat.Blocks == 0 || stat.Bsize == 0 { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		tags := map[string]string{"type": "node", "device": linefields[0]} | 		tags := map[string]string{"type": "node", "device": linefields[0]} | ||||||
| 		total := (stat.Blocks * uint64(stat.Bsize)) / uint64(1000000000) | 		total := (stat.Blocks * uint64(stat.Bsize)) / uint64(1000000000) | ||||||
|  | 		if m.shouldOutput("disk_total") { | ||||||
| 			y, err := lp.NewMessage("disk_total", tags, m.meta, map[string]interface{}{"value": total}, time.Now()) | 			y, err := lp.NewMessage("disk_total", tags, m.meta, map[string]interface{}{"value": total}, time.Now()) | ||||||
| 			if err == nil { | 			if err == nil { | ||||||
| 				y.AddMeta("unit", "GBytes") | 				y.AddMeta("unit", "GBytes") | ||||||
| 				output <- y | 				output <- y | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 		free := (stat.Bfree * uint64(stat.Bsize)) / uint64(1000000000) | 		free := (stat.Bfree * uint64(stat.Bsize)) / uint64(1000000000) | ||||||
| 		y, err = lp.NewMessage("disk_free", tags, m.meta, map[string]interface{}{"value": free}, time.Now()) | 		if m.shouldOutput("disk_free") { | ||||||
|  | 			y, err := lp.NewMessage("disk_free", tags, m.meta, map[string]interface{}{"value": free}, time.Now()) | ||||||
| 			if err == nil { | 			if err == nil { | ||||||
| 				y.AddMeta("unit", "GBytes") | 				y.AddMeta("unit", "GBytes") | ||||||
| 				output <- y | 				output <- y | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 		if total > 0 { | 		if total > 0 { | ||||||
| 			perc := (100 * (total - free)) / total | 			perc := (100 * (total - free)) / total | ||||||
| 			if perc > part_max_used { | 			if perc > part_max_used { | ||||||
| @@ -110,11 +129,13 @@ func (m *DiskstatCollector) Read(interval time.Duration, output chan lp.CCMessag | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	if m.shouldOutput("part_max_used") { | ||||||
| 		y, err := lp.NewMessage("part_max_used", map[string]string{"type": "node"}, m.meta, map[string]interface{}{"value": int(part_max_used)}, time.Now()) | 		y, err := lp.NewMessage("part_max_used", map[string]string{"type": "node"}, m.meta, map[string]interface{}{"value": int(part_max_used)}, time.Now()) | ||||||
| 		if err == nil { | 		if err == nil { | ||||||
| 			y.AddMeta("unit", "percent") | 			y.AddMeta("unit", "percent") | ||||||
| 			output <- y | 			output <- y | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *DiskstatCollector) Close() { | func (m *DiskstatCollector) Close() { | ||||||
|   | |||||||
| @@ -1,21 +1,29 @@ | |||||||
|  |  | ||||||
| ## `diskstat` collector | ## `diskstat` collector | ||||||
|  |  | ||||||
| ```json | ```json | ||||||
|   "diskstat": { |   "diskstat": { | ||||||
|     "exclude_metrics": [ |     "exclude_metrics": [ | ||||||
|       "disk_total" |       "part_max_used" | ||||||
|     ], |     ], | ||||||
|  |     "only_metrics": [ | ||||||
|  |       "disk_free", | ||||||
|  |     ], | ||||||
|  |     "exclude_mounts": [ | ||||||
|  |       "slurm-tmpfs" | ||||||
|  |     ] | ||||||
|   } |   } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| The `diskstat` collector reads data from `/proc/self/mounts` and outputs a handful **node** metrics. If a metric is not required, it can be excluded from forwarding it to the sink. | The `diskstat` collector reads data from `/proc/self/mounts` and outputs a handful **node** metrics.  | ||||||
|  | Any mount point containing one of the strings specified in `exclude_mounts` will be skipped during metric collection. | ||||||
|  |  | ||||||
|  | Both filtering mechanisms are supported: | ||||||
|  | - `exclude_metrics`: Excludes the specified metrics. | ||||||
|  | - `only_metrics`: If provided, only the listed metrics are collected. This takes precedence over `exclude_metrics`. | ||||||
|  |  | ||||||
| Metrics per device (with `device` tag): | Metrics per device (with `device` tag): | ||||||
| * `disk_total` (unit `GBytes`) | - `disk_total` (unit `GBytes`) | ||||||
| * `disk_free` (unit `GBytes`) | - `disk_free` (unit `GBytes`) | ||||||
|  |  | ||||||
| Global metrics: | Global metrics: | ||||||
| * `part_max_used` (unit `percent`) | - `part_max_used` (unit `percent`) | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user