Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

testutil compareMetricFamilies: make less error-prone #1424

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

leonnicolas
Copy link

The functions GatherAndCompare, ScrapeAndCompare and others that use
compareMetricFamilies under the hood can return no error if
metricNames includes none of the names found in the scraped/gathered
results. To avoid false Positves (an error being the negative case), we
can return an error if there is is at least one name in metricNames
that is not in the filtered results.

Fixes: #1351

Signed-off-by: leonnicolas leonloechner@gmx.de

The functions `GatherAndCompare`, `ScrapeAndCompare` and others that use
`compareMetricFamilies` under the hood can return no error if
`metricNames` includes none of the names found in the scraped/gathered
results. To avoid false Positves (an error being the negative case), we
can return an error if there is is at least one name in `metricNames`
that is not in the filtered results.

Fixes: prometheus#1351

Signed-off-by: leonnicolas <leonloechner@gmx.de>
@leonnicolas leonnicolas force-pushed the testutil-compare-metrics-family branch from 0381a25 to 7163ac9 Compare January 4, 2024 11:31
@@ -254,6 +254,9 @@ func compareMetricFamilies(got, expected []*dto.MetricFamily, metricNames ...str
if metricNames != nil {
got = filterMetrics(got, metricNames)
expected = filterMetrics(expected, metricNames)
if len(metricNames) > len(got) {
Copy link
Author

Choose a reason for hiding this comment

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

I was thinking to use something like slices, to find the metricName that is not present in got. Would the additional package (slices is not yet in the std lib in go 1.19) and extra complexity of this function be outweighed by the improved usability? You would be able to see the misspelled or missing metricName in the error text.

Copy link
Member

Choose a reason for hiding this comment

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

Nice, I would either wait for older versions than 1.19 to be dropped from support or quickly write a small function finding those. I don't think at the end using std lib slices extension is that needed. It might be just two loops. WDYT?

Copy link
Author

Choose a reason for hiding this comment

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

I added a commit. Finding the difference in 2 slices seems so easy but always requires so much code.

I added the "resulting" slice to the error with %v. I wonder if we should somehow allow callers of compareMetricFamilies to extract the missing metric Names? I guess that would require an API change :(
It is just awkward to test if the "correct" metric names are in the error message.

Copy link
Author

Choose a reason for hiding this comment

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

any feedback @bwplotka ?

Copy link
Member

Choose a reason for hiding this comment

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

Why exact metric names would be useful? Isn't it enough to return error?

compareMetricFamilies has a clear semantics - we are just ensuring the error is more readable and comparison true.

I think small code complexity is fine here - proposed below what can be done.

Copy link
Author

Choose a reason for hiding this comment

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

Why exact metric names would be useful? Isn't it enough to return error?

right, error should be enough

@leonnicolas
Copy link
Author

According to Contributing.md I have to address one of the maintainers: @bwplotka

I also tried using table tests as you suggested in #1351, but I found it a bit messy for the test cases where the scraped server is not running or returns a bad request, so I left those tests as there where.

In to see which metric names are missing, we can add them to the error
message.

Signed-off-by: leonnicolas <leonloechner@gmx.de>
Copy link
Member

@bwplotka bwplotka left a comment

Choose a reason for hiding this comment

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

Nice, added suggestions, otherwise LGTM!

if len(metricNames) > len(got) {
h := make(map[string]struct{})
for _, mf := range got {
if mf == nil {
Copy link
Member

Choose a reason for hiding this comment

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

got element can be really nil here?

prometheus/testutil/testutil.go Outdated Show resolved Hide resolved
@@ -254,6 +254,9 @@ func compareMetricFamilies(got, expected []*dto.MetricFamily, metricNames ...str
if metricNames != nil {
got = filterMetrics(got, metricNames)
expected = filterMetrics(expected, metricNames)
if len(metricNames) > len(got) {
Copy link
Member

Choose a reason for hiding this comment

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

Why exact metric names would be useful? Isn't it enough to return error?

compareMetricFamilies has a clear semantics - we are just ensuring the error is more readable and comparison true.

I think small code complexity is fine here - proposed below what can be done.

@@ -332,27 +332,46 @@ Diff:
}

func TestScrapeAndCompare(t *testing.T) {
const expected = `
scenarios := map[string]struct {
Copy link
Member

Choose a reason for hiding this comment

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

nice!

prometheus/testutil/testutil_test.go Outdated Show resolved Hide resolved
@leonnicolas leonnicolas force-pushed the testutil-compare-metrics-family branch from 6085d5d to 847a7bb Compare February 7, 2024 17:55
- remove if nil check
- use two nested loops instead of map
- use new function `hasMetricByName` for readability

Co-authored-by: Bartlomiej Plotka <bwplotka@gmail.com>
Signed-off-by: leonnicolas <60091705+leonnicolas@users.noreply.github.com>
@leonnicolas leonnicolas force-pushed the testutil-compare-metrics-family branch from 847a7bb to 437f988 Compare February 7, 2024 18:01
@leonnicolas
Copy link
Author

@bwplotka thanks for your review. I hope I addressed all you comments

@leonnicolas
Copy link
Author

@bwplotka anything missing from my side to move on with this PR?

Copy link
Member

@bwplotka bwplotka left a comment

Choose a reason for hiding this comment

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

Thanks! Looks nice, just one comment, otherwise LGTM

Comment on lines +338 to +339
// expectedErrPrefix if empty, means no fail is expected for the comparison.
expectedErrPrefix string
Copy link
Member

Choose a reason for hiding this comment

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

Why prefix and not exact error? Would be nice to test that missing metric semantics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

testutil.GatherAndCompare is error-prone
2 participants