diff --git a/docs/metrics.md b/docs/metrics.md index a37bbd1a36e2..e9b748fae9d0 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -1,16 +1,4 @@ - - # KubeVirt metrics -This document aims to help users that are not familiar with all metrics exposed by different KubeVirt components. -All metrics documented here are auto-generated by the utility tool `tools/doc-generator` and reflects exactly what is being exposed. - -## KubeVirt Metrics List -### kubevirt_info -Version information. ### kubevirt_allocatable_nodes The number of allocatable nodes in the cluster. Type: Gauge. @@ -24,6 +12,9 @@ Indicates whether the Software Emulation is enabled in the configuration. Type: ### kubevirt_console_active_connections Amount of active Console connections, broken down by namespace and vmi name. Type: Gauge. +### kubevirt_info +Version information. Type: Gauge. + ### kubevirt_memory_delta_from_requested_bytes The delta between the pod with highest memory working set or rss and its requested memory for each container, virt-controller, virt-handler, virt-api and virt-operator. Type: Gauge. @@ -145,7 +136,7 @@ The total amount of memory written out to swap space of the guest in bytes. Type The amount of memory left completely unused by the system. Memory that is available but used for reclaimable caches should NOT be reported as free. Type: Gauge. ### kubevirt_vmi_memory_usable_bytes -The amount of memory which can be reclaimed by balloon without pushing the guest system to swap, corresponds to 'Available' in /proc/meminfo Type: Gauge. +The amount of memory which can be reclaimed by balloon without pushing the guest system to swap, corresponds to 'Available' in /proc/meminfo. Type: Gauge. ### kubevirt_vmi_memory_used_bytes Amount of `used` memory as seen by the domain. Type: Gauge. @@ -193,7 +184,7 @@ The total number of rx packets dropped on vNIC interfaces. Type: Counter. Total network traffic received packets. Type: Counter. ### kubevirt_vmi_network_traffic_bytes_total -Deprecated. Type: Counter. +[Deprecated] Total number of bytes sent and received. Type: Counter. ### kubevirt_vmi_network_transmit_bytes_total Total network traffic transmitted in bytes. Type: Counter. @@ -283,6 +274,7 @@ Request latency in seconds. Broken down by verb and URL. Type: Histogram. Number of HTTP requests, partitioned by status code, method, and host. Type: Counter. ## Developing new metrics -After developing new metrics or changing old ones, please run `make generate` to regenerate this document. -If you feel that the new metric doesn't follow these rules, please change `doc-generator` with your needs. +All metrics documented here are auto-generated and reflect exactly what is being +exposed. After developing new metrics or changing old ones please regenerate +this document. diff --git a/hack/generate.sh b/hack/generate.sh index 710b0b35fc37..30e822a83e73 100755 --- a/hack/generate.sh +++ b/hack/generate.sh @@ -140,8 +140,7 @@ ${KUBEVIRT_DIR}/tools/openapispec/openapispec --dump-api-spec-path ${KUBEVIRT_DI (cd ${KUBEVIRT_DIR}/tools/doc-generator/ && go_build) ( cd ${KUBEVIRT_DIR}/docs - ${KUBEVIRT_DIR}/tools/doc-generator/doc-generator - mv newmetrics.md metrics.md + ${KUBEVIRT_DIR}/tools/doc-generator/doc-generator >metrics.md ) rm -f ${KUBEVIRT_DIR}/manifests/generated/* diff --git a/tools/doc-generator/BUILD.bazel b/tools/doc-generator/BUILD.bazel index 2bc5961a7da1..7bf72f091258 100644 --- a/tools/doc-generator/BUILD.bazel +++ b/tools/doc-generator/BUILD.bazel @@ -2,27 +2,17 @@ load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") go_library( name = "go_default_library", - srcs = [ - "doc-generator.go", - "fakeDomainCollector.go", - ], + srcs = ["doc-generator.go"], importpath = "kubevirt.io/kubevirt/tools/doc-generator", visibility = ["//visibility:private"], deps = [ - "//pkg/monitoring/domainstats/prometheus:go_default_library", "//pkg/monitoring/metrics/virt-api:go_default_library", "//pkg/monitoring/metrics/virt-controller:go_default_library", "//pkg/monitoring/metrics/virt-handler:go_default_library", "//pkg/monitoring/metrics/virt-operator:go_default_library", "//pkg/monitoring/rules:go_default_library", - "//pkg/virt-controller/watch:go_default_library", - "//pkg/virt-launcher/virtwrap/stats:go_default_library", - "//pkg/virt-launcher/virtwrap/statsconv:go_default_library", - "//pkg/virt-launcher/virtwrap/statsconv/util:go_default_library", - "//staging/src/kubevirt.io/api/core/v1:go_default_library", + "//vendor/github.com/machadovilaca/operator-observability/pkg/docs:go_default_library", "//vendor/github.com/machadovilaca/operator-observability/pkg/operatormetrics:go_default_library", - "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", - "//vendor/libvirt.org/go/libvirt:go_default_library", ], ) diff --git a/tools/doc-generator/doc-generator.go b/tools/doc-generator/doc-generator.go index 4b95e6602d1b..ebd50ef6eb4b 100644 --- a/tools/doc-generator/doc-generator.go +++ b/tools/doc-generator/doc-generator.go @@ -1,265 +1,69 @@ package main import ( - "bufio" "fmt" - "io" - "net/http" - "net/http/httptest" - "os" - "sort" - "strings" "github.com/machadovilaca/operator-observability/pkg/operatormetrics" - domainstats "kubevirt.io/kubevirt/pkg/monitoring/domainstats/prometheus" // import for prometheus metrics - virt_api "kubevirt.io/kubevirt/pkg/monitoring/metrics/virt-api" - virt_controller "kubevirt.io/kubevirt/pkg/monitoring/metrics/virt-controller" - virt_handler "kubevirt.io/kubevirt/pkg/monitoring/metrics/virt-handler" - virt_operator "kubevirt.io/kubevirt/pkg/monitoring/metrics/virt-operator" + virtapi "kubevirt.io/kubevirt/pkg/monitoring/metrics/virt-api" + virtcontroller "kubevirt.io/kubevirt/pkg/monitoring/metrics/virt-controller" + virthandler "kubevirt.io/kubevirt/pkg/monitoring/metrics/virt-handler" + virtoperator "kubevirt.io/kubevirt/pkg/monitoring/metrics/virt-operator" "kubevirt.io/kubevirt/pkg/monitoring/rules" - _ "kubevirt.io/kubevirt/pkg/virt-controller/watch" -) - -// constant parts of the file -const ( - genFileComment = `` - title = "# KubeVirt metrics\n" - background = "This document aims to help users that are not familiar with all metrics exposed by different KubeVirt components.\n" + - "All metrics documented here are auto-generated by the utility tool `tools/doc-generator` and reflects exactly what is being exposed.\n\n" - - KVSpecificMetrics = "## KubeVirt Metrics List\n" + - "### kubevirt_info\n" + - "Version information.\n\n" - - opening = genFileComment + "\n\n" + - title + - background + - KVSpecificMetrics - // footer - footerHeading = "## Developing new metrics\n" - footerContent = "After developing new metrics or changing old ones, please run `make generate` to regenerate this document.\n\n" + - "If you feel that the new metric doesn't follow these rules, please change `doc-generator` with your needs.\n" - - footer = footerHeading + footerContent + "github.com/machadovilaca/operator-observability/pkg/docs" ) -func main() { - handler := domainstats.Handler(1) - RegisterFakeDomainCollector() - - req, err := http.NewRequest(http.MethodGet, "/metrics", nil) - checkError(err) - - recorder := httptest.NewRecorder() - - handler.ServeHTTP(recorder, req) - - metrics := getMetricsNotIncludeInEndpointByDefault() - - if status := recorder.Code; status == http.StatusOK { - err := parseVirtMetrics(recorder.Body, &metrics) - checkError(err) - - } else { - panic(fmt.Errorf("got HTTP status code of %d from /metrics", recorder.Code)) - } - writeToFile(metrics) -} - -func writeToFile(metrics metricList) { - newFile, err := os.Create("newmetrics.md") - checkError(err) - defer newFile.Close() +const tpl = `# KubeVirt metrics - fmt.Fprint(newFile, opening) - metrics.writeToFile(newFile) +{{- range . }} - fmt.Fprint(newFile, footer) +{{ $deprecatedVersion := "" -}} +{{- with index .ExtraFields "DeprecatedVersion" -}} + {{- $deprecatedVersion = printf " in %s" . -}} +{{- end -}} -} - -type metric struct { - name string - description string - mType string -} - -func (m metric) writeToFile(newFile io.WriteCloser) { - fmt.Fprintln(newFile, "###", m.name) - fmt.Fprintln(newFile, m.description, "Type:", m.mType+".") - fmt.Fprintln(newFile) -} - -type metricList []metric +{{- $stabilityLevel := "" -}} +{{- if and (.ExtraFields.StabilityLevel) (ne .ExtraFields.StabilityLevel "STABLE") -}} + {{- $stabilityLevel = printf "[%s%s] " .ExtraFields.StabilityLevel $deprecatedVersion -}} +{{- end -}} -// Len implements sort.Interface.Len -func (m metricList) Len() int { - return len(m) -} +### {{ .Name }} +{{ print $stabilityLevel }}{{ .Help }} Type: {{ .Type -}}. -// Less implements sort.Interface.Less -func (m metricList) Less(i, j int) bool { - return m[i].name < m[j].name -} - -// Swap implements sort.Interface.Swap -func (m metricList) Swap(i, j int) { - m[i], m[j] = m[j], m[i] -} - -func (m metricList) writeToFile(newFile io.WriteCloser) { - for _, met := range m { - met.writeToFile(newFile) - } -} - -func getMetricsNotIncludeInEndpointByDefault() metricList { - metrics := metricList{ - { - name: domainstats.MigrateVmiDataProcessedMetricName, - description: "The total Guest OS data processed and migrated to the new VM.", - mType: "Gauge", - }, - { - name: domainstats.MigrateVmiDataRemainingMetricName, - description: "The remaining guest OS data to be migrated to the new VM.", - mType: "Gauge", - }, - { - name: domainstats.MigrateVmiDirtyMemoryRateMetricName, - description: "The rate of memory being dirty in the Guest OS.", - mType: "Gauge", - }, - { - name: domainstats.MigrateVmiMemoryTransferRateMetricName, - description: "The rate at which the memory is being transferred.", - mType: "Gauge", - }, - { - name: "kubevirt_vmi_phase_count", - description: "Sum of VMIs per phase and node. `phase` can be one of the following: [`Pending`, `Scheduling`, `Scheduled`, `Running`, `Succeeded`, `Failed`, `Unknown`].", - mType: "Gauge", - }, - { - name: "kubevirt_vmi_non_evictable", - description: "Indication for a VirtualMachine that its eviction strategy is set to Live Migration but is not migratable.", - mType: "Gauge", - }, - } +{{- end }} - metrics = append(metrics, getVirtControllerMetrics()...) - metrics = append(metrics, getComponentMetrics(virt_api.SetupMetrics, virt_api.ListMetrics)...) - metrics = append(metrics, getComponentMetrics(virt_operator.SetupMetrics, virt_operator.ListMetrics)...) - metrics = append(metrics, getComponentMetrics(virt_handler.SetupMetrics, virt_handler.ListMetrics)...) +## Developing new metrics - err := rules.SetupRules("") - checkError(err) +All metrics documented here are auto-generated and reflect exactly what is being +exposed. After developing new metrics or changing old ones please regenerate +this document. +` - for _, rule := range rules.ListRecordingRules() { - metrics = append(metrics, metric{ - name: rule.GetOpts().Name, - description: rule.GetOpts().Help, - mType: string(rule.GetType()), - }) - } - - return metrics -} - -func getVirtControllerMetrics() metricList { - err := virt_controller.SetupMetrics(nil, nil, nil, nil, nil, nil, nil, nil) - checkError(err) - return listComponentMetrics(virt_controller.ListMetrics) -} - -func getComponentMetrics(setup func() error, list func() []operatormetrics.Metric) metricList { - err := setup() - checkError(err) - return listComponentMetrics(list) -} - -func listComponentMetrics(list func() []operatormetrics.Metric) metricList { - metrics := metricList{} - - for _, m := range list() { - metrics = append(metrics, newMetric(m)) - } - - err := operatormetrics.CleanRegistry() - checkError(err) - - return metrics -} - -func newMetric(om operatormetrics.Metric) metric { - return metric{ - name: om.GetOpts().Name, - description: om.GetOpts().Help, - mType: strings.Replace(string(om.GetType()), "Vec", "", 1), +func main() { + if err := virtcontroller.SetupMetrics(nil, nil, nil, nil, nil, nil, nil, nil); err != nil { + panic(err) } -} - -func parseMetricDesc(line string) (string, string) { - split := strings.Split(line, " ") - name := split[2] - split[3] = strings.Title(split[3]) - description := strings.Join(split[3:], " ") - return name, description -} -func parseMetricType(scan *bufio.Scanner, name string) string { - for scan.Scan() { - typeLine := scan.Text() - if strings.HasPrefix(typeLine, "# TYPE ") { - split := strings.Split(typeLine, " ") - if split[2] == name { - return strings.Title(split[3]) - } - } + if err := virtapi.SetupMetrics(); err != nil { + panic(err) } - return "" -} - -const filter = "kubevirt_" -func parseVirtMetrics(r io.Reader, metrics *metricList) error { - scan := bufio.NewScanner(r) - for scan.Scan() { - helpLine := scan.Text() - if strings.HasPrefix(helpLine, "# HELP ") { - if strings.Contains(helpLine, filter) { - metName, metDesc := parseMetricDesc(helpLine) - metType := parseMetricType(scan, metName) - *metrics = append(*metrics, metric{name: metName, description: metDesc, mType: metType}) - } - } + if err := virtoperator.SetupMetrics(); err != nil { + panic(err) } - if scan.Err() != nil { - return fmt.Errorf("failed to parse metrics from prometheus endpoint, %w", scan.Err()) + if err := virthandler.SetupMetrics("", "", 0, nil); err != nil { + panic(err) } - sort.Sort(metrics) - - // remove duplicates - for i := 0; i < len(*metrics)-1; i++ { - if (*metrics)[i].name == (*metrics)[i+1].name { - *metrics = append((*metrics)[:i], (*metrics)[i+1:]...) - i-- - } + if err := rules.SetupRules(""); err != nil { + panic(err) } - return nil -} + metricsList := operatormetrics.ListMetrics() + rulesList := rules.ListRecordingRules() -func checkError(err error) { - if err != nil { - panic(err) - } + docsString := docs.BuildMetricsDocsWithCustomTemplate(metricsList, rulesList, tpl) + fmt.Print(docsString) } diff --git a/tools/doc-generator/fakeDomainCollector.go b/tools/doc-generator/fakeDomainCollector.go deleted file mode 100644 index 391f13c95ac4..000000000000 --- a/tools/doc-generator/fakeDomainCollector.go +++ /dev/null @@ -1,91 +0,0 @@ -package main - -import ( - "github.com/prometheus/client_golang/prometheus" - "libvirt.org/go/libvirt" - - domainstats "kubevirt.io/kubevirt/pkg/monitoring/domainstats/prometheus" - - k6tv1 "kubevirt.io/api/core/v1" - - "kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/stats" - "kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/statsconv" - "kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/statsconv/util" -) - -type fakeDomainCollector struct { -} - -func (fc fakeDomainCollector) Describe(_ chan<- *prometheus.Desc) { -} - -// Collect needs to report all metrics to see it in docs -func (fc fakeDomainCollector) Collect(ch chan<- prometheus.Metric) { - ps := domainstats.NewPrometheusScraper(ch) - - libstatst, err := util.LoadStats() - if err != nil { - panic(err) - } - - in := &libstatst[0] - inMem := []libvirt.DomainMemoryStat{} - inDomInfo := &libvirt.DomainInfo{} - jobInfo := stats.DomainJobInfo{} - out := stats.DomainStats{} - fs := k6tv1.VirtualMachineInstanceFileSystemList{} - ident := statsconv.DomainIdentifier(&fakeDomainIdentifier{}) - devAliasMap := make(map[string]string) - - if err = statsconv.Convert_libvirt_DomainStats_to_stats_DomainStats(ident, in, inMem, inDomInfo, devAliasMap, &jobInfo, &out); err != nil { - panic(err) - } - - out.Memory.ActualBalloonSet = true - out.Memory.UnusedSet = true - out.Memory.CachedSet = true - out.Memory.AvailableSet = true - out.Memory.RSSSet = true - out.Memory.SwapInSet = true - out.Memory.SwapOutSet = true - out.Memory.UsableSet = true - out.Memory.MinorFaultSet = true - out.Memory.MajorFaultSet = true - out.CPUMapSet = true - out.Cpu.SystemSet = true - out.Cpu.UserSet = true - out.Cpu.TimeSet = true - - fs.Items = []k6tv1.VirtualMachineInstanceFileSystem{ - { - DiskName: "disk1", - MountPoint: "/", - FileSystemType: "EXT4", - TotalBytes: 1000, - UsedBytes: 10, - }, - } - - vmi := k6tv1.VirtualMachineInstance{ - Status: k6tv1.VirtualMachineInstanceStatus{ - Phase: k6tv1.Running, - NodeName: "test", - }, - } - ps.Report("test", &vmi, &domainstats.VirtualMachineInstanceStats{DomainStats: &out, FsStats: fs}) -} - -type fakeDomainIdentifier struct { -} - -func (*fakeDomainIdentifier) GetName() (string, error) { - return "test", nil -} - -func (*fakeDomainIdentifier) GetUUIDString() (string, error) { - return "uuid", nil -} - -func RegisterFakeDomainCollector() { - prometheus.MustRegister(fakeDomainCollector{}) -} diff --git a/vendor/github.com/machadovilaca/operator-observability/pkg/docs/BUILD.bazel b/vendor/github.com/machadovilaca/operator-observability/pkg/docs/BUILD.bazel new file mode 100644 index 000000000000..a3465bcd41b4 --- /dev/null +++ b/vendor/github.com/machadovilaca/operator-observability/pkg/docs/BUILD.bazel @@ -0,0 +1,17 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "alerts.go", + "metrics.go", + ], + importmap = "kubevirt.io/kubevirt/vendor/github.com/machadovilaca/operator-observability/pkg/docs", + importpath = "github.com/machadovilaca/operator-observability/pkg/docs", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/machadovilaca/operator-observability/pkg/operatormetrics:go_default_library", + "//vendor/github.com/machadovilaca/operator-observability/pkg/operatorrules:go_default_library", + "//vendor/github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1:go_default_library", + ], +) diff --git a/vendor/github.com/machadovilaca/operator-observability/pkg/docs/alerts.go b/vendor/github.com/machadovilaca/operator-observability/pkg/docs/alerts.go new file mode 100644 index 000000000000..e5d65f922532 --- /dev/null +++ b/vendor/github.com/machadovilaca/operator-observability/pkg/docs/alerts.go @@ -0,0 +1,96 @@ +package docs + +import ( + "bytes" + "log" + "sort" + "text/template" + + promv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" +) + +const defaultAlertsTemplate = `# Operator Alerts + +{{- range . }} + +### {{.Name}} +**Summary:** {{ index .Annotations "summary" }}. + +**Description:** {{ index .Annotations "description" }}. + +**Severity:** {{ index .Labels "severity" }}. +{{- if .For }} + +**For:** {{ .For }}. +{{- end -}} +{{- end }} + +## Developing new alerts + +All alerts documented here are auto-generated and reflect exactly what is being +exposed. After developing new alerts or changing old ones please regenerate +this document. +` + +type alertDocs struct { + Name string + Expr string + For string + Annotations map[string]string + Labels map[string]string +} + +// BuildAlertsDocsWithCustomTemplate returns a string with the documentation +// for the given alerts, using the given template. +func BuildAlertsDocsWithCustomTemplate( + alerts []promv1.Rule, + tplString string, +) string { + + tpl, err := template.New("alerts").Parse(tplString) + if err != nil { + log.Fatalln(err) + } + + var allDocs []alertDocs + + if alerts != nil { + allDocs = append(allDocs, buildAlertsDocs(alerts)...) + } + + buf := bytes.NewBufferString("") + err = tpl.Execute(buf, allDocs) + if err != nil { + log.Fatalln(err) + } + + return buf.String() +} + +// BuildAlertsDocs returns a string with the documentation for the given +// metrics. +func BuildAlertsDocs(alerts []promv1.Rule) string { + return BuildAlertsDocsWithCustomTemplate(alerts, defaultAlertsTemplate) +} + +func buildAlertsDocs(alerts []promv1.Rule) []alertDocs { + alertsDocs := make([]alertDocs, len(alerts)) + for i, alert := range alerts { + alertsDocs[i] = alertDocs{ + Name: alert.Alert, + Expr: alert.Expr.String(), + For: string(*alert.For), + Annotations: alert.Annotations, + Labels: alert.Labels, + } + } + sortAlertsDocs(alertsDocs) + + return alertsDocs +} + +func sortAlertsDocs(alertsDocs []alertDocs) { + sort.Slice(alertsDocs, func(i, j int) bool { + return alertsDocs[i].Name < alertsDocs[j].Name + }) +} diff --git a/vendor/github.com/machadovilaca/operator-observability/pkg/docs/metrics.go b/vendor/github.com/machadovilaca/operator-observability/pkg/docs/metrics.go new file mode 100644 index 000000000000..c61db1346467 --- /dev/null +++ b/vendor/github.com/machadovilaca/operator-observability/pkg/docs/metrics.go @@ -0,0 +1,111 @@ +package docs + +import ( + "bytes" + "log" + "sort" + "strings" + "text/template" + + "github.com/machadovilaca/operator-observability/pkg/operatormetrics" + "github.com/machadovilaca/operator-observability/pkg/operatorrules" +) + +const defaultMetricsTemplate = `# Operator Metrics + +{{- range . }} + +### {{.Name}} +{{.Help}}. + +Type: {{.Type}}. +{{- end }} + +## Developing new metrics + +All metrics documented here are auto-generated and reflect exactly what is being +exposed. After developing new metrics or changing old ones please regenerate +this document. +` + +type metricDocs struct { + Name string + Help string + Type string + ExtraFields map[string]string +} + +type docOptions interface { + GetOpts() operatormetrics.MetricOpts + GetType() operatormetrics.MetricType +} + +// BuildMetricsDocsWithCustomTemplate returns a string with the documentation +// for the given metrics, using the given template. +func BuildMetricsDocsWithCustomTemplate( + metrics []operatormetrics.Metric, + recordingRules []operatorrules.RecordingRule, + tplString string, +) string { + + tpl, err := template.New("metrics").Parse(tplString) + if err != nil { + log.Fatalln(err) + } + + var allDocs []metricDocs + + if metrics != nil { + allDocs = append(allDocs, buildMetricsDocs(metrics)...) + } + + if recordingRules != nil { + allDocs = append(allDocs, buildMetricsDocs(recordingRules)...) + } + + sortMetricsDocs(allDocs) + + buf := bytes.NewBufferString("") + err = tpl.Execute(buf, allDocs) + if err != nil { + log.Fatalln(err) + } + + return buf.String() +} + +// BuildMetricsDocs returns a string with the documentation for the given +// metrics. +func BuildMetricsDocs(metrics []operatormetrics.Metric, recordingRules []operatorrules.RecordingRule) string { + return BuildMetricsDocsWithCustomTemplate(metrics, recordingRules, defaultMetricsTemplate) +} + +func buildMetricsDocs[T docOptions](items []T) []metricDocs { + uniqueNames := make(map[string]struct{}) + var metricsDocs []metricDocs + + for _, metric := range items { + metricOpts := metric.GetOpts() + if _, exists := uniqueNames[metricOpts.Name]; !exists { + uniqueNames[metricOpts.Name] = struct{}{} + metricsDocs = append(metricsDocs, metricDocs{ + Name: metricOpts.Name, + Help: metricOpts.Help, + Type: getAndConvertMetricType(metric.GetType()), + ExtraFields: metricOpts.ExtraFields, + }) + } + } + + return metricsDocs +} + +func sortMetricsDocs(metricsDocs []metricDocs) { + sort.Slice(metricsDocs, func(i, j int) bool { + return metricsDocs[i].Name < metricsDocs[j].Name + }) +} + +func getAndConvertMetricType(metricType operatormetrics.MetricType) string { + return strings.ReplaceAll(string(metricType), "Vec", "") +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 6de8abd338f9..0bc508748e84 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -243,6 +243,7 @@ github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1 github.com/kubevirt/monitoring/pkg/metrics/parser # github.com/machadovilaca/operator-observability v0.0.19 ## explicit; go 1.21 +github.com/machadovilaca/operator-observability/pkg/docs github.com/machadovilaca/operator-observability/pkg/operatormetrics github.com/machadovilaca/operator-observability/pkg/operatorrules # github.com/mailru/easyjson v0.7.7