Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 78 additions & 68 deletions cmd/scheduler/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,48 +71,51 @@ func (cc ClusterManagerCollector) Describe(ch chan<- *prometheus.Desc) {
// Collect creates constant metrics for each host on the fly based on the returned data.
func (cc ClusterManagerCollector) Collect(ch chan<- prometheus.Metric) {
klog.V(3).Info("Starting to collect metrics for scheduler")
if cc.ClusterManager == nil || cc.metricsProvider == nil {
return
}
legacy := cc.ClusterManager.LegacyMetrics

// New metric descriptors
nodevGPUMemoryLimitDesc := prometheus.NewDesc(
"hami_gpu_memory_limit_bytes",
"Device memory limit for a certain GPU",
[]string{"node", "device_uuid", "device_index", "device_type"}, nil,
[]string{"node_name", "device_uuid", "device_index", "device_type"}, nil,
)
nodevGPUCoreLimitDesc := prometheus.NewDesc(
"hami_gpu_core_limit_ratio",
"Device core limit for a certain GPU",
[]string{"node", "device_uuid", "device_index", "device_type"}, nil,
[]string{"node_name", "device_uuid", "device_index", "device_type"}, nil,
)
nodevGPUMemoryAllocatedDesc := prometheus.NewDesc(
"hami_gpu_memory_allocated_bytes",
"Device memory allocated for a certain GPU",
[]string{"node", "device_uuid", "device_index", "device_cores", "device_type"}, nil,
[]string{"node_name", "device_uuid", "device_index", "device_cores", "device_type"}, nil,
)
nodevGPUSharedNumDesc := prometheus.NewDesc(
"hami_gpu_shared_count",
"Number of containers sharing this GPU",
[]string{"node", "device_uuid", "device_index", "device_type"}, nil,
[]string{"node_name", "device_uuid", "device_index", "device_type"}, nil,
)
nodeGPUCoreAllocatedDesc := prometheus.NewDesc(
"hami_gpu_core_allocated_ratio",
"Device core allocated for a certain GPU",
[]string{"node", "device_uuid", "device_index", "device_type"}, nil,
[]string{"node_name", "device_uuid", "device_index", "device_type"}, nil,
)
nodeGPUOverview := prometheus.NewDesc(
"hami_node_gpu_overview",
"GPU overview on a certain node",
[]string{"node", "device_uuid", "device_index", "device_cores", "device_memory_limit", "device_type"}, nil,
[]string{"node_name", "device_uuid", "device_index", "device_cores", "shared_containers", "device_memory_limit", "device_type"}, nil,
)
nodeGPUMemoryPercentage := prometheus.NewDesc(
"hami_node_gpu_memory_allocated_ratio",
"GPU Memory Allocated Percentage on a certain GPU",
[]string{"node", "device_uuid", "device_index"}, nil,
[]string{"node_name", "device_uuid", "device_index"}, nil,
)
nodeGPUMigInstance := prometheus.NewDesc(
"hami_node_gpu_mig_instance_info",
"GPU Sharing mode. 0 for hami-core, 1 for mig, 2 for mps",
[]string{"node", "device_uuid", "device_index", "mig_name"}, nil,
[]string{"node_name", "device_uuid", "device_index", "mig_name"}, nil,
)

// Legacy metric descriptors (only created when legacy mode is enabled)
Expand Down Expand Up @@ -188,6 +191,9 @@ func (cc ClusterManagerCollector) Collect(ch chan<- prometheus.Metric) {
}

nu := cc.metricsProvider.InspectAllNodesUsage()
if nu == nil {
return
}
for nodeID, val := range *nu {
for _, devs := range val.Devices.DeviceLists {
coreLimit, coreAllocated := normalizeAMDCoreMetrics(devs.Device.Type, devs.Device.Totalcore, devs.Device.Usedcores)
Expand Down Expand Up @@ -249,7 +255,7 @@ func (cc ClusterManagerCollector) Collect(ch chan<- prometheus.Metric) {
nodeGPUOverview,
prometheus.GaugeValue,
float64(devs.Device.Usedmem)*float64(1024)*float64(1024),
nodeID, devs.Device.ID, fmt.Sprint(devs.Device.Index), fmt.Sprint(devs.Device.Totalcore), fmt.Sprint(devs.Device.Totalmem), devs.Device.Type,
nodeID, devs.Device.ID, fmt.Sprint(devs.Device.Index), fmt.Sprint(devs.Device.Totalcore), fmt.Sprint(devs.Device.Used), fmt.Sprint(devs.Device.Totalmem), devs.Device.Type,
)

if devs.Device.Totalmem > 0 {
Expand Down Expand Up @@ -313,95 +319,99 @@ func (cc ClusterManagerCollector) Collect(ch chan<- prometheus.Metric) {
ctrvGPUdeviceAllocatedMemoryDesc := prometheus.NewDesc(
"hami_vgpu_memory_allocated_bytes",
"vGPU memory allocated from a container",
[]string{"namespace", "node", "pod", "container_index", "device_uuid"}, nil,
[]string{"namespace", "node_name", "pod", "container_index", "device_uuid"}, nil,
)
ctrvGPUdeviceAllocatedCoreDesc := prometheus.NewDesc(
"hami_vgpu_core_allocated_ratio",
"vGPU core allocated from a container",
[]string{"namespace", "node", "pod", "container_index", "device_uuid"}, nil,
[]string{"namespace", "node_name", "pod", "container_index", "device_uuid"}, nil,
)
quotaUsedDesc := prometheus.NewDesc(
"hami_resource_quota_used",
"resourcequota usage for a certain device",
[]string{"namespace", "quota_name", "limit"}, nil,
)
for ns, val := range cc.metricsProvider.GetQuotaManager().GetResourceQuota() {
for quotaname, q := range *val {
ch <- prometheus.MustNewConstMetric(
quotaUsedDesc,
prometheus.GaugeValue,
float64(q.Used),
ns, quotaname, fmt.Sprint(q.Limit),
)
if legacy {
if cc.metricsProvider.GetQuotaManager() != nil {
for ns, val := range cc.metricsProvider.GetQuotaManager().GetResourceQuota() {
for quotaname, q := range *val {
ch <- prometheus.MustNewConstMetric(
legacyQuotaUsed,
quotaUsedDesc,
prometheus.GaugeValue,
float64(q.Used),
ns, quotaname, fmt.Sprint(q.Limit),
)
if legacy {
ch <- prometheus.MustNewConstMetric(
legacyQuotaUsed,
prometheus.GaugeValue,
float64(q.Used),
ns, quotaname, fmt.Sprint(q.Limit),
)
}
}
}
}
schedpods, _ := cc.metricsProvider.GetPodManager().GetScheduledPods()
for _, val := range schedpods {
for _, podSingleDevice := range val.Devices {
for ctridx, ctrdevs := range podSingleDevice {
for _, ctrdevval := range ctrdevs {
klog.V(4).InfoS("Collecting metrics",
"namespace", val.Namespace,
"podName", val.Name,
"deviceUUID", ctrdevval.UUID,
"usedCores", ctrdevval.Usedcores,
"usedMem", ctrdevval.Usedmem,
"nodeID", val.NodeID,
)
if len(ctrdevval.UUID) == 0 {
klog.Warningf("Device UUID is empty, omitting metric collection for namespace=%s, podName=%s, ctridx=%d, nodeID=%s",
val.Namespace, val.Name, ctridx, val.NodeID)
continue
}
ch <- prometheus.MustNewConstMetric(
ctrvGPUdeviceAllocatedMemoryDesc,
prometheus.GaugeValue,
float64(ctrdevval.Usedmem)*float64(1024)*float64(1024),
val.Namespace, val.NodeID, val.Name, fmt.Sprint(ctridx), ctrdevval.UUID)
ch <- prometheus.MustNewConstMetric(
ctrvGPUdeviceAllocatedCoreDesc,
prometheus.GaugeValue,
float64(ctrdevval.Usedcores),
val.Namespace, val.NodeID, val.Name, fmt.Sprint(ctridx), ctrdevval.UUID)
if legacy {
if cc.metricsProvider.GetPodManager() != nil {
schedpods, _ := cc.metricsProvider.GetPodManager().GetScheduledPods()
for _, val := range schedpods {
for _, podSingleDevice := range val.Devices {
for ctridx, ctrdevs := range podSingleDevice {
for _, ctrdevval := range ctrdevs {
klog.V(4).InfoS("Collecting metrics",
"namespace", val.Namespace,
"podName", val.Name,
"deviceUUID", ctrdevval.UUID,
"usedCores", ctrdevval.Usedcores,
"usedMem", ctrdevval.Usedmem,
"nodeID", val.NodeID,
)
if len(ctrdevval.UUID) == 0 {
klog.Warningf("Device UUID is empty, omitting metric collection for namespace=%s, podName=%s, ctridx=%d, nodeID=%s",
val.Namespace, val.Name, ctridx, val.NodeID)
continue
}
ch <- prometheus.MustNewConstMetric(
legacyAllocatedMemory,
ctrvGPUdeviceAllocatedMemoryDesc,
prometheus.GaugeValue,
float64(ctrdevval.Usedmem)*float64(1024)*float64(1024),
val.Namespace, val.NodeID, val.Name, fmt.Sprint(ctridx), ctrdevval.UUID)
ch <- prometheus.MustNewConstMetric(
legacyAllocatedCore,
ctrvGPUdeviceAllocatedCoreDesc,
prometheus.GaugeValue,
float64(ctrdevval.Usedcores),
val.Namespace, val.NodeID, val.Name, fmt.Sprint(ctridx), ctrdevval.UUID)
}
var totaldev int32
found := false
for _, ni := range *nu {
for _, nodedev := range ni.Devices.DeviceLists {
if strings.Compare(nodedev.Device.ID, ctrdevval.UUID) == 0 {
totaldev = nodedev.Device.Totalmem
found = true
if legacy {
ch <- prometheus.MustNewConstMetric(
legacyAllocatedMemory,
prometheus.GaugeValue,
float64(ctrdevval.Usedmem)*float64(1024)*float64(1024),
val.Namespace, val.NodeID, val.Name, fmt.Sprint(ctridx), ctrdevval.UUID)
ch <- prometheus.MustNewConstMetric(
legacyAllocatedCore,
prometheus.GaugeValue,
float64(ctrdevval.Usedcores),
val.Namespace, val.NodeID, val.Name, fmt.Sprint(ctridx), ctrdevval.UUID)
}
var totaldev int32
found := false
for _, ni := range *nu {
for _, nodedev := range ni.Devices.DeviceLists {
if strings.Compare(nodedev.Device.ID, ctrdevval.UUID) == 0 {
totaldev = nodedev.Device.Totalmem
found = true
break
}
}
if found {
break
}
}
if found {
break
}
klog.V(4).InfoS("Total memory for device",
"deviceUUID", ctrdevval.UUID,
"totalMemory", totaldev,
"nodeID", val.NodeID,
)
}
klog.V(4).InfoS("Total memory for device",
"deviceUUID", ctrdevval.UUID,
"totalMemory", totaldev,
"nodeID", val.NodeID,
)
}
}
}
Expand Down
101 changes: 97 additions & 4 deletions cmd/scheduler/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"strings"
"testing"

"github.com/prometheus/client_golang/prometheus"
promtestutil "github.com/prometheus/client_golang/prometheus/testutil"

"github.com/Project-HAMi/HAMi/pkg/device"
Expand Down Expand Up @@ -97,12 +98,12 @@ func TestClusterManagerCollectorSkipsMemoryRatioWithNonPositiveTotalMemory(t *te
want := `
# HELP hami_gpu_core_limit_ratio Device core limit for a certain GPU
# TYPE hami_gpu_core_limit_ratio gauge
hami_gpu_core_limit_ratio{device_index="0",device_type="AWSNeuron",device_uuid="zero-memory",node="node-1"} 2
hami_gpu_core_limit_ratio{device_index="1",device_type="test-device",device_uuid="negative-memory",node="node-1"} 2
hami_gpu_core_limit_ratio{device_index="2",device_type="NVIDIA",device_uuid="normal-memory",node="node-1"} 2
hami_gpu_core_limit_ratio{device_index="0",device_type="AWSNeuron",device_uuid="zero-memory",node_name="node-1"} 2
hami_gpu_core_limit_ratio{device_index="1",device_type="test-device",device_uuid="negative-memory",node_name="node-1"} 2
hami_gpu_core_limit_ratio{device_index="2",device_type="NVIDIA",device_uuid="normal-memory",node_name="node-1"} 2
# HELP hami_node_gpu_memory_allocated_ratio GPU Memory Allocated Percentage on a certain GPU
# TYPE hami_node_gpu_memory_allocated_ratio gauge
hami_node_gpu_memory_allocated_ratio{device_index="2",device_uuid="normal-memory",node="node-1"} 0.25
hami_node_gpu_memory_allocated_ratio{device_index="2",device_uuid="normal-memory",node_name="node-1"} 0.25
# HELP nodeGPUMemoryPercentage GPU Memory Allocated Percentage on a certain GPU
# TYPE nodeGPUMemoryPercentage gauge
nodeGPUMemoryPercentage{deviceidx="2",deviceuuid="normal-memory",nodeid="node-1"} 0.25
Expand All @@ -118,3 +119,95 @@ nodeGPUMemoryPercentage{deviceidx="2",deviceuuid="normal-memory",nodeid="node-1"
t.Fatalf("unexpected collecting result:\n%s", err)
}
}

func newFakeMetricsProvider() *fakeSchedulerMetricsProvider {
nodeUsage := map[string]*schedulerpkg.NodeUsage{
"node-1": {
Devices: policy.DeviceUsageList{
DeviceLists: []*policy.DeviceListsScore{
{
Device: &device.DeviceUsage{
ID: "dev-1",
Index: 0,
Totalmem: 1024,
Totalcore: 100,
Type: "NVIDIA",
},
},
},
},
},
}
return &fakeSchedulerMetricsProvider{
nodeUsage: nodeUsage,
quotaManager: device.NewQuotaManager(),
podManager: device.NewPodManager(),
}
}

func TestSchedulerMetricDescriptors(t *testing.T) {
cm := &ClusterManager{
Zone: "test-zone",
LegacyMetrics: false,
}
collector := ClusterManagerCollector{
ClusterManager: cm,
metricsProvider: newFakeMetricsProvider(),
}

ch := make(chan *prometheus.Desc, 50)
collector.Describe(ch)
close(ch)

foundDescriptors := 0
for desc := range ch {
foundDescriptors++
descStr := desc.String()
// Ensure standard GPU descriptors (excluding namespace-scoped quota metrics) contain node_name and do not contain old 'node'
if strings.Contains(descStr, "fqName: \"hami_") && !strings.Contains(descStr, "hami_resource_quota_used") {
if !strings.Contains(descStr, "node_name") {
t.Errorf("standard descriptor %s does not contain node_name label", descStr)
}
if strings.Contains(descStr, "variableLabels: [node ") || strings.Contains(descStr, "variableLabels: [node,") {
t.Errorf("standard descriptor %s still contains old 'node' label", descStr)
Comment on lines +171 to +172

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify the resolved client_golang version and Desc.String() representation.
rg -n -C2 'github.com/prometheus/client_golang' go.mod go.sum
curl -fsSL https://raw.githubusercontent.com/prometheus/client_golang/v1.24.1/prometheus/desc.go |
  rg -n -A10 'func \(d \*Desc\) String'

Repository: Project-HAMi/HAMi

Length of output: 1880


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the metric descriptor output format and test predicates without running repository code.
FILE="cmd/scheduler/metrics_test.go"
if [ -f "$FILE" ]; then
  echo "== file lines 120-225 =="
  cat -n "$FILE" | sed -n '120,225p'
fi

echo "== relevant Prometheus Desc.String format examples =="
python3 - <<'PY'
# Directly model Prometheus github.com/prometheus/client_golang v1.24.1 Desc.String() variableLabels formatting.
# The implementation appends names with fmt.Sprintf("%s=%q", name, ...) joined by ", ".
def variable_labels_str(names):
    return ", ".join(f'{{name={n!r}}}' for n in names)

cases = [
    [],
    ["node"],
    ["node_name"],
    ["node_name", "node"],
    ["node", "node_name"],
    ["node", "other"],
]
for names in cases:
    s = f"Desc(dname=\"dname\", fqName: \"fqName\", help: \"\", variableLabels: {variable_labels_str(names)}, constLabelPairs: []constLabelPair, err: )"
    print("names=", names)
    print("contains_variableLabels: [node ", "variableLabels: [node " in s)
    print("contains_variableLabels: [node,", "variableLabels: [node," in s)
    print("contains_variableLabels: {node}", "variableLabels: " in s and "{node}" in s)
    print("contains node boundaries", any(tok in s for tok in ['{node}', ',node,']))
    print("contains exact node_name node substring", "node_name" in s and "node" in s)
    print()
PY

echo "== all occurrences of the old-label predicate =="
rg -n "variableLabels: \\[node" cmd/scheduler/metrics_test.go

Repository: Project-HAMi/HAMi

Length of output: 5117


🌐 Web query:

prometheus client_golang v1.24.1 Desc String variableLabels names

💡 Result:

In Prometheus client_golang v1.24.1, the Desc struct manages metric descriptors, which include both constant and variable labels. The internal field responsible for storing the names of variable labels is named variableLabels [1][2]. Specifically, the Desc struct maintains a variableLabels field, which is a structure containing a names slice (a []string) [1][2]. When NewDesc is called, the provided variable label names are stored within this structure [1]. The String method of the Desc struct provides a string representation of the descriptor [2]. When displaying variable labels, this method iterates through d.variableLabels.names to format them [2]. If a variable label has an associated constraint (such as a custom validation or normalization function), the String method prefixes the label name with c to indicate that the label is constrained (e.g., c(label_name)) [3][2]. Otherwise, it simply lists the label name [2]. In summary, the variable label names are stored in the names slice within the variableLabels field of the Desc struct, and this field is accessed by the String method to generate a human-readable representation of the metric's descriptor [2].

Citations:


🌐 Web query:

site:github.com/prometheus/client_golang "func (d *Desc) String" variableLabels names fmt.Sprintf

💡 Result:

The code snippet func (d *Desc) String() string { ... } refers to the String() method of the prometheus.Desc struct within the official Prometheus Go client library (prometheus/client_golang) [1][2]. This method generates a string representation of the descriptor for debugging or logging purposes [1][3]. It utilizes fmt.Sprintf to format the descriptor's fields, including its fully qualified name (fqName), help text, constant labels, and variable labels [1]. Key aspects of its implementation include: 1. Constant Labels: It iterates over d.constLabelPairs and formats each as key=value using fmt.Sprintf("%s=%q", ...) [1][2]. 2. Variable Labels: It iterates over the names stored within d.variableLabels (specifically d.variableLabels.names) [1][2]. If a label is constrained, it denotes this by wrapping the name in c(...) [1]. 3. Safety: Modern versions of the client library include a nil check for d.variableLabels before accessing its names field to prevent a nil-pointer dereference, a fix introduced following issues where NewInvalidDesc resulted in variableLabels being nil [1][2][4]. Example output of this method looks like: Desc{fqName: "net_node_up", help: "Is node up...", constLabels: {}, variableLabels: [node]} [3]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import urllib.request
url = "https://raw.githubusercontent.com/prometheus/client_golang/v1.24.1/prometheus/desc.go"
text = urllib.request.urlopen(url).read().decode()
start = text.find('func (d *Desc) String()')
end = text.find('\nfunc ', start + 1)
print(text[start:end if end != -1 else len(text)])
PY

echo "== raw URL source around variableLabels formatting =="
python3 - <<'PY'
import urllib.request
text = urllib.request.urlopen("https://raw.githubusercontent.com/prometheus/client_golang/v1.24.1/prometheus/desc.go").read().decode()
for i, line in enumerate(text.splitlines(), 1):
    if 'variableLabels' in line or 'names' in line:
        print(f"{i}: {line}")
PY

Repository: Project-HAMi/HAMi

Length of output: 2441


🏁 Script executed:

#!/bin/bash
set -euo pipefail

GOCACHE="$(go env GOCACHE 2>/dev/null || true)"
echo "GOCACHE=$GOCACHE"

find "$GOCACHE" \
  -path '*prometheus/client_golang@v1.24.1/prometheus/desc.go' \
  -type f 2>/dev/null | while read -r f; do
    echo "== $f =="
    sed -n '200,235p' "$f"
done

echo "== local module cache occurrences across downloaded tags =="
find "$GOCACHE" \
  -path '*/prometheus/client_golang@*/prometheus/desc.go' \
  -type f 2>/dev/null | while read -r f; do
    echo "-- $f --"
    rg -n 'variableLabels:|variableLabels\.names|variableLabels: \{' "$f" || true
done

echo "== deterministic model comparison =="
# Use the exact formatting from the v1.24.1 source snippet if it uses {name}.
declare -a inputs=("node" "node_name" "node_name,node" "node,node_name" "node,other")
for labels in "${inputs[@]}"; do
  s="Desc{fqName: \"hami_x\", help: \"\", variableLabels: {$labels}, constLabels: {}, constLabelPairs: []constLabelPair, err: }"
  echo "labels=$labels"
  echo "  contains variableLabels: [node space -> ${s#*(contains variableLabels: [node space -> *false, skipped)}"; if echo "$s" | grep -q 'variableLabels: \[node '; then echo "  bracket-space true"; else echo "  bracket-space false"; fi
  echo "  contains variableLabels: [node comma -> "; if echo "$s" | grep -q 'variableLabels: \[node,'; then echo "true"; else echo "false"; fi; echo
done

Repository: Project-HAMi/HAMi

Length of output: 194


Correct the old-label matcher.

prometheus.Desc.String() formats variableLabels with braces, so both current variableLabels: [...] predicates are false. Match node as a complete label in the brace-delimited list so these tests can catch descriptors containing both node_name and the obsolete node label. Apply the same update at both predicate locations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/scheduler/metrics_test.go` around lines 171 - 172, Update both old-label
matcher predicates in the descriptor validation test to match Prometheus’s
brace-delimited variableLabels format and detect node as a complete label, while
avoiding partial matches such as node_name. Keep the existing error behavior
unchanged.

}
}
}

if foundDescriptors == 0 {
t.Error("expected at least 1 descriptor from scheduler collector")
}
}
Comment on lines +148 to +180

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add a collected-metric assertion for shared_containers.

TestSchedulerMetricDescriptors validates descriptors only. It does not verify that hami_node_gpu_overview emits the new shared_containers label with DeviceUsage.Used.

Set Used to a non-zero value in newFakeMetricsProvider. Then use promtestutil.CollectAndCompare for hami_node_gpu_overview. Assert the shared_containers label value. This protects the new scheduler-to-vGPUmonitor join contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/scheduler/metrics_test.go` around lines 148 - 180, Extend
TestSchedulerMetricDescriptors with a collected-metric assertion for
hami_node_gpu_overview using promtestutil. Configure newFakeMetricsProvider to
return a non-zero DeviceUsage.Used value, collect and compare the metric, and
verify the emitted shared_containers label contains that value while preserving
the existing descriptor checks.


func TestSchedulerMetricDescriptorsLegacyMode(t *testing.T) {
cm := &ClusterManager{
Zone: "test-zone",
LegacyMetrics: true,
}
collector := ClusterManagerCollector{
ClusterManager: cm,
metricsProvider: newFakeMetricsProvider(),
}

ch := make(chan *prometheus.Desc, 50)
collector.Describe(ch)
close(ch)

foundDescriptors := 0
for desc := range ch {
foundDescriptors++
descStr := desc.String()
if strings.Contains(descStr, "fqName: \"hami_") && !strings.Contains(descStr, "hami_resource_quota_used") {
if !strings.Contains(descStr, "node_name") {
t.Errorf("standard descriptor %s does not contain node_name label", descStr)
}
if strings.Contains(descStr, "variableLabels: [node ") || strings.Contains(descStr, "variableLabels: [node,") {
t.Errorf("standard descriptor %s still contains old 'node' label", descStr)
}
}
}

if foundDescriptors == 0 {
t.Error("expected at least 1 descriptor from scheduler collector in legacy mode")
}
}
Loading