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

logcheck: support banning non-contextual functions and methods #25

Merged
merged 2 commits into from
Dec 6, 2023

Conversation

pohly
Copy link
Contributor

@pohly pohly commented Nov 23, 2023

Sometimes there are APIs with different variants where one variant is fine in code which doesn't support contextual logging but should be replaced with some other variant if that is the goal.

For example, k8s.io/apimachinery/pkg/util/runtime.HandleError is the old-style function. We cannot deprecate it because it works fine in most existing code. But the upcoming HandleErrorWithContext is what code in Kubernetes that has (or will be) converted to contextual logging should use.

We also cannot forbid it through forbidigo, because then the logcheck.conf with its definition of which code is "contextual" would be ignored. Besides, maintaining a config for forbidigo would be continual effort that would need to be replicated by other projects consuming the package with these APIs.

A better solution is to:

  • mark these non-contextual APIs through a //logcheck:context // <why> comment
  • detect those comments in logcheck
  • warn about using them in contextual code

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: pohly

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

The pull request process is described here

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

@k8s-ci-robot k8s-ci-robot requested a review from thockin November 23, 2023 13:58
@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. approved Indicates a PR has been approved by an approver from all required OWNERS files. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Nov 23, 2023
@pohly pohly force-pushed the logcheck-context-comment branch from b51cd08 to a4e5ad0 Compare November 23, 2023 14:00
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 23, 2023
@pohly
Copy link
Contributor Author

pohly commented Nov 23, 2023

It also works in Kubernetes:

diff --git a/staging/src/k8s.io/client-go/tools/cache/shared_informer.go b/staging/src/k8s.io/client-go/tools/cache/shared_informer.go
index 9851b197240..36af7ca07f0 100644
--- a/staging/src/k8s.io/client-go/tools/cache/shared_informer.go
+++ b/staging/src/k8s.io/client-go/tools/cache/shared_informer.go
@@ -170,7 +170,7 @@ type SharedInformer interface {
        // Run starts and runs the shared informer, returning after it stops.
        // The informer will be stopped when stopCh is closed.
        //
-       // RunWithContext should be used instead in k8s.io/kubernetes source code.
+       //logcheck:context // RunWithContext should be used instead in code which uses contextual logging.
        Run(stopCh <-chan struct{})
        // RunWithContext starts and runs the shared informer, returning after it stops.
        // The informer will be stopped when the context is canceled.
$ logcheck -config hack/logcheck.conf ./pkg/controller/...
...
/nvme/gopath/src/k8s.io/kubernetes/pkg/controller/job/job_controller_test.go:4642:57: RunWithContext should be used instead in code which uses contextual logging.
/nvme/gopath/src/k8s.io/kubernetes/pkg/controller/job/job_controller_test.go:4668:17: RunWithContext should be used instead in code which uses contextual logging.
/nvme/gopath/src/k8s.io/kubernetes/pkg/controller/job/job_controller_test.go:5195:51: RunWithContext should be used instead in code which uses contextual logging.
/nvme/gopath/src/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_test.go:712:45: RunWithContext should be used instead in code which uses contextual logging.

@pohly pohly force-pushed the logcheck-context-comment branch 2 times, most recently from 8fccd67 to 8a7f645 Compare November 23, 2023 15:09
}

