This directory contains a tool for checking structured logging calls to logr.Logger instances (inspired by klog's logcheck).
It checks Info, Error and WithValues calls for common programmer-level errors.
For example, it verifies that
- calls are made with key-value pairs (even number of variadic args)
- messages don't contain
printfformat specifiers (%sand friends)
Furthermore, it verifies compliance with several aspects of our logging guideline (e.g., constant messages and keys, capitalized messages, etc.).
The tool was created to support the migration from unstructured logging with logrus to structured logging with logr in the context of gardener/gardener#4251.
With this tool we will be able to prevent bugs caused by switching to a new logging style (e.g. panic due to odd number of args). Also, it helps to make logging in our components more consistent across the entire codebase despite the high number of contributors.
The tool is implemented using the golang.org/x/tools/go/analysis package, which is a "linter framework" used by go vet and golangci-lint as well.
If you are looking for a better understanding of how the tool is implemented, you can take a look at this tutorial on writing custom linters, which explains all the fundamental building blocks.
There are two options for installing and using the logcheck tool:
- standalone binary: simple, but limited
golangci-lintplugin (recommended): specific build requirements, but comes with caching, nice output, and flexible configuration options (e.g., excludes and//nolintcomments) out of the box
Install the tool with:
go install github.com/gardener/gardener/hack/tools/logcheckUse it with:
logcheck package [package...]golangci-lint Plugin (Recommended)
golangci-lint features a mechanism for loading custom linters using Go's plugin library.
Build the plugin with:
CGO_ENABLED=1 go build -o logcheck.so -buildmode=plugin github.com/gardener/gardener/hack/tools/logcheck/plugin
⚠️ Both thegolangci-lintbinary and thelogcheckplugin have to be built withCGO_ENABLED=1for the plugin mechanism to work. See golangci/golangci-lint#1276 for more details. This means, you can't use released binaries from GitHub or Homebrew for example, but have to build the binary yourself.
Load the plugin by adding the following to your .golangci.yaml configuration file:
linters-settings:
custom:
logcheck:
path: hack/tools/bin/logcheck.so
description: Check structured logging calls to logr.Logger instances
original-url: github.com/gardener/gardener/hack/tools/logcheckℹ️ In order for the plugin mechanism to work, all versions of plugin dependencies that overlap with
golangci-lintmust be set to the same version. You can see the versions by runninggo version -m golangci-lint.
Now, logcheck is executed along with all other linters:
golangci-lint run ./...This repository is configured to run logcheck as a golangci-lint plugin along with all other linters on:
make check