-
Notifications
You must be signed in to change notification settings - Fork 56
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
(WIP) 🐛 Fix: Prevent nil errors in setupLog.Error to ensure proper logging and add sanity check #1599
base: main
Are you sure you want to change the base?
(WIP) 🐛 Fix: Prevent nil errors in setupLog.Error to ensure proper logging and add sanity check #1599
Conversation
✅ Deploy Preview for olmv1 ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
27f6d94
to
287b0a0
Compare
287b0a0
to
c597f22
Compare
hack/ci/sanity.sh
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I like this!
Nit: I'd probably name this hack/ci/extra_linters.sh
Also nit: Is there a way to define the rules and messages such that they are setup as a list of pairs, and then we go ahead and write a loop to iterate and run each of them?
Lastly, I kinda wonder if there's already a generic regex-based linter built into golangci-lint that we could add custom rules to? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good points, I will try to check them out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may also want to look into writing custom analyzers in Go using golang.org/x/tools/go/analysis
. As is, if we have a variable name for a logger that is not setupLog
, we'll miss it.
I assume an analyzer could find all logr.Logger.Error()
method usage where the first parameter is nil
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But now I'm getting really picky :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the idea of the custom analyse is nice
I will try it out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it will be so easier.
I need to install locally
574 brew install pkg-config
576 brew install gpgme
Then, I could run
$ go vet -vettool=./bin/custom-linter ./...
# github.com/operator-framework/operator-controller/catalogd/cmd/catalogd
# [github.com/operator-framework/operator-controller/catalogd/cmd/catalogd]
catalogd/cmd/catalogd/main.go:146:3: Avoid using 'setupLog.Error(nil, ...)'. Instead, use 'errors.New()' or 'fmt.Errorf()' to ensure logs are created. Using 'nil' for errors can result in silent failures, making bugs harder to detect.
catalogd/cmd/catalogd/main.go:151:3: Avoid using 'setupLog.Error(nil, ...)'. Instead, use 'errors.New()' or 'fmt.Errorf()' to ensure logs are created. Using 'nil' for errors can result in silent failures, making bugs harder to detect.
# github.com/operator-framework/operator-controller/cmd/operator-controller
# [github.com/operator-framework/operator-controller/cmd/operator-controller]
cmd/operator-controller/main.go:131:3: Avoid using 'setupLog.Error(nil, ...)'. Instead, use 'errors.New()' or 'fmt.Errorf()' to ensure logs are created. Using 'nil' for errors can result in silent failures, making bugs harder to detect.
cmd/operator-controller/main.go:136:3: Avoid using 'setupLog.Error(nil, ...)'. Instead, use 'errors.New()' or 'fmt.Errorf()' to ensure logs are created. Using 'nil' for errors can result in silent failures, making bugs harder to detect.
But with golang-ci custom linters did not worked
And also, when I call via make file, that fails.
Seems that I need to pass some config
Then, we endup with configs for mac/linux
Maybe better keep it KISS
####################################################
# The purpose of this script is allow us to do extra
# sanity checks to ensure the quality.
####################################################
#!/bin/bash
set -e
echo_error() {
echo "[Sanity Check Fail]: $1"
}
# Criteria 1: Do not use setupLog.Error(nil, ...)
CRITERIA1_RULE="setupLog\.Error\(nil,"
CRITERIA1_MSG="Avoid using 'setupLog.Error(nil, ...)'. Instead, use 'errors.New()' or 'fmt.Errorf()' \
to ensure logs are created. Using 'nil' for errors can result in silent failures, making bugs harder to detect."
if grep -r --include="*.go" "$CRITERIA1_RULE" .; then
echo_error "$CRITERIA1_MSG"
exit 1
fi
echo "Sanity checks passed with success."
exit 0
####################################################
# The purpose of this script is allow us to do extra
# sanity checks to ensure the quality.
####################################################
#!/bin/bash
set -e
echo_error() {
echo "[Sanity Check Fail]: $1"
}
# Criteria 1: Do not use setupLog.Error(nil, ...)
CRITERIA1_RULE="setupLog\.Error\(nil,"
CRITERIA1_MSG="Avoid using 'setupLog.Error(nil, ...)'. Instead, use 'errors.New()' or 'fmt.Errorf()' \
to ensure logs are created. Using 'nil' for errors can result in silent failures, making bugs harder to detect."
if grep -r --include="*.go" "$CRITERIA1_RULE" .; then
echo_error "$CRITERIA1_MSG"
exit 1
fi
echo "Sanity checks passed with success."
exit 0
####################################################
# The purpose of this script is allow us to do extra
# sanity checks to ensure the quality.
####################################################
#!/bin/bash
set -e
echo_error() {
echo "[Sanity Check Fail]: $1"
}
# Criteria 1: Do not use setupLog.Error(nil, ...)
CRITERIA1_RULE="setupLog\.Error\(nil,"
CRITERIA1_MSG="Avoid using 'setupLog.Error(nil, ...)'. Instead, use 'errors.New()' or 'fmt.Errorf()' \
to ensure logs are created. Using 'nil' for errors can result in silent failures, making bugs harder to detect."
if grep -r --include="*.go" "$CRITERIA1_RULE" .; then
echo_error "$CRITERIA1_MSG"
exit 1
fi
echo "Sanity checks passed with success."
exit 0
for now.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1599 +/- ##
=======================================
Coverage 66.68% 66.68%
=======================================
Files 57 57
Lines 4584 4584
=======================================
Hits 3057 3057
Misses 1302 1302
Partials 225 225
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
c597f22
to
11b2c46
Compare
New custom linter under hack/ci project was created to allow us to define custom linters for the project
11b2c46
to
a66fb03
Compare
if !ok || i.Name != "setupLog" { | ||
return true | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check should:
- Look for all instances of
logr.Logger
(not justsetupLog
) - Of those, find when
Error
is called. - Of those, find when the first argument is
nil
.
That way, we'll find all cases where this is an issue, and we'll protect ourselves in the case that we decide to change the name of setupLog
.
if len(expr.Args) > 0 { | ||
if arg, ok := expr.Args[0].(*ast.Ident); ok && arg.Name == "nil" { | ||
pass.Reportf(expr.Pos(), "Avoid using 'setupLog.Error(nil, ...)'. Instead, use 'errors.New()' "+ | ||
"or 'fmt.Errorf()' to ensure logs are created. Using 'nil' for errors can result in silent "+ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most likely, we should just say "pass a non-nil error". If we suggest fmt.Errorf()
, that may incorrect lead to a contributor burying useful structured log context inside the error message, when what they should do is:
l.Error(errors.New("could not do thing"), "thing", foo, "otherThing", bar)
os.Exit(1) | ||
} | ||
|
||
if metricsAddr != "" && certFile == "" && keyFile == "" { | ||
setupLog.Error(nil, "metrics-bind-address requires tls-cert and tls-key flags to be set") | ||
setupLog.Error(fmt.Errorf("unable to configure metrics-bind-address"), "metrics-bind-address requires tls-cert and tls-key flags to be set") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: use errors.New
since we aren't using the format string capabilities of fmt.Errorf
.
.PHONY: lint-custom | ||
lint-custom: custom-linter-build | ||
go vet -vettool=./bin/custom-linter ./... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
golangci-lint
should already be running go vet
(assuming the govet
linter is enabled). So I think we get this part automatically if we add the directory where we build the linter binary to the path for the golangci-lint run
command.
Description
Fix: Prevent nil errors in setupLog.Error to ensure proper logging
Closes; #1566
Closes: #1556
Reviewer Checklist