type Handler interface {
//logcheck:context//Use HandleErrorWithContext instead in code which supports contextual logging.

Choose a reason for hiding this comment

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

small nits
I think
//logcheck:context //Use HandleErrorWithContext instead in code which supports contextual logging.
may be better which is same as described in README.md

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is intentionally checking that the code handles also the case that there is no space before the //.

@@ -56,6 +56,14 @@ through that.
klog calls that are needed to manage contextual logging, for example
`klog.Background`, are still allowed.

Functions or methods that have a comment of the form

//logcheck:context // Foo should not be used in code which supports contextual logging.

Choose a reason for hiding this comment

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

Just curious, I think this default explanation wants to express the Foo function does not support contextual logging, so the developer should not use this function any more, they should use the new version function which supports contextual logging, am I understanding this correctly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct. The default doesn't know what the replacement is, so it can't mention it. I think in practice one should always add such a comment.

Choose a reason for hiding this comment

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

Yes, I think you're right.
This Foo should not be used in code which supports contextual logging expression makes me a little confused about whether Foo supports contextual logging or not, when I first see it. Now it's clear.

Comment on lines 61 to 62
//logcheck:context // Foo should not be used in code which supports contextual logging.
func Foo() { ... }

Choose a reason for hiding this comment

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

This code example is best selected using the Code block, otherwise the format is messy
image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right. I didn't indent enough. Will fix.

//logcheck:context // Foo should not be used in code which supports contextual logging.
func Foo() { ... }

are also not allowed. The additional explanation is optional. The default is

Choose a reason for hiding this comment

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

I'm a little confused. Functions or methods that have a comment of the form should be allowed from the PR context. Why is the description here not allowed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"not allowed" in code where checking for contextual logging is enabled. The description (the additional explanation after logcheck:context) is allowed.

Does this clarify it?

Choose a reason for hiding this comment

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

I understand, but it is best to add clarification above to avoid user confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I already updated the README.md with my comment. If it needs further wording changes, can you suggest something?

Choose a reason for hiding this comment

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

Just my personal suggestion:

When contextual logging is enabled, a function or method has no the //logcheck:context // <why> comment will not be allowed by log check verification. Conversely, a function or method that has the //logcheck:context // <why> comment will be allowed by log check verification, and the additional explanation you have defined (// <why>) will be output as a warning message. The additional explanation is optional. The default is the example text below.

Here is an example:

    //logcheck:context // Foo should not be used in code which supports contextual logging.
    func Foo() { ... }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's actually the other way around: having that comment indicates that the function is not allowed.

I've rewritten the section. I hope it is clearer now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Regarding "not allowed": the comment also could be logcheck:nocontext with the same semantic. Not sure whether that would be better.

Choose a reason for hiding this comment

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

Nice job! It does seem clearer after the rewrite.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

LGTM it and we can do a release? 😄

@pohly pohly force-pushed the logcheck-context-comment branch from 8a7f645 to c704227 Compare November 24, 2023 10:51
@pohly
Copy link
Contributor Author

pohly commented Nov 27, 2023

/hold

When I try this on the entire Kubernetes code base, I get warnings about unstructured log calls in packages where those should be allowed. Need to investigate...

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Nov 27, 2023
@pohly
Copy link
Contributor Author

pohly commented Nov 27, 2023

/unhold

False alarm. kubernetes/kubernetes#121757 needs to be merged first, then logcheck can be updated.

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Nov 27, 2023
@dgrisonnet
Copy link
Member

/triage accepted

@k8s-ci-robot k8s-ci-robot added triage/accepted Indicates an issue or PR is ready to be actively worked on. and removed needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. labels Nov 30, 2023
pohly added 2 commits December 5, 2023 10:29
Sometimes there are APIs with different variants where one variant is fine in
code which doesn't support contextual logging but should be replaced with some
other variant if that is the goal.

For example, k8s.io/apimachinery/pkg/util/runtime.HandleError is the old-style
function. We cannot deprecate it because it works fine in most existing
code. But the upcoming HandleErrorWithContext is what code in Kubernetes that
has (or will be) converted to contextual logging should use.

We also cannot forbid it through forbidigo, because then the logcheck.conf with
its definition of which code is "contextual" would be ignored. Besides,
maintaining a config for forbidigo would be continual effort that would need to
be replicated by other projects consuming the package with these APIs.

A better solution is to:
- mark these non-contextual APIs through a `//logcheck:context // <why>` comment
- detect those comments in logcheck
- warn about using them in contextual code
strings.CutPrefix is useful and only available in >= 1.20. golangci-lint then
complains about the out-dated ioutil.
@pohly pohly force-pushed the logcheck-context-comment branch from c704227 to 0eec4af Compare December 5, 2023 09:29
@mengjiao-liu
Copy link

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Dec 6, 2023
@k8s-ci-robot k8s-ci-robot merged commit a41e815 into kubernetes-sigs:main Dec 6, 2023
3 checks passed
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. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. triage/accepted Indicates an issue or PR is ready to be actively worked on.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants