From 174ce01e7e2bebd72762b5456d1f6d1f02fb2560 Mon Sep 17 00:00:00 2001 From: yaroslavborbat Date: Tue, 24 Sep 2024 00:09:53 +0300 Subject: [PATCH] add Signed-off-by: yaroslavborbat --- .../pkg/monitoring/metrics/metrics.go | 19 +++ .../pkg/monitoring/metrics/util/dynamic.go | 91 +++++++++++++++ .../pkg/monitoring/metrics/util/labels.go | 80 +++++++++++++ .../monitoring/metrics/util/labels_test.go | 51 ++++++++ .../metrics/virtualmachine/collector.go | 27 +++-- .../metrics/virtualmachine/data_metric.go | 28 ++++- .../metrics/virtualmachine/metrics.go | 66 ++++++++--- .../metrics/virtualmachine/scraper.go | 109 ++++++++++++------ 8 files changed, 402 insertions(+), 69 deletions(-) create mode 100644 images/virtualization-artifact/pkg/monitoring/metrics/util/dynamic.go create mode 100644 images/virtualization-artifact/pkg/monitoring/metrics/util/labels.go create mode 100644 images/virtualization-artifact/pkg/monitoring/metrics/util/labels_test.go diff --git a/images/virtualization-artifact/pkg/monitoring/metrics/metrics.go b/images/virtualization-artifact/pkg/monitoring/metrics/metrics.go index 44c865f6e..f2db92079 100644 --- a/images/virtualization-artifact/pkg/monitoring/metrics/metrics.go +++ b/images/virtualization-artifact/pkg/monitoring/metrics/metrics.go @@ -16,6 +16,25 @@ limitations under the License. package metrics +import "github.com/prometheus/client_golang/prometheus" + const ( MetricNamespace = "d8_virtualization" ) + +type MetricInfo struct { + Desc *prometheus.Desc + Type prometheus.ValueType +} + +// +nolint: unparam +func NewMetricInfo(metricName, help string, t prometheus.ValueType, labels []string, constLabels prometheus.Labels) MetricInfo { + return MetricInfo{ + Desc: prometheus.NewDesc( + prometheus.BuildFQName(MetricNamespace, "", metricName), + help, + labels, + constLabels), + Type: t, + } +} diff --git a/images/virtualization-artifact/pkg/monitoring/metrics/util/dynamic.go b/images/virtualization-artifact/pkg/monitoring/metrics/util/dynamic.go new file mode 100644 index 000000000..509520ac9 --- /dev/null +++ b/images/virtualization-artifact/pkg/monitoring/metrics/util/dynamic.go @@ -0,0 +1,91 @@ +/* +Copyright 2024 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "fmt" + + "github.com/gogo/protobuf/proto" + "github.com/prometheus/client_golang/prometheus" + dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/types/known/timestamppb" +) + +type dynamicMetric struct { + desc *prometheus.Desc + metric *dto.Metric +} + +func (m dynamicMetric) Desc() *prometheus.Desc { + return m.desc +} + +func (m dynamicMetric) Write(out *dto.Metric) error { + out.Label = m.metric.Label + out.Counter = m.metric.Counter + out.Gauge = m.metric.Gauge + out.Untyped = m.metric.Untyped + return nil +} + +func NewDynamicMetric(desc *prometheus.Desc, valueType prometheus.ValueType, value float64, labelValues []string, extraLabels prometheus.Labels) (prometheus.Metric, error) { + metric := &dto.Metric{} + if err := populateMetric(valueType, value, makeLabelPairs(desc, labelValues, extraLabels), nil, metric, nil); err != nil { + return nil, err + } + + return &dynamicMetric{ + desc: desc, + metric: metric, + }, nil +} + +func makeLabelPairs(desc *prometheus.Desc, labelValues []string, extraLabels prometheus.Labels) []*dto.LabelPair { + pairs := prometheus.MakeLabelPairs(desc, labelValues) + if extraLabels == nil { + return pairs + } + for k, v := range extraLabels { + pairs = append(pairs, &dto.LabelPair{ + Name: proto.String(k), + Value: proto.String(v), + }) + } + return pairs +} + +func populateMetric( + t prometheus.ValueType, + v float64, + labelPairs []*dto.LabelPair, + e *dto.Exemplar, + m *dto.Metric, + ct *timestamppb.Timestamp, +) error { + m.Label = labelPairs + switch t { + case prometheus.CounterValue: + m.Counter = &dto.Counter{Value: proto.Float64(v), Exemplar: e, CreatedTimestamp: ct} + case prometheus.GaugeValue: + m.Gauge = &dto.Gauge{Value: proto.Float64(v)} + case prometheus.UntypedValue: + m.Untyped = &dto.Untyped{Value: proto.Float64(v)} + default: + return fmt.Errorf("encountered unknown type %v", t) + } + return nil +} diff --git a/images/virtualization-artifact/pkg/monitoring/metrics/util/labels.go b/images/virtualization-artifact/pkg/monitoring/metrics/util/labels.go new file mode 100644 index 000000000..2b6d5abd9 --- /dev/null +++ b/images/virtualization-artifact/pkg/monitoring/metrics/util/labels.go @@ -0,0 +1,80 @@ +/* +Copyright 2024 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "fmt" + "regexp" + "strings" +) + +var ( + invalidLabelCharRE = regexp.MustCompile(`[^a-zA-Z0-9_]`) + matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])") +) + +type SkipLabel func(key, value string) bool + +func WrapPrometheusLabels(labels map[string]string, prefix string, skip SkipLabel) map[string]string { + wrapLabels := make(map[string]string, len(labels)) + conflicts := make(map[string]int, len(labels)) + + for k, v := range labels { + if skip != nil && skip(k, v) { + continue + } + labelKey := labelName(prefix, k) + if conflictCount, ok := conflicts[labelKey]; ok { + if conflictCount == 1 { + // this is the first conflict for the label, + // so we have to go back and rename the initial label that we've already added + + value := wrapLabels[labelKey] + delete(wrapLabels, labelKey) + wrapLabels[labelConflictSuffix(labelKey, conflictCount)] = value + } + conflicts[labelKey]++ + labelKey = labelConflictSuffix(labelKey, conflicts[labelKey]) + } else { + conflicts[labelKey] = 1 + } + + wrapLabels[labelKey] = v + } + return wrapLabels +} + +func labelName(prefix, labelName string) string { + return prefix + "_" + lintLabelName(SanitizeLabelName(labelName)) +} + +func SanitizeLabelName(s string) string { + return invalidLabelCharRE.ReplaceAllString(s, "_") +} + +func lintLabelName(s string) string { + return toSnakeCase(s) +} + +func toSnakeCase(s string) string { + snake := matchAllCap.ReplaceAllString(s, "${1}_${2}") + return strings.ToLower(snake) +} + +func labelConflictSuffix(label string, count int) string { + return fmt.Sprintf("%s_conflict%d", label, count) +} diff --git a/images/virtualization-artifact/pkg/monitoring/metrics/util/labels_test.go b/images/virtualization-artifact/pkg/monitoring/metrics/util/labels_test.go new file mode 100644 index 000000000..9f4165959 --- /dev/null +++ b/images/virtualization-artifact/pkg/monitoring/metrics/util/labels_test.go @@ -0,0 +1,51 @@ +/* +Copyright 2024 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestWrapPrometheusLabels(t *testing.T) { + tests := []struct { + name string + labels map[string]string + expected map[string]string + }{ + { + name: "should resolve conflicted labels", + labels: map[string]string{ + "key-1": "value1", + "key_1": "value1", + "key-2": "value2", + }, + expected: map[string]string{ + "label_key_1_conflict1": "value1", + "label_key_1_conflict2": "value1", + "label_key_2": "value2", + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + wrapped := WrapPrometheusLabels(test.labels, "label", nil) + require.Equal(t, test.expected, wrapped) + }) + } +} diff --git a/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/collector.go b/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/collector.go index 46281f521..63ae8e97e 100644 --- a/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/collector.go +++ b/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/collector.go @@ -32,14 +32,9 @@ const collectorName = "virtualmachine-collector" func SetupCollector(reader client.Reader, registerer prometheus.Registerer, log *slog.Logger, -) *Collector { - c := &Collector{ - iterator: newUnsafeIterator(reader), - log: log.With(logger.SlogCollector(collectorName)), - } - - registerer.MustRegister(c) - return c +) { + c := NewCollector(reader, log) + c.Register(registerer) } type handler func(m *dataMetric) (stop bool) @@ -48,14 +43,25 @@ type Iterator interface { Iter(ctx context.Context, h handler) error } +func NewCollector(reader client.Reader, log *slog.Logger) *Collector { + return &Collector{ + iterator: newUnsafeIterator(reader), + log: log.With(logger.SlogCollector(collectorName)), + } +} + type Collector struct { iterator Iterator log *slog.Logger } +func (c Collector) Register(reg prometheus.Registerer) { + reg.MustRegister(c) +} + func (c Collector) Describe(ch chan<- *prometheus.Desc) { - for _, v := range virtualMachineMetrics { - ch <- v + for _, m := range virtualMachineMetrics { + ch <- m.Desc } } @@ -68,6 +74,5 @@ func (c Collector) Collect(ch chan<- prometheus.Metric) { return }); err != nil { c.log.Error("Failed to iterate of VirtualMachines", logger.SlogErr(err)) - return } } diff --git a/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/data_metric.go b/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/data_metric.go index 773126841..693970f35 100644 --- a/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/data_metric.go +++ b/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/data_metric.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "github.com/deckhouse/virtualization-controller/pkg/controller/service" + "github.com/deckhouse/virtualization-controller/pkg/monitoring/metrics/util" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" "github.com/deckhouse/virtualization/api/core/v1alpha2/vmcondition" ) @@ -33,16 +34,19 @@ type dataMetric struct { Node string UID string Phase virtv2.MachinePhase + CpuConfigurationCores float64 + CpuConfigurationCoreFraction float64 CpuCores float64 CpuCoreFraction float64 - CpuRequestedCores float64 CpuRuntimeOverhead float64 - MemorySize float64 + MemoryConfigurationSize float64 MemoryRuntimeOverhead float64 AwaitingRestartToApplyConfiguration bool ConfigurationApplied bool RunPolicy virtv2.RunPolicy Pods []virtv2.VirtualMachinePod + Labels map[string]string + Annotations map[string]string } // DO NOT mutate VirtualMachine! @@ -51,7 +55,9 @@ func newDataMetric(vm *virtv2.VirtualMachine) *dataMetric { return nil } res := vm.Status.Resources - cf := intstr.FromString(strings.TrimSuffix(res.CPU.CoreFraction, "%")) + cf := getPercent(res.CPU.CoreFraction) + cfSpec := getPercent(vm.Spec.CPU.CoreFraction) + var ( awaitingRestartToApplyConfiguration bool configurationApplied bool @@ -68,21 +74,33 @@ func newDataMetric(vm *virtv2.VirtualMachine) *dataMetric { for i, pod := range vm.Status.VirtualMachinePods { pods[i] = *pod.DeepCopy() } + return &dataMetric{ Name: vm.Name, Namespace: vm.Namespace, Node: vm.Status.Node, UID: string(vm.UID), Phase: vm.Status.Phase, + CpuConfigurationCores: float64(vm.Spec.CPU.Cores), + CpuConfigurationCoreFraction: float64(cfSpec.IntValue()), CpuCores: float64(res.CPU.Cores), CpuCoreFraction: float64(cf.IntValue()), - CpuRequestedCores: float64(res.CPU.RequestedCores.MilliValue()), CpuRuntimeOverhead: float64(res.CPU.RuntimeOverhead.MilliValue()), - MemorySize: float64(res.Memory.Size.Value()), + MemoryConfigurationSize: float64(vm.Spec.Memory.Size.Value()), MemoryRuntimeOverhead: float64(res.Memory.RuntimeOverhead.Value()), AwaitingRestartToApplyConfiguration: awaitingRestartToApplyConfiguration, ConfigurationApplied: configurationApplied, RunPolicy: vm.Spec.RunPolicy, Pods: pods, + Labels: util.WrapPrometheusLabels(vm.GetLabels(), "label", func(key, value string) bool { + return false + }), + Annotations: util.WrapPrometheusLabels(vm.GetAnnotations(), "annotation", func(key, _ string) bool { + return strings.HasPrefix(key, "kubectl.kubernetes.io") + }), } } + +func getPercent(s string) intstr.IntOrString { + return intstr.FromString(strings.TrimSuffix(s, "%")) +} diff --git a/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/metrics.go b/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/metrics.go index a777c6e3e..a1c75fde3 100644 --- a/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/metrics.go +++ b/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/metrics.go @@ -24,16 +24,19 @@ import ( const ( MetricVirtualMachineStatusPhase = "virtualmachine_status_phase" + MetricVirtualMachineCpuCores = "virtualmachine_cpu_cores" MetricVirtualMachineConfigurationCpuCores = "virtualmachine_configuration_cpu_cores" + MetricVirtualMachineCpuCoreFraction = "virtualmachine_cpu_core_fraction" MetricVirtualMachineConfigurationCpuCoreFraction = "virtualmachine_configuration_cpu_core_fraction" - MetricVirtualMachineConfigurationCpuRequestedCores = "virtualmachine_configuration_cpu_requested_cores" MetricVirtualMachineConfigurationCpuRuntimeOverhead = "virtualmachine_configuration_cpu_runtime_overhead" - MetricVirtualMachineConfigurationMemorySize = "virtualmachine_configuration_memory_size" + MetricVirtualMachineConfigurationMemorySizeBytes = "virtualmachine_configuration_memory_size_bytes" MetricVirtualMachineConfigurationMemoryRuntimeOverhead = "virtualmachine_configuration_memory_runtime_overhead" MetricVirtualMachineAwaitingRestartToApplyConfiguration = "virtualmachine_awaiting_restart_to_apply_configuration" MetricVirtualMachineConfigurationApplied = "virtualmachine_configuration_applied" MetricVirtualMachineConfigurationRunPolicy = "virtualmachine_configuration_run_policy" MetricVirtualMachinePod = "virtualmachine_pod" + MetricVirtualMachineLabels = "virtualmachine_labels" + MetricVirtualMachineAnnotations = "virtualmachine_annotations" ) var baseLabels = []string{"name", "namespace", "uid", "node"} @@ -55,69 +58,102 @@ func WithBaseLabelsByMetric(m *dataMetric, labels ...string) []string { return append(base, labels...) } -var virtualMachineMetrics = map[string]*prometheus.Desc{ - MetricVirtualMachineStatusPhase: prometheus.NewDesc(prometheus.BuildFQName(metrics.MetricNamespace, "", MetricVirtualMachineStatusPhase), +var virtualMachineMetrics = map[string]metrics.MetricInfo{ + MetricVirtualMachineStatusPhase: metrics.NewMetricInfo(MetricVirtualMachineStatusPhase, "The virtualmachine current phase.", + prometheus.GaugeValue, WithBaseLabels("phase"), nil, ), - MetricVirtualMachineConfigurationCpuCores: prometheus.NewDesc(prometheus.BuildFQName(metrics.MetricNamespace, "", MetricVirtualMachineConfigurationCpuCores), + MetricVirtualMachineCpuCores: metrics.NewMetricInfo(MetricVirtualMachineCpuCores, "The virtualmachine current core count.", + prometheus.GaugeValue, WithBaseLabels(), nil, ), - MetricVirtualMachineConfigurationCpuCoreFraction: prometheus.NewDesc(prometheus.BuildFQName(metrics.MetricNamespace, "", MetricVirtualMachineConfigurationCpuCoreFraction), + MetricVirtualMachineConfigurationCpuCores: metrics.NewMetricInfo(MetricVirtualMachineConfigurationCpuCores, + "The virtualmachine desired core count from the spec.", + prometheus.GaugeValue, + WithBaseLabels(), + nil, + ), + + MetricVirtualMachineCpuCoreFraction: metrics.NewMetricInfo(MetricVirtualMachineCpuCoreFraction, "The virtualmachine current coreFraction.", + prometheus.GaugeValue, WithBaseLabels(), nil, ), - MetricVirtualMachineConfigurationCpuRequestedCores: prometheus.NewDesc(prometheus.BuildFQName(metrics.MetricNamespace, "", MetricVirtualMachineConfigurationCpuRequestedCores), - "The virtualmachine current requested cores.", + MetricVirtualMachineConfigurationCpuCoreFraction: metrics.NewMetricInfo(MetricVirtualMachineConfigurationCpuCoreFraction, + "The virtualmachine desired coreFraction from the spec.", + prometheus.GaugeValue, WithBaseLabels(), nil, ), - MetricVirtualMachineConfigurationCpuRuntimeOverhead: prometheus.NewDesc(prometheus.BuildFQName(metrics.MetricNamespace, "", MetricVirtualMachineConfigurationCpuRuntimeOverhead), + MetricVirtualMachineConfigurationCpuRuntimeOverhead: metrics.NewMetricInfo(MetricVirtualMachineConfigurationCpuRuntimeOverhead, "The virtualmachine current cpu runtime overhead.", + prometheus.GaugeValue, WithBaseLabels(), nil, ), - MetricVirtualMachineConfigurationMemorySize: prometheus.NewDesc(prometheus.BuildFQName(metrics.MetricNamespace, "", MetricVirtualMachineConfigurationMemorySize), + MetricVirtualMachineConfigurationMemorySizeBytes: metrics.NewMetricInfo(MetricVirtualMachineConfigurationMemorySizeBytes, "The virtualmachine current memory size.", + prometheus.GaugeValue, WithBaseLabels(), nil, ), - MetricVirtualMachineConfigurationMemoryRuntimeOverhead: prometheus.NewDesc(prometheus.BuildFQName(metrics.MetricNamespace, "", MetricVirtualMachineConfigurationMemoryRuntimeOverhead), + MetricVirtualMachineConfigurationMemoryRuntimeOverhead: metrics.NewMetricInfo(MetricVirtualMachineConfigurationMemoryRuntimeOverhead, "The virtualmachine current memory runtime overhead.", + prometheus.GaugeValue, WithBaseLabels(), nil, ), - MetricVirtualMachineAwaitingRestartToApplyConfiguration: prometheus.NewDesc(prometheus.BuildFQName(metrics.MetricNamespace, "", MetricVirtualMachineAwaitingRestartToApplyConfiguration), + MetricVirtualMachineAwaitingRestartToApplyConfiguration: metrics.NewMetricInfo(MetricVirtualMachineAwaitingRestartToApplyConfiguration, "The virtualmachine awaiting restart to apply configuration.", + prometheus.GaugeValue, WithBaseLabels(), nil, ), - MetricVirtualMachineConfigurationApplied: prometheus.NewDesc(prometheus.BuildFQName(metrics.MetricNamespace, "", MetricVirtualMachineConfigurationApplied), + MetricVirtualMachineConfigurationApplied: metrics.NewMetricInfo(MetricVirtualMachineConfigurationApplied, "The virtualmachine configuration applied.", + prometheus.GaugeValue, WithBaseLabels(), nil, ), - MetricVirtualMachineConfigurationRunPolicy: prometheus.NewDesc(prometheus.BuildFQName(metrics.MetricNamespace, "", MetricVirtualMachineConfigurationRunPolicy), + MetricVirtualMachineConfigurationRunPolicy: metrics.NewMetricInfo(MetricVirtualMachineConfigurationRunPolicy, "The virtualmachine current runPolicy.", + prometheus.GaugeValue, WithBaseLabels("runPolicy"), nil, ), - MetricVirtualMachinePod: prometheus.NewDesc(prometheus.BuildFQName(metrics.MetricNamespace, "", MetricVirtualMachinePod), + + MetricVirtualMachinePod: metrics.NewMetricInfo(MetricVirtualMachinePod, "The virtualmachine current active pod.", + prometheus.GaugeValue, WithBaseLabels("pod"), nil, ), + + MetricVirtualMachineLabels: metrics.NewMetricInfo(MetricVirtualMachineLabels, + "Kubernetes labels converted to Prometheus labels.", + prometheus.GaugeValue, + WithBaseLabels(), + nil, + ), + + MetricVirtualMachineAnnotations: metrics.NewMetricInfo(MetricVirtualMachineAnnotations, + "Kubernetes annotations converted to Prometheus labels.", + prometheus.GaugeValue, + WithBaseLabels(), + nil, + ), } diff --git a/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/scraper.go b/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/scraper.go index 8e1d03c70..6cd6665a6 100644 --- a/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/scraper.go +++ b/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/scraper.go @@ -22,6 +22,7 @@ import ( "github.com/prometheus/client_golang/prometheus" + metricutil "github.com/deckhouse/virtualization-controller/pkg/monitoring/metrics/util" "github.com/deckhouse/virtualization-controller/pkg/util" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" ) @@ -36,20 +37,23 @@ type scraper struct { } func (s *scraper) Report(m *dataMetric) { - s.updateVMStatusPhaseMetrics(m) - s.updateVMCpuCoresMetrics(m) - s.updateVMCpuCoreFractionMetrics(m) - s.updateVMCpuRequestedCoresMetrics(m) - s.updateVMCpuRuntimeOverheadMetrics(m) - s.updateVMMemorySizeMetrics(m) - s.updateVMMemoryRuntimeOverheadMetrics(m) - s.updateVMAwaitingRestartToApplyConfigurationMetrics(m) - s.updateVMConfigurationAppliedMetrics(m) - s.updateVMConfigurationRunPolicyMetrics(m) - s.updateVMPodMetrics(m) -} - -func (s *scraper) updateVMStatusPhaseMetrics(m *dataMetric) { + s.updateMetricVirtualMachineStatusPhase(m) + s.updateMetricVirtualMachineCpuCores(m) + s.updateMetricVirtualMachineConfigurationCpuCores(m) + s.updateMetricVirtualMachineCpuCoreFraction(m) + s.updateMetricVirtualMachineConfigurationCpuCoreFraction(m) + s.updateMetricVirtualMachineConfigurationCpuRuntimeOverhead(m) + s.updateMetricVirtualMachineConfigurationMemoryRuntimeOverhead(m) + s.updateMetricVirtualMachineConfigurationMemorySizeBytes(m) + s.updateMetricVirtualMachineAwaitingRestartToApplyConfiguration(m) + s.updateMetricVirtualMachineConfigurationApplied(m) + s.updateMetricVirtualMachineConfigurationRunPolicy(m) + s.updateMetricVirtualMachinePod(m) + s.updateMetricVirtualMachineLabels(m) + s.updateMetricVirtualMachineAnnotations(m) +} + +func (s *scraper) updateMetricVirtualMachineStatusPhase(m *dataMetric) { phase := m.Phase if phase == "" { phase = virtv2.MachinePending @@ -74,47 +78,52 @@ func (s *scraper) updateVMStatusPhaseMetrics(m *dataMetric) { } } -func (s *scraper) updateVMCpuCoresMetrics(m *dataMetric) { - s.defaultUpdate(MetricVirtualMachineConfigurationCpuCores, +func (s *scraper) updateMetricVirtualMachineCpuCores(m *dataMetric) { + s.defaultUpdate(MetricVirtualMachineCpuCores, m.CpuCores, m) } -func (s *scraper) updateVMCpuCoreFractionMetrics(m *dataMetric) { - s.defaultUpdate(MetricVirtualMachineConfigurationCpuCoreFraction, +func (s *scraper) updateMetricVirtualMachineConfigurationCpuCores(m *dataMetric) { + s.defaultUpdate(MetricVirtualMachineConfigurationCpuCores, + m.CpuConfigurationCores, m) +} + +func (s *scraper) updateMetricVirtualMachineCpuCoreFraction(m *dataMetric) { + s.defaultUpdate(MetricVirtualMachineCpuCoreFraction, m.CpuCoreFraction, m) } -func (s *scraper) updateVMCpuRequestedCoresMetrics(m *dataMetric) { - s.defaultUpdate(MetricVirtualMachineConfigurationCpuRequestedCores, - m.CpuRequestedCores, m) +func (s *scraper) updateMetricVirtualMachineConfigurationCpuCoreFraction(m *dataMetric) { + s.defaultUpdate(MetricVirtualMachineConfigurationCpuCoreFraction, + m.CpuConfigurationCoreFraction, m) } -func (s *scraper) updateVMCpuRuntimeOverheadMetrics(m *dataMetric) { +func (s *scraper) updateMetricVirtualMachineConfigurationCpuRuntimeOverhead(m *dataMetric) { s.defaultUpdate(MetricVirtualMachineConfigurationCpuRuntimeOverhead, m.CpuRuntimeOverhead, m) } -func (s *scraper) updateVMMemorySizeMetrics(m *dataMetric) { - s.defaultUpdate(MetricVirtualMachineConfigurationMemorySize, - m.MemorySize, m) -} - -func (s *scraper) updateVMMemoryRuntimeOverheadMetrics(m *dataMetric) { +func (s *scraper) updateMetricVirtualMachineConfigurationMemoryRuntimeOverhead(m *dataMetric) { s.defaultUpdate(MetricVirtualMachineConfigurationMemoryRuntimeOverhead, m.MemoryRuntimeOverhead, m) } -func (s *scraper) updateVMAwaitingRestartToApplyConfigurationMetrics(m *dataMetric) { +func (s *scraper) updateMetricVirtualMachineConfigurationMemorySizeBytes(m *dataMetric) { + s.defaultUpdate(MetricVirtualMachineConfigurationMemorySizeBytes, + m.MemoryConfigurationSize, m) +} + +func (s *scraper) updateMetricVirtualMachineAwaitingRestartToApplyConfiguration(m *dataMetric) { s.defaultUpdate(MetricVirtualMachineAwaitingRestartToApplyConfiguration, util.BoolFloat64(m.AwaitingRestartToApplyConfiguration), m) } -func (s *scraper) updateVMConfigurationAppliedMetrics(m *dataMetric) { +func (s *scraper) updateMetricVirtualMachineConfigurationApplied(m *dataMetric) { s.defaultUpdate(MetricVirtualMachineConfigurationApplied, util.BoolFloat64(m.ConfigurationApplied), m) } -func (s *scraper) updateVMConfigurationRunPolicyMetrics(m *dataMetric) { +func (s *scraper) updateMetricVirtualMachineConfigurationRunPolicy(m *dataMetric) { policy := m.RunPolicy policies := []struct { value bool @@ -131,22 +140,46 @@ func (s *scraper) updateVMConfigurationRunPolicyMetrics(m *dataMetric) { } } -func (s *scraper) updateVMPodMetrics(m *dataMetric) { +func (s *scraper) updateMetricVirtualMachinePod(m *dataMetric) { for _, p := range m.Pods { s.defaultUpdate(MetricVirtualMachinePod, util.BoolFloat64(p.Active), m, p.Name) } } -func (s *scraper) defaultUpdate(descName string, value float64, m *dataMetric, labels ...string) { - desc := virtualMachineMetrics[descName] +func (s *scraper) updateMetricVirtualMachineLabels(m *dataMetric) { + s.updateDynamic(MetricVirtualMachineLabels, 1, m, nil, m.Labels) +} + +func (s *scraper) updateMetricVirtualMachineAnnotations(m *dataMetric) { + s.updateDynamic(MetricVirtualMachineAnnotations, 1, m, nil, m.Annotations) +} + +func (s *scraper) defaultUpdate(name string, value float64, m *dataMetric, labelValues ...string) { + info := virtualMachineMetrics[name] metric, err := prometheus.NewConstMetric( - desc, - prometheus.GaugeValue, + info.Desc, + info.Type, + value, + WithBaseLabelsByMetric(m, labelValues...)..., + ) + if err != nil { + s.log.Warn(fmt.Sprintf("Error creating the new const dataMetric for %s: %s", info.Desc, err)) + return + } + s.ch <- metric +} + +func (s *scraper) updateDynamic(name string, value float64, m *dataMetric, labelValues []string, extraLabels prometheus.Labels) { + info := virtualMachineMetrics[name] + metric, err := metricutil.NewDynamicMetric( + info.Desc, + info.Type, value, - WithBaseLabelsByMetric(m, labels...)..., + WithBaseLabelsByMetric(m, labelValues...), + extraLabels, ) if err != nil { - s.log.Warn(fmt.Sprintf("Error creating the new const dataMetric for %s: %s", desc, err)) + s.log.Warn(fmt.Sprintf("Error creating the new dynamic dataMetric for %s: %s", info.Desc, err)) return } s.ch <- metric