Leveled logs with Cobra and Logrus
I recently wrote a CLI using Cobra, a widely adopted CLI framework for Golang that’s used in Kubectl, Docker, Terraform, Hugo, and other industry-standard CLIs.
I wanted to use Logrus, a highly regarded structured logging framework for Go. I wanted informative, colorized, leveled logs, but I also wanted to be able to log simple, user-facing output without all of the bells and whistles. I was surprised at the lack of documentation around this simple goal.
Here’s one way to solve this problem.
Create a file called logging.go
in your cmd
package:
package cmd
import (
"fmt"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
var debug bool
type PlainFormatter struct {
}
func (f *PlainFormatter) Format(entry *log.Entry) ([]byte, error) {
return []byte(fmt.Sprintf("%s\n", entry.Message)), nil
}
func toggleDebug(cmd *cobra.Command, args []string) {
if debug {
log.Info("Debug logs enabled")
log.SetLevel(log.DebugLevel)
log.SetFormatter(&log.TextFormatter{})
} else {
plainFormatter := new(PlainFormatter)
log.SetFormatter(plainFormatter)
}
}
Add a PreRun
to each of your Cobra commands:
var addCmd = &cobra.Command{
...
PreRun: toggleDebug, // This.
Run: func(cmd *cobra.Command, args []string) {
// Subcommand logic goes here.
}
}
Add a global persistent flag to root.go
:
func init() {
...
rootCmd.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "verbose logging")
}
It’s as simple as that. Now you can reap the benefits of flag-toggled leveled logs. Use the following invocations anywhere in your code:
log.Info()
log.Debug()
log.Warning()
log.Error()
log.Fatal()
Debug logs are suppressed by default. You can pass the --debug
or -d
flag to any command to print more verbose, colorized debug logs, which are super helpful when troubleshooting.
I hope you found this helpful.
2020-07-22