mirror of
https://github.com/ClusterCockpit/cc-metric-collector.git
synced 2025-12-20 06:06:16 +01:00
Add include configuration to diskstat collector
This commit is contained in:
@@ -23,13 +23,22 @@ const MOUNTFILE = `/proc/self/mounts`
|
|||||||
|
|
||||||
type DiskstatCollectorConfig struct {
|
type DiskstatCollectorConfig struct {
|
||||||
ExcludeMetrics []string `json:"exclude_metrics,omitempty"`
|
ExcludeMetrics []string `json:"exclude_metrics,omitempty"`
|
||||||
ExcludeMounts []string `json:"exclude_mounts,omitempty"`
|
ExcludeDevices []string `json:"exclude_devices,omitempty"`
|
||||||
|
ExcludeMountpoints []string `json:"exclude_mountpoints,omitempty"`
|
||||||
|
IncludeDevices []string `json:"include_devices,omitempty"`
|
||||||
|
IncludeMountpoints []string `json:"include_mountpoints,omitempty"`
|
||||||
|
UseMountpoint bool `json:"mountpoint_as_stype,omitempty"`
|
||||||
|
UseIncludeConfig bool `json:"use_include_config,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DiskstatCollector struct {
|
type DiskstatCollector struct {
|
||||||
metricCollector
|
metricCollector
|
||||||
config DiskstatCollectorConfig
|
config DiskstatCollectorConfig
|
||||||
allowedMetrics map[string]bool
|
allowedMetrics map[string]bool
|
||||||
|
includeDevices map[string]bool
|
||||||
|
includeMountpoints map[string]bool
|
||||||
|
excludeDevices map[string]bool
|
||||||
|
excludeMountpoints map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *DiskstatCollector) Init(config json.RawMessage) error {
|
func (m *DiskstatCollector) Init(config json.RawMessage) error {
|
||||||
@@ -37,6 +46,7 @@ func (m *DiskstatCollector) Init(config json.RawMessage) error {
|
|||||||
m.parallel = true
|
m.parallel = true
|
||||||
m.meta = map[string]string{"source": m.name, "group": "Disk"}
|
m.meta = map[string]string{"source": m.name, "group": "Disk"}
|
||||||
m.setup()
|
m.setup()
|
||||||
|
m.config.UseIncludeConfig = false
|
||||||
if len(config) > 0 {
|
if len(config) > 0 {
|
||||||
if err := json.Unmarshal(config, &m.config); err != nil {
|
if err := json.Unmarshal(config, &m.config); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -52,12 +62,50 @@ func (m *DiskstatCollector) Init(config json.RawMessage) error {
|
|||||||
m.allowedMetrics[excl] = false
|
m.allowedMetrics[excl] = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.Open(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
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
availDevices := make(map[string]struct{})
|
||||||
|
availMpoints := make(map[string]struct{})
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
if len(line) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
linefields := strings.Fields(line)
|
||||||
|
availDevices[linefields[0]] = struct{}{}
|
||||||
|
availMpoints[linefields[1]] = struct{}{}
|
||||||
|
}
|
||||||
|
m.includeDevices = make(map[string]bool)
|
||||||
|
for _, incl := range m.config.IncludeDevices {
|
||||||
|
if _, ok := availDevices[incl]; ok {
|
||||||
|
m.includeDevices[incl] = true
|
||||||
|
} else {
|
||||||
|
cclog.ComponentWarn(m.name, "Included Mount device ", incl, " does not exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.includeMountpoints = make(map[string]bool)
|
||||||
|
for _, incl := range m.config.IncludeMountpoints {
|
||||||
|
if _, ok := availMpoints[incl]; ok {
|
||||||
|
m.includeMountpoints[incl] = true
|
||||||
|
} else {
|
||||||
|
cclog.ComponentWarn(m.name, "Included Mount point ", incl, " does not exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.excludeMountpoints = make(map[string]bool)
|
||||||
|
for _, excl := range m.config.ExcludeMountpoints {
|
||||||
|
m.excludeMountpoints[excl] = true
|
||||||
|
}
|
||||||
|
m.excludeDevices = make(map[string]bool)
|
||||||
|
for _, excl := range m.config.ExcludeDevices {
|
||||||
|
m.excludeDevices[excl] = true
|
||||||
|
}
|
||||||
|
|
||||||
m.init = true
|
m.init = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -75,6 +123,8 @@ func (m *DiskstatCollector) Read(interval time.Duration, output chan lp.CCMessag
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
part_max_used := uint64(0)
|
part_max_used := uint64(0)
|
||||||
|
part_max_used_device := ""
|
||||||
|
part_max_used_mountpoint := ""
|
||||||
scanner := bufio.NewScanner(file)
|
scanner := bufio.NewScanner(file)
|
||||||
mountLoop:
|
mountLoop:
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
@@ -82,9 +132,9 @@ mountLoop:
|
|||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !strings.HasPrefix(line, "/dev") {
|
// if !strings.HasPrefix(line, "/dev") {
|
||||||
continue
|
// continue
|
||||||
}
|
// }
|
||||||
linefields := strings.Fields(line)
|
linefields := strings.Fields(line)
|
||||||
if strings.Contains(linefields[0], "loop") {
|
if strings.Contains(linefields[0], "loop") {
|
||||||
continue
|
continue
|
||||||
@@ -95,8 +145,16 @@ mountLoop:
|
|||||||
|
|
||||||
mountPath := strings.Replace(linefields[1], `\040`, " ", -1)
|
mountPath := strings.Replace(linefields[1], `\040`, " ", -1)
|
||||||
|
|
||||||
for _, excl := range m.config.ExcludeMounts {
|
if m.config.UseIncludeConfig {
|
||||||
if strings.Contains(mountPath, excl) {
|
_, ok1 := m.includeDevices[linefields[0]]
|
||||||
|
_, ok2 := m.includeMountpoints[linefields[1]]
|
||||||
|
if !(ok1 || ok2) {
|
||||||
|
continue mountLoop
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, ok1 := m.excludeDevices[linefields[0]]
|
||||||
|
_, ok2 := m.excludeMountpoints[linefields[1]]
|
||||||
|
if ok1 || ok2 {
|
||||||
continue mountLoop
|
continue mountLoop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,7 +167,10 @@ mountLoop:
|
|||||||
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", "stype": "filesystem", "stype-id": linefields[0]}
|
||||||
|
if m.config.UseMountpoint {
|
||||||
|
tags["stype-id"] = linefields[1]
|
||||||
|
}
|
||||||
total := (stat.Blocks * uint64(stat.Bsize)) / uint64(1000000000)
|
total := (stat.Blocks * uint64(stat.Bsize)) / uint64(1000000000)
|
||||||
if m.allowedMetrics["disk_total"] {
|
if m.allowedMetrics["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())
|
||||||
@@ -130,11 +191,17 @@ mountLoop:
|
|||||||
perc := (100 * (total - free)) / total
|
perc := (100 * (total - free)) / total
|
||||||
if perc > part_max_used {
|
if perc > part_max_used {
|
||||||
part_max_used = perc
|
part_max_used = perc
|
||||||
|
part_max_used_mountpoint = linefields[1]
|
||||||
|
part_max_used_device = linefields[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m.allowedMetrics["part_max_used"] {
|
if m.allowedMetrics["part_max_used"] && len(part_max_used_mountpoint) > 0 {
|
||||||
y, err := lp.NewMessage("part_max_used", map[string]string{"type": "node"}, m.meta, map[string]interface{}{"value": int(part_max_used)}, time.Now())
|
tags := map[string]string{"type": "node", "stype": "filesystem", "stype-id": part_max_used_device}
|
||||||
|
if m.config.UseMountpoint {
|
||||||
|
tags["stype-id"] = part_max_used_mountpoint
|
||||||
|
}
|
||||||
|
y, err := lp.NewMessage("part_max_used", tags, 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
|
||||||
|
|||||||
@@ -16,19 +16,38 @@ hugo_path: docs/reference/cc-metric-collector/collectors/diskstat.md
|
|||||||
"exclude_metrics": [
|
"exclude_metrics": [
|
||||||
"disk_total"
|
"disk_total"
|
||||||
],
|
],
|
||||||
"exclude_mounts": [
|
"exclude_devices": [
|
||||||
"slurm-tmpfs"
|
"slurm-tmpfs"
|
||||||
|
],
|
||||||
|
"exclude_mountpoints": [
|
||||||
|
"/tmp"
|
||||||
|
],
|
||||||
|
"mountpoint_as_stype": true,
|
||||||
|
"use_include_config": false,
|
||||||
|
"include_devices": [
|
||||||
|
"/dev/sda3"
|
||||||
|
],
|
||||||
|
"include_mountpoints" : [
|
||||||
|
"/home"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
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. Additionally, any mount point containing one of the strings specified in `exclude_mounts` will be skipped during metric collection.
|
The `diskstat` collector reads data from `/proc/self/mounts` and outputs a handful **node** metrics with `stype=filesystem,stype-id=<mountdevice>`. If a metric is not required, it can be excluded from forwarding it to the sink.
|
||||||
|
|
||||||
Metrics per device (with `device` tag):
|
For sending the `mountpoint` instead of the `mountdevice` in the `stype-id`, use `mountpoint_as_stype`.
|
||||||
|
|
||||||
|
There are two ways to specify for which devices or mountpoints the collector generates metrics. It's "either ...or".
|
||||||
|
- Excluding devices and mount points using `exclude_devices` and `exclude_mountpoints`. All devices (*) will be read that are not explicitly excluded
|
||||||
|
- Include devices and mount points by setting `use_include_config:true` and using `include_devices` and `include_mountpoints`.
|
||||||
|
|
||||||
|
(*) File systems where the mount device (first column in `/proc/self/mounts`) contains `loop` are always excluded. Filesystems where the mount point (second column in `/proc/self/mounts`) contains `boot` are also always excluded.
|
||||||
|
|
||||||
|
Metrics per filesystem (with `stype=filesystem` tag and `stype-id` based on the configuration):
|
||||||
* `disk_total` (unit `GBytes`)
|
* `disk_total` (unit `GBytes`)
|
||||||
* `disk_free` (unit `GBytes`)
|
* `disk_free` (unit `GBytes`)
|
||||||
|
|
||||||
Global metrics:
|
Global metrics (with `stype=filesystem` tag and `stype-id` pointing to the max. used filesystem device or mount point based on the configuration):
|
||||||
* `part_max_used` (unit `percent`)
|
* `part_max_used` (unit `percent`)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user