Skip to content

MON-1157: Test metrics for prometheus best practice#31370

Open
jan--f wants to merge 2 commits into
openshift:mainfrom
jan--f:MON-1157-promlint-best-practices
Open

MON-1157: Test metrics for prometheus best practice#31370
jan--f wants to merge 2 commits into
openshift:mainfrom
jan--f:MON-1157-promlint-best-practices

Conversation

@jan--f

@jan--f jan--f commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

This commit adds a testing for prometheus metric naming best practices with an exception list. The exception list in empty initially and should be filled in a followup. After the initial setup, the list should ideally not grow.
The test is informative for now.

Summary by CodeRabbit

  • Bug Fixes
    • Improved Prometheus metric validation so naming issues are detected and reported more clearly.
    • Expanded label consistency checks to better enforce expected camelCase label usage in metric families.
    • Added handling for known exception metrics so only actionable lint problems are surfaced.
  • Tests
    • Introduced new Prometheus utility coverage for metadata-to-metric-family conversion, camelCase label discovery, and exception formatting.

This commit adds a testing for prometheus metric naming best practices
with an exception list. The exception list in empty initially and should
be filled in a followup. After the initial setup, the list should
ideally not grow.
The test is informative for now.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jan Fajerski <jfajersk@redhat.com>
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: automatic mode

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 8, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 8, 2026

Copy link
Copy Markdown

@jan--f: This pull request references MON-1157 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

This commit adds a testing for prometheus metric naming best practices with an exception list. The exception list in empty initially and should be filled in a followup. After the initial setup, the list should ideally not grow.
The test is informative for now.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 00b21087-39fa-4610-906f-06034dd66cc1

📥 Commits

Reviewing files that changed from the base of the PR and between 23ddbba and f60e96b.

📒 Files selected for processing (3)
  • test/extended/prometheus/prometheus.go
  • test/extended/util/prometheus/metrics.go
  • test/extended/util/prometheus/metrics_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • test/extended/util/prometheus/metrics_test.go
  • test/extended/prometheus/prometheus.go
  • test/extended/util/prometheus/metrics.go

Walkthrough

This PR adds Prometheus metric-family helpers, a promlint wrapper with exception filtering, and an extended Ginkgo test that runs the naming lint over live Prometheus metadata.

Changes

Prometheus Metric Naming Lint

Layer / File(s) Summary
Metric family helpers
test/extended/util/prometheus/metrics.go
MetadataToMetricFamilies converts Prometheus metadata into dto.MetricFamily values, convertMetricType maps Prometheus types, FindCamelCaseLabels discovers metric-label usage from Prometheus, and SetCamelCaseLabels attaches label pairs to families.
Promlint wrapper and exception formatting
test/extended/util/prometheus/promlint.go
Adds Problem, a Linter wrapper that filters metrics present in exceptionMetrics, and FormatExceptionEntries for sorted, deduplicated exception-list source lines.
Extended metric naming test
test/extended/prometheus/prometheus.go, test/extended/util/prometheus/metrics_test.go
Adds the new Ginkgo metric naming check plus unit tests for metadata conversion, camelCase matching, label injection, and exception-entry formatting.

Estimated code review effort: 3 (Moderate) | ~25 minutes

🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Microshift Test Compatibility ⚠️ Warning The new Ginkgo test queries Prometheus via openshift-monitoring/prometheus-k8s with no MicroShift skip guard. Add a [Skipped:MicroShift] or apigroup tag, or guard the spec with exutil.IsMicroShiftCluster() and g.Skip().
✅ Passed checks (14 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: adding Prometheus metric best-practice tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed PASS: The new Ginkgo titles are static strings with no dynamic values or generated identifiers.
Test Structure And Quality ✅ Passed The new Ginkgo test is single-purpose, uses SpecContext and informative assertions, creates no resources, and matches existing Prometheus test patterns.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The new Ginkgo test only fetches Prometheus metadata and lints metric names; it has no node-count, scheduling, topology, or HA assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed The PR only adds/updates Prometheus test utilities and an informational Ginkgo test; no manifests, controllers, pod specs, or scheduling constraints were introduced.
Ote Binary Stdout Contract ✅ Passed No stdout writes were added in init/TestMain/suite setup; ote.Informing() only returns Ginkgo labels, and the lone fmt.Printf is inside a test-helper called from an It block.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed New metric-naming Ginkgo test only queries in-cluster Prometheus; no IPv4 literals, IP parsing, or external/public network calls found.
No-Weak-Crypto ✅ Passed Touched files are Prometheus test utilities only; scans found no crypto APIs, weak algorithms, or secret comparisons.
Container-Privileges ✅ Passed The PR only changes Go test/util files and introduces no privileged, hostPID/Network/IPC, or allowPrivilegeEscalation settings.
No-Sensitive-Data-In-Logs ✅ Passed No new logs print secrets or customer data; the added test logs only counts and metric/violation names, not raw values.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@openshift-ci openshift-ci Bot requested review from rexagod and slashpai July 8, 2026 09:36
@openshift-ci

openshift-ci Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jan--f

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
test/extended/util/prometheus/metrics.go (2)

49-56: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Guard against empty Metric slice before indexing Metric[0].

SetCamelCaseLabels assumes every family has at least one Metric entry. This holds today since MetadataToMetricFamilies always appends a single &dto.Metric{}, but the function has no defensive check of its own — if it's ever called with families built differently (or the invariant is broken in a future refactor), this will panic with an index-out-of-range.

🛡️ Proposed defensive check
 func SetCamelCaseLabels(families []*dto.MetricFamily, labelsPerMetric map[string][]*dto.LabelPair) {
 	for i, family := range families {
+		if len(families[i].Metric) == 0 {
+			continue
+		}
 		labels, ok := labelsPerMetric[family.GetName()]
 		if ok {
 			families[i].Metric[0].Label = labels
 		}
 	}
 }
🤖 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 `@test/extended/util/prometheus/metrics.go` around lines 49 - 56,
SetCamelCaseLabels currently indexes families[i].Metric[0] without verifying
that Metric contains any entries, so add a defensive guard before assigning
labels. Update the SetCamelCaseLabels function to check that the matched family
has at least one Metric element before touching Metric[0], and only set the
Label field when that slice is non-empty. Keep the existing label lookup by
family name and preserve the current behavior for valid MetricFamily values.

79-99: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

PromQL query built with raw label name; also val variable shadowing reduces readability.

Line 79 interpolates label directly into a PromQL selector via fmt.Sprintf. Since label comes from promClient.LabelNames results on the live cluster, valid Prometheus label names shouldn't break the query syntax, but this is still string-built query construction worth double-checking against the "no fmt.Sprintf in queries" guidance for query-building code.

Separately, at Lines 94-95, val := "" shadows the outer val (the model.Value from Line 80's promClient.Query call), which is confusing to read even though it's harmless here.

♻️ Suggested rename to avoid shadowing
 		for _, sample := range vector {
 			metricName := string(sample.Metric[model.MetricNameLabel])
 			if metricName == "" {
 				continue
 			}
 			lbl := label
-			val := ""
+			emptyVal := ""
 			result[metricName] = append(result[metricName], &dto.LabelPair{
 				Name:  &lbl,
-				Value: &val,
+				Value: &emptyVal,
 			})
 		}
🤖 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 `@test/extended/util/prometheus/metrics.go` around lines 79 - 99, The query
construction in the metrics helper still uses fmt.Sprintf with a raw label name,
so update the PromQL building logic around promClient.Query to avoid
string-interpolating the selector directly and follow the
no-fmt.Sprintf-in-queries guidance. Also rename the inner val string in the
sample loop to avoid shadowing the outer val from promClient.Query, making the
code in this metrics aggregation path easier to read and maintain.

Source: Path instructions

test/extended/util/prometheus/metrics_test.go (1)

11-242: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

No unit test for FindCamelCaseLabels.

All other new helpers (MetadataToMetricFamilies, camelCaseRe, SetCamelCaseLabels, FormatExceptionEntries) have table-driven tests, but FindCamelCaseLabels (which contains the query-building and result-parsing logic) is untested. A mock implementing prometheusv1.API would let you cover the camelCase filtering and label-pair construction logic without a live cluster.

🤖 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 `@test/extended/util/prometheus/metrics_test.go` around lines 11 - 242, Add
unit coverage for FindCamelCaseLabels, since its query construction and response
parsing are currently untested. Create a table-driven test around
FindCamelCaseLabels using a mock prometheusv1.API to verify it issues the
camelCase-focused query, filters only matching metrics, and builds the expected
label pairs. Keep the test alongside the existing Metrics helpers tests and
reference FindCamelCaseLabels plus the label-pair handling used by
SetCamelCaseLabels.
test/extended/util/prometheus/promlint.go (1)

27-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider embedding upstream promlint.Problem instead of redeclaring fields.

Problem duplicates promlint.Problem's Metric/Text fields via a plain struct rather than wrapping/embedding the upstream type. Functionally correct as-is (confirmed promlint.Problem has these fields), just a minor duplication given the doc comment says it "wraps" the upstream type.

🤖 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 `@test/extended/util/prometheus/promlint.go` around lines 27 - 41, Update the
local Problem type in the prometheus promlint utility to actually wrap the
upstream promlint.Problem instead of duplicating its Metric and Text fields. Use
embedding or a direct alias-style wrapper so the existing String method and any
callers still work with the upstream type, and keep the Linter wrapper
unchanged.
🤖 Prompt for all review comments with 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.

Inline comments:
In `@test/extended/util/prometheus/metrics_test.go`:
- Line 169: Update the misleading test comment in the Prometheus metrics tests
so it matches the actual regex behavior: in the `metrics_test.go` case for
`myHTTPHandler`, the `[a-z][A-Z]` match is the `yH` transition, not `PH`. Keep
the assertion as-is and only correct the inline explanation near the
`myHTTPHandler` test case.

---

Nitpick comments:
In `@test/extended/util/prometheus/metrics_test.go`:
- Around line 11-242: Add unit coverage for FindCamelCaseLabels, since its query
construction and response parsing are currently untested. Create a table-driven
test around FindCamelCaseLabels using a mock prometheusv1.API to verify it
issues the camelCase-focused query, filters only matching metrics, and builds
the expected label pairs. Keep the test alongside the existing Metrics helpers
tests and reference FindCamelCaseLabels plus the label-pair handling used by
SetCamelCaseLabels.

In `@test/extended/util/prometheus/metrics.go`:
- Around line 49-56: SetCamelCaseLabels currently indexes families[i].Metric[0]
without verifying that Metric contains any entries, so add a defensive guard
before assigning labels. Update the SetCamelCaseLabels function to check that
the matched family has at least one Metric element before touching Metric[0],
and only set the Label field when that slice is non-empty. Keep the existing
label lookup by family name and preserve the current behavior for valid
MetricFamily values.
- Around line 79-99: The query construction in the metrics helper still uses
fmt.Sprintf with a raw label name, so update the PromQL building logic around
promClient.Query to avoid string-interpolating the selector directly and follow
the no-fmt.Sprintf-in-queries guidance. Also rename the inner val string in the
sample loop to avoid shadowing the outer val from promClient.Query, making the
code in this metrics aggregation path easier to read and maintain.

In `@test/extended/util/prometheus/promlint.go`:
- Around line 27-41: Update the local Problem type in the prometheus promlint
utility to actually wrap the upstream promlint.Problem instead of duplicating
its Metric and Text fields. Use embedding or a direct alias-style wrapper so the
existing String method and any callers still work with the upstream type, and
keep the Linter wrapper unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 9992f1dc-639f-439e-9172-8a748ffe71dd

📥 Commits

Reviewing files that changed from the base of the PR and between 52fc3ba and 23ddbba.

📒 Files selected for processing (4)
  • test/extended/prometheus/prometheus.go
  • test/extended/util/prometheus/metrics.go
  • test/extended/util/prometheus/metrics_test.go
  • test/extended/util/prometheus/promlint.go

Comment thread test/extended/util/prometheus/metrics_test.go Outdated
- gofmt: fix import ordering in prometheus.go and alignment in
  metrics_test.go, fixing the failing ci/prow/verify job
- fix misleading comment in TestCamelCaseRegex: the myHTTPHandler
  case matches the yH transition, not PH
- guard SetCamelCaseLabels against MetricFamily values with an empty
  Metric slice to avoid a future index-out-of-range panic
- rename the inner shadowed val variable in FindCamelCaseLabels to
  emptyVal for clarity

Assisted-by: claude-sonnet-5
Signed-off-by: Jan Fajerski <jfajersk@redhat.com>
@jan--f

jan--f commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Pushed a follow-up commit addressing review feedback and the failing verify job:

  • Fixed gofmt -s failures in prometheus.go (import ordering) and metrics_test.go (comment alignment) that caused ci/prow/verify to fail.
  • Fixed the misleading myHTTPHandler regex comment (actionable comment).
  • Added a defensive guard in SetCamelCaseLabels for MetricFamily values with an empty Metric slice.
  • Renamed the shadowed inner val to emptyVal in FindCamelCaseLabels.

Left two nitpicks as-is:

  • Embedding upstream promlint.Problem instead of duplicating its fields would break the existing Problem{Metric: ..., Text: ...} struct-literal call sites (embedding doesn't allow promoting field names in literals), for no functional benefit.
  • Added unit test coverage for FindCamelCaseLabels was flagged by CodeRabbit itself as a "poor tradeoff" (would need a full prometheusv1.API mock); skipping for now since the function is exercised by the informing e2e test itself.

@openshift-ci openshift-ci Bot added the ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review label Jul 9, 2026
@machine424

Copy link
Copy Markdown
Contributor

/pipeline required

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e-aws-csi
/test e2e-aws-ovn-fips
/test e2e-aws-ovn-microshift
/test e2e-aws-ovn-microshift-serial
/test e2e-aws-ovn-serial-1of2
/test e2e-aws-ovn-serial-2of2
/test e2e-gcp-csi
/test e2e-gcp-ovn
/test e2e-gcp-ovn-upgrade
/test e2e-metal-ipi-ovn-ipv6
/test e2e-vsphere-ovn
/test e2e-vsphere-ovn-upi

@openshift-ci

openshift-ci Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

@jan--f: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-aws-ovn-serial-2of2 f60e96b link true /test e2e-aws-ovn-serial-2of2
ci/prow/e2e-aws-ovn-fips f60e96b link true /test e2e-aws-ovn-fips

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@openshift-trt

openshift-trt Bot commented Jul 9, 2026

Copy link
Copy Markdown

Risk analysis has seen new tests most likely introduced by this PR.
Please ensure that new tests meet guidelines for naming and stability.

New Test Risks for sha: f60e96b

Job Name New Test Risk
pull-ci-openshift-origin-main-e2e-aws-ovn-fips High - "[sig-instrumentation][Late] Prometheus metric naming should follow Prometheus naming best practices [Suite:openshift/conformance/parallel]" is a new test that failed 1 time(s) against the current commit
pull-ci-openshift-origin-main-e2e-aws-ovn-microshift High - "[sig-instrumentation][Late] Prometheus metric naming should follow Prometheus naming best practices [Suite:openshift/conformance/parallel]" is a new test that failed 1 time(s) against the current commit
pull-ci-openshift-origin-main-e2e-aws-ovn-microshift-serial High - "[sig-instrumentation][Late] Prometheus metric naming should follow Prometheus naming best practices [Suite:openshift/conformance/parallel]" is a new test that failed 1 time(s) against the current commit
pull-ci-openshift-origin-main-e2e-aws-ovn-serial-1of2 High - "[sig-instrumentation][Late] Prometheus metric naming should follow Prometheus naming best practices [Suite:openshift/conformance/parallel]" is a new test that failed 1 time(s) against the current commit
pull-ci-openshift-origin-main-e2e-aws-ovn-serial-2of2 High - "[sig-instrumentation][Late] Prometheus metric naming should follow Prometheus naming best practices [Suite:openshift/conformance/parallel]" is a new test that failed 1 time(s) against the current commit
pull-ci-openshift-origin-main-e2e-gcp-ovn High - "[sig-instrumentation][Late] Prometheus metric naming should follow Prometheus naming best practices [Suite:openshift/conformance/parallel]" is a new test that failed 1 time(s) against the current commit
pull-ci-openshift-origin-main-e2e-metal-ipi-ovn-ipv6 High - "[sig-instrumentation][Late] Prometheus metric naming should follow Prometheus naming best practices [Suite:openshift/conformance/parallel]" is a new test that failed 1 time(s) against the current commit
pull-ci-openshift-origin-main-e2e-vsphere-ovn High - "[sig-instrumentation][Late] Prometheus metric naming should follow Prometheus naming best practices [Suite:openshift/conformance/parallel]" is a new test that failed 1 time(s) against the current commit
pull-ci-openshift-origin-main-e2e-vsphere-ovn-upi High - "[sig-instrumentation][Late] Prometheus metric naming should follow Prometheus naming best practices [Suite:openshift/conformance/parallel]" is a new test that failed 1 time(s) against the current commit

New tests seen in this PR at sha: f60e96b

  • "[sig-instrumentation][Late] Prometheus metric naming should follow Prometheus naming best practices [Suite:openshift/conformance/parallel]" [Total: 9, Pass: 0, Fail: 9, Flake: 0]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants