Schritt-für-Schritt: Weitere Metriken
!!! info "Schritt-für-Schritt · Teil 2/2" Dieses Kapitel baut direkt auf Schritt-für-Schritt: Erste Metrik auf.
Arbeiten Sie zuerst Teil 1 durch, damit alle Basisdateien und Umbenennungen vorhanden sind.
Dies ist der zweite Teil der Schritt-für-Schritt-Reihe und baut auf der ersten Metrik (cpu_load) auf.
Eine Übersicht über alle verfügbaren Collectoren gibt es unter https://github.com/ClusterCockpit/cc-metric-collector/tree/main/collectors
In den READMEs jedes Collectors werden die erhebbaren Metriken und Konfigurationsmöglichkeiten aufgezeigt.
Sofern im jeweiligen Abschnitt nichts anderes erwähnt wird, gilt scope: node.
Hinweis: In
cc-lib-Versionen bis einschließlichv0.10.1musstendrop_messages_ifundchange_unit_prefixmit den originalen Metriknamen befüllt werden. Seit der aktuellen Version gelten die umbenannten Namen (also nachrename_messages). Die Beispiele unten orientieren sich an diesem neuen Verhalten.
CPU
loadavg (Recap)
Der Collector loadavg liefert load_one, load_five, load_fifteen, proc_run und proc_total. Für ClusterCockpit genügt weiterhin load_one, das in cpu_load umbenannt wird.
collectors.json:
"loadavg": {}
router.json (Auszug):
"process_messages": {
"hostname_tag": "hostname",
"rename_messages": {
"load_one": "cpu_load"
},
"drop_messages_if": [
"!(name in ['cpu_load'])"
]
}
Die Positivliste in drop_messages_if und die rename_messages Liste wird im Laufe dieses Kapitels um weitere Metriken ergänzt. Sämtliche folgenden drop_messages_if- und change_unit_prefix-Blöcke beziehen sich weiterhin auf den Abschnitt process_messages in derselben router.json.
cpustat
cpustat zapft /proc/stat an und liefert CPU-Zeiten pro Hardware-Thread. Für das Job-Monitoring genügt cpu_user, das die Nutzerzeit je Kern anzeigt (scope: hwthread). Die Messung wird automatisch auf jeden Hardware-Thread angewendet.
collectors.json:
"cpustat": {}
router.json:
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user'])"
]
Damit cpu_user erhalten bleibt, wird es der Positivliste drop_messages_if hinzugefügt (siehe Router-Auszug oben). Weitere vom Collector gelieferte Spalten wie cpu_system oder cpu_idle werden damit verworfen.
schedstat
Der Collector schedstat liefert cpu_load_core, das die Auslastung pro Kern (scope: hwthread) zeigt und falsches Pinning sichtbar macht.
collectors.json:
"schedstat": {}
router.json:
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core'])"
]
Arbeitsspeicher
memstat
Der Collector memstat sammelt einige Metriken aus /proc/meminfo:
MemTotal: 32278500 kB
MemFree: 8472384 kB
MemAvailable: 19816380 kB
Buffers: 6656 kB
Cached: 12963688 kB
Erfasst wird mem_used (=mem_total-(mem_free + mem_buffers + mem_cached)).
Man kann konfigurieren, dass die Metriken auf Ebene der NUMA Subcluster erhoben werden (scope: memoryDomain), allerdings kann cc-backend in der Version aus dem main-Branch diese Werte nicht zuordnen.
collectors.json:
"memstat": {
"node_stats": true,
"numa_stats": true
}
router.json:
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used'])"
],
"change_unit_prefix": {
"name == 'mem_used'": "G"
}
slurm_cgroup
Der Collector slurm_cgroup liest die von Slurm angelegten cgroups aus, ermittelt daraus den Arbeitsspeicherverbrauch pro Job und verteilt den Wert auf die vom Job belegten Kerne. Dadurch entsteht eine pro Hardware-Thread (scope: hwthread) sichtbare Metrik job_mem_used, die direkt mit den CPU-Kernen eines Jobs korreliert.
collectors.json:
"slurm_cgroup": {
}
router.json:
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used', 'job_mem_used'])"
],
"change_unit_prefix": {
"name == 'job_mem_used'": "G"
}
numastats
numastats wertet /sys/devices/system/node/node*/numastat aus und liefert daraus abgeleitete Ereigniszähler pro Sekunde (count/s) für die einzelnen NUMA-Domains (scope: memoryDomain). Damit lässt sich schnell erkennen, ob Interleave-Strategien greifen oder Speicherzugriffe häufig außerhalb der lokalen NUMA-Domain stattfinden.
collectors.json:
"numastats": {
"send_abs_values": false,
"send_derived_values": true
}
router.json (Auszug):
"rename_messages": {
"numastats_interleave_hit_rate": "numastats_interleave_hit",
"numastats_local_node_rate": "numastats_local_node",
"numastats_numa_foreign_rate": "numastats_numa_foreign",
"numastats_numa_hit_rate": "numastats_numa_hit",
"numastats_numa_miss_rate": "numastats_numa_miss",
"numastats_other_node_rate": "numastats_other_node"
},
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used', 'job_mem_used', 'numastats_interleave_hit', 'numastats_local_node', 'numastats_numa_foreign', 'numastats_numa_hit', 'numastats_numa_miss', 'numastats_other_node'])"
]
Lokaler Speicher
Für stateful Knoten bieten sich zwei Collectoren an:
diskstat
Liest /proc/self/mounts aus und liefert pro Mountpunkt Festplattengröße (disk_total), freien Platz (disk_free) und Belegungsgrad (part_max_used). Dabei werden Mountpunkte mit loop und boot im Namen ignoriert. In der collectors.json können weitere zu exkludierende Mountpunkte angegeben werden, z.B. log:
"diskstat": {
"exclude_mounts": [
"log"
]
}
Erfasst wird ausschließlich disk_free.
Bei unserem Partitionslayout
/dev/nvme0n1p1 /boot/efi vfat rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=winnt,errors=remount-ro 0 0
/dev/nvme0n1p2 / xfs rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,sunit=256,swidth=256,noquota 0 0
/dev/nvme0n1p3 /var/log xfs rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,sunit=256,swidth=256,usrquota,prjquota,grpquota 0 0
/dev/nvme0n1p4 /var/slurm-tmpfs xfs rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,sunit=256,swidth=256,usrquota,prjquota,grpquota 0 0
werden noch zwei Nachrichten versendet:
disk_free,cluster=testcluster,device=/dev/nvme0n1p2,hostname=cpu001,type=node,unit=GB value=41u 1757426394108539349
disk_free,cluster=testcluster,device=/dev/nvme0n1p4,hostname=cpu001,type=node,unit=GB value=869u 1757426394108546859
Die beiden Nachrichten unterscheiden sich nur durch das device-Tag. Die Werte werden von cc-backend nicht aufsummiert. Es wird nur der Wert der ersten Nachricht verarbeitet. Da es sich um das Dateisystem "/" handelt, kann es mit exclude_mounts nicht herausgefiltert werden. Die Filterung erfolgt über den messageProcessor:
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used', 'job_mem_used', 'numastats_interleave_hit', 'numastats_local_node', 'numastats_numa_foreign', 'numastats_numa_hit', 'numastats_numa_miss', 'numastats_other_node', 'disk_free'])",
"name == 'disk_free' && tag.device != '/dev/nvme0n1p4'"
],
"change_unit_prefix": {
"name == 'disk_free'": "G"
}
Danach erhalten wir nur noch gewünschte Partition:
disk_free,cluster=testcluster,device=/dev/nvme0n1p4,hostname=cpu001,type=node,unit=GB value=869u 1757426394108546859
iostat
Liest Daten zu I/O Statistiken aus /proc/diskstats aus. Dabei werden nur die Differenzwerte zur letzen Messung gesendet. Ähnlich wie bei diskstat filtern wir nur nach der gewünschten Partition. Außerdem interessieren uns nur io_reads und io_writes:
collectors.json:
"iostat": {}
router.json:
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used', 'job_mem_used', 'numastats_interleave_hit', 'numastats_local_node', 'numastats_numa_foreign', 'numastats_numa_hit', 'numastats_numa_miss', 'numastats_other_node', 'disk_free', 'io_reads', 'io_writes'])",
"(name in ['disk_free', 'io_reads', 'io_writes']) && tag.device != '/dev/nvme0n1p4'"
],
Netzwerk
ibstat
Der Collector ibstat erfasst Link- und Traffic-Metriken für Highspeed-Interconnects unter Linux. Er funktioniert nicht nur mit InfiniBand, sondern auch mit Omni-Path, da beide ihre Geräte unter /sys/class/infiniband/<dev>/ports/<port>/... exponieren.
Standardmäßig werden absolute Zählerstände gesendet. Für eine aussagekräftige Zeitreihe benötigen wir Bandbreitenwerte, also pro Sekunde (abgeleitet aus Differenzen). Dafür schalten wir absolute Werte aus und abgeleitete Werte ein.
collectors.json:
"ibstat": {
"send_abs_values": false,
"send_derived_values": true
}
router.json:
"rename_messages": {
"ib_recv_bw": "ib_recv",
"ib_xmit_bw": "ib_xmit",
"ib_recv_pkts_bw": "ib_recv_pkts",
"ib_xmit_pkts_bw": "ib_xmit_pkts"
},
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used', 'job_mem_used', 'numastats_interleave_hit', 'numastats_local_node', 'numastats_numa_foreign', 'numastats_numa_hit', 'numastats_numa_miss', 'numastats_other_node', 'disk_free', 'io_reads', 'io_writes', 'ib_recv', 'ib_xmit', 'ib_recv_pkts', 'ib_xmit_pkts'])",
"(name in ['disk_free', 'io_reads', 'io_writes']) && tag.device != '/dev/nvme0n1p4'"
],
"change_unit_prefix": {
"name == 'ib_recv'": "M",
"name == 'ib_xmit'": "M"
}
Hinweis: Abgeleitete Werte entstehen aus zwei Messungen. Diese Metriken erscheinen nicht, wenn cc-metric-collector mit der Option -once läuft.
netstat
Der Collector netstat liefert Netzwerkmetriken für Ethernet-Interfaces. Um eine einzige Konfiguration für heterogene Knotengruppen wiederzuverwenden kann man mehrere Namen angeben.
Abgeleitete Werte werden aktiviert, damit die Bandbreiten direkt vorliegen. Der Collector liefert:
net_bytes_in_bwEinheit bytes/snet_bytes_out_bwEinheit bytes/snet_pkts_in_bwEinheit packets/snet_pkts_out_bwEinheit packets/s
collectors.json:
"netstat": {
"include_devices": [
"eth0", "eno1", "eno1no0"
],
"send_abs_values": false,
"send_derived_values": true,
}
router.json:
"rename_messages": {
"net_bytes_in_bw": "net_bytes_in",
"net_bytes_out_bw": "net_bytes_out",
"net_pkts_in_bw": "net_pkts_in",
"net_pkts_out_bw": "net_pkts_out"
},
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used', 'job_mem_used', 'numastats_interleave_hit', 'numastats_local_node', 'numastats_numa_foreign', 'numastats_numa_hit', 'numastats_numa_miss', 'numastats_other_node', 'disk_free', 'io_reads', 'io_writes', 'ib_recv', 'ib_xmit', 'ib_recv_pkts', 'ib_xmit_pkts', 'net_bytes_in', 'net_bytes_out', 'net_pkts_in', 'net_pkts_out'])",
"(name in ['disk_free', 'io_reads', 'io_writes']) && tag.device != '/dev/nvme0n1p4'"
],
"change_unit_prefix": {
"name == 'net_bytes_in'": "M",
"name == 'net_bytes_out'": "M"
}
Die zuvor definierte rename_messages-Liste sorgt dafür, dass die Bandbreitenkennzahlen als net_bytes_* bzw. net_pkts_* geführt werden.
Filesysteme
lustrestat
Der Collector lustrestat verwendet das Kommando lctl und liefert Statistiken zu Lustre-Clients. Standardmäßig werden eine Vielzahl von Countern erhoben. Für die meisten Anwendungsfälle reicht es, sich auf folgende Metriken zu konzentrieren:
lustre_read_bw(Lese-Bandbreite in bytes/sec)lustre_write_bw(Schreib-Bandbreite in bytes/sec)lustre_open(Anzahl geöffneter Dateien seit der letzten Messung)lustre_close(Anzahl geschlossener Dateien seit der letzten Messung)lustre_statfs(Differenzen ausstatfs-Aufrufen)
collectors.json:
"lustrestat": {}
router.json:
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used', 'job_mem_used', 'numastats_interleave_hit', 'numastats_local_node', 'numastats_numa_foreign', 'numastats_numa_hit', 'numastats_numa_miss', 'numastats_other_node', 'disk_free', 'io_reads', 'io_writes', 'ib_recv', 'ib_xmit', 'ib_recv_pkts', 'ib_xmit_pkts', 'net_bytes_in', 'net_bytes_out', 'net_pkts_in', 'net_pkts_out', 'lustre_read_bw', 'lustre_write_bw', 'lustre_open', 'lustre_close', 'lustre_statfs'])",
"(name in ['disk_free', 'io_reads', 'io_writes']) && tag.device != '/dev/nvme0n1p4'"
],
"change_unit_prefix": {
"name == 'lustre_read_bw'": "M",
"name == 'lustre_write_bw'": "M"
}
nfs4stat
Der Collector nfs4stat basiert auf dem Kommando nfsstat und erhebt NFSv4-Client-Counter. Im Vordergrund stehen die Dateizugriffszähler:
open_diff(Anzahl der Dateiöffnungen seit letzter Messung)close_diff(Anzahl der Dateischließungen seit letzter Messung)
collectors.json:
"nfs4stat": {}
router.json:
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used', 'job_mem_used', 'numastats_interleave_hit', 'numastats_local_node', 'numastats_numa_foreign', 'numastats_numa_hit', 'numastats_numa_miss', 'numastats_other_node', 'disk_free', 'io_reads', 'io_writes', 'ib_recv', 'ib_xmit', 'ib_recv_pkts', 'ib_xmit_pkts', 'net_bytes_in', 'net_bytes_out', 'net_pkts_in', 'net_pkts_out', 'lustre_read_bw', 'lustre_write_bw', 'lustre_open', 'lustre_close', 'lustre_statfs', 'open_diff', 'close_diff'])",
"(name in ['disk_free', 'io_reads', 'io_writes']) && tag.device != '/dev/nvme0n1p4'"
]
nfsiostat
Der Collector nfsiostat liefert detaillierte Statistiken für NFS-Mounts, ähnlich dem bekannten Kommando nfsiostat. Der Schwerpunkt liegt auf den abgeleiteten Bandbreiten:
nfsio_nread(gelesene Daten in bytes/s)nfsio_nwrite(geschriebene Daten in bytes/s)
collectors.json:
"nfsiostat": {}
router.json:
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used', 'job_mem_used', 'numastats_interleave_hit', 'numastats_local_node', 'numastats_numa_foreign', 'numastats_numa_hit', 'numastats_numa_miss', 'numastats_other_node', 'disk_free', 'io_reads', 'io_writes', 'ib_recv', 'ib_xmit', 'ib_recv_pkts', 'ib_xmit_pkts', 'net_bytes_in', 'net_bytes_out', 'net_pkts_in', 'net_pkts_out', 'lustre_read_bw', 'lustre_write_bw', 'lustre_open', 'lustre_close', 'lustre_statfs', 'open_diff', 'close_diff', 'nfsio_nread', 'nfsio_nwrite'])",
"(name in ['disk_free', 'io_reads', 'io_writes']) && tag.device != '/dev/nvme0n1p4'"
],
"change_unit_prefix": {
"name == 'nfsio_nread'": "M",
"name == 'nfsio_nwrite'": "M"
}
GPU
nvidia
Der Collector nvidia liefert zentrale GPU-Kennzahlen wie Auslastung, Speichernutzung und Leistungsaufnahme. Über optionale Flags lassen sich MIG-Geräte vereinfachen und zusätzliche Metadaten unterdrücken, damit das Datenvolumen überschaubar bleibt.
Scope: accelerator
collectors.json:
"nvidia": {
"process_mig_devices": false,
"use_pci_info_as_type_id": true,
"add_pci_info_tag": true,
"add_uuid_meta": false,
"add_board_number_meta": false,
"add_serial_meta": false,
"use_uuid_for_mig_device": false,
"use_slice_for_mig_device": false
}
router.json:
"rename_messages": {
"nv_util": "acc_utilization",
"nv_fb_mem_used": "acc_mem_used",
"nv_power_usage": "acc_power",
"nv_mem_util": "acc_mem_util"
},
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used', 'job_mem_used', 'numastats_interleave_hit', 'numastats_local_node', 'numastats_numa_foreign', 'numastats_numa_hit', 'numastats_numa_miss', 'numastats_other_node', 'disk_free', 'io_reads', 'io_writes', 'ib_recv', 'ib_xmit', 'ib_recv_pkts', 'ib_xmit_pkts', 'net_bytes_in', 'net_bytes_out', 'net_pkts_in', 'net_pkts_out', 'lustre_read_bw', 'lustre_write_bw', 'lustre_open', 'lustre_close', 'lustre_statfs', 'open_diff', 'close_diff', 'nfsio_nread', 'nfsio_nwrite', 'acc_utilization', 'acc_mem_used', 'acc_power', 'acc_mem_util', 'nv_compute_processes'])",
"(name in ['disk_free', 'io_reads', 'io_writes']) && tag.device != '/dev/nvme0n1p4'"
],
"change_unit_prefix": {
"name == 'acc_mem_used'": "G"
}
customcmd: Eigene Skripte einbinden
Wenn kein dedizierter Collector existiert, kann `customcmd` ein beliebiges Skript starten und dessen Ausgabe als Metrik übernehmen. So lassen sich individuelle Sensoren oder Spezialfälle unkompliziert einbinden. Das Skript muss lediglich ausführbar sein und die Ausgabe im passenden Format liefern. Das folgende Beispiel liest die Gesamtleistungsaufnahme eines Knotens über `ipmi-sensors` aus und sendet sie im InfluxDB Line Protocol als `node_total_power` weiter:#!/bin/bash
# Script to extract the overall node power consumption from ipmi-sensors output.
# It searches for "NODE_PWR" first, and if not found, then for "SYS_POWER".
# The extracted value is output in InfluxDB Line Protocol format:
# Measurement: node_total_power
# Tags: cluster, hostname, type, unit
# Field: value
# Timestamp: current time in nanoseconds
output=$(sudo /usr/sbin/ipmi-sensors --comma-separated-output)
# Search for "NODE_PWR" and extract the fourth field (reading)
value=$(echo "$output" | awk -F, '$2 == "NODE_PWR" {print $4; exit}')
# If "NODE_PWR" is not found, search for "SYS_POWER"
if [ -z "$value" ]; then
value=$(echo "$output" | awk -F, '$2 ~ /SYS_POWER/ {print $4; exit}')
fi
# Exit with an error if no valid power metric is found
if [ -z "$value" ]; then
echo "No valid power metric found" >&2
exit 1
fi
host=$(hostname)
timestamp=$(date +%s%N)
echo "node_total_power,cluster=elysium,hostname=${host},type=node,unit=W value=${value} ${timestamp}"
bis hierher erstellte collectors.json
{
"loadavg": {},
"cpustat": {},
"schedstat": {},
"memstat": {
"node_stats": true,
"numa_stats": true
},
"slurm_cgroup": {
"scope": "hwthread"
},
"numastats": {
"send_abs_values": false,
"send_derived_values": true
},
"diskstat": {
"exclude_mounts": [
"log"
]
},
"iostat": {},
"ibstat": {
"send_abs_values": false,
"send_derived_values": true
},
"netstat": {
"include_devices": [
"eth0",
"eno1",
"eno1no0"
],
"send_abs_values": false,
"send_derived_values": true
},
"lustrestat": {},
"nfs4stat": {},
"nfsiostat": {},
"nvidia": {
"process_mig_devices": false,
"use_pci_info_as_type_id": true,
"add_pci_info_tag": true,
"add_uuid_meta": false,
"add_board_number_meta": false,
"add_serial_meta": false,
"use_uuid_for_mig_device": false,
"use_slice_for_mig_device": false
}
}
Beispiel: bis hierher erstellte router.json
{
"add_tags": [
{
"key": "cluster",
"value": "__CLUSTER__",
"if": "*"
}
],
"interval_timestamp": false,
"num_cache_intervals": 0,
"hostname_tag": "hostname",
"normalize_units": true,
"process_messages": {
"rename_messages": {
"load_one": "cpu_load",
"net_bytes_in_bw": "net_bytes_in",
"net_bytes_out_bw": "net_bytes_out",
"net_pkts_in_bw": "net_pkts_in",
"net_pkts_out_bw": "net_pkts_out",
"ib_recv_bw": "ib_recv",
"ib_xmit_bw": "ib_xmit",
"ib_recv_pkts_bw": "ib_recv_pkts",
"ib_xmit_pkts_bw": "ib_xmit_pkts",
"lustre_open_diff": "lustre_open",
"lustre_close_diff": "lustre_close",
"lustre_statfs_diff": "lustre_statfs",
"nv_util": "acc_utilization",
"nv_fb_mem_used": "acc_mem_used",
"nv_power_usage": "acc_power",
"nv_mem_util": "acc_mem_util",
"nfsio_nread_bw": "nfsio_nread",
"nfsio_nwrite_bw": "nfsio_nwrite",
"numastats_interleave_hit_rate": "numastats_interleave_hit",
"numastats_local_node_rate": "numastats_local_node",
"numastats_numa_foreign_rate": "numastats_numa_foreign",
"numastats_numa_hit_rate": "numastats_numa_hit",
"numastats_numa_miss_rate": "numastats_numa_miss",
"numastats_other_node_rate": "numastats_other_node"
},
"drop_messages_if": [
"!(name in ['cpu_load', 'cpu_user', 'cpu_load_core', 'mem_used', 'job_mem_used', 'numastats_interleave_hit', 'numastats_local_node', 'numastats_numa_foreign', 'numastats_numa_hit', 'numastats_numa_miss', 'numastats_other_node', 'disk_free', 'io_reads', 'io_writes', 'ib_recv', 'ib_xmit', 'ib_recv_pkts', 'ib_xmit_pkts', 'net_bytes_in', 'net_bytes_out', 'net_pkts_in', 'net_pkts_out', 'lustre_read_bw', 'lustre_write_bw', 'lustre_open', 'lustre_close', 'lustre_statfs', 'open_diff', 'close_diff', 'nfsio_nread', 'nfsio_nwrite', 'acc_utilization', 'acc_mem_used', 'acc_power', 'acc_mem_util', 'nv_compute_processes'])",
"(name in ['disk_free', 'io_reads', 'io_writes']) && tag.device != '/dev/nvme0n1p4'"
],
"change_unit_prefix": {
"name == 'mem_used'": "G",
"name == 'job_mem_used'": "G",
"name == 'disk_free'": "G",
"name == 'ib_recv'": "M",
"name == 'ib_xmit'": "M",
"name == 'net_bytes_in'": "M",
"name == 'net_bytes_out'": "M",
"name == 'lustre_read_bw'": "M",
"name == 'lustre_write_bw'": "M",
"name == 'nfsio_nread'": "M",
"name == 'nfsio_nwrite'": "M",
"name == 'acc_mem_used'": "G"
}
}
}
Als letztes fehlen nur noch die LIKWID Metriken.