I am relatively new to the packages Cobra and Logrus in Golang and there is one little thing I would to ask for help when it comes to integrating them. I am working on a new Golang Cobra CLI which contains several commands/sub-commands. I'd like to use Logrus for logging inside my subcommands but I cannot find a good way to add new fields to the logger and pass them all to my subcommands. This is what I have so far (I simplified my code for better explanation of my purpose):
├──pkg/
├──logger/
| ├──logger.go
├──cmd/
├── root.go
├──scmd/
| ├──scmd.go
// root.go
package cmd
func ExecuteRoot() {
rootCmd := getRootCmd()
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func getRootCmd() *cobra.Command {
rootCmd := &cobra.Command{
Use: "mycli",
PersistentPreRun: enableLogs,
}
rootCmd.AddCommand(scmd.Getscmd())
return rootCmd
}
func enableLogs(cmd *cobra.Command, args []string) {
logger.ConfigureLogger(cmd.Flag("log-level").Value.String())
}
// logger.go
package logger
import (
"github.com/sirupsen/logrus"
)
var MyCli *logrus.Entry
func ConfigureLogger(d string) {
lv, err := logrus.ParseLevel(d)
if err != nil {
logrus.Fatal(err)
}
logrus.SetLevel(lv)
logrus.SetFormatter(&logrus.TextFormatter{
DisableQuote: true,
ForceColors: true,
})
MyCli = logrus.WithFields(logrus.Fields{"foo1": "bar1", "foo2": "bar2"})
}
// scmd.go
package scmd
import (
"pkg/logger"
"github.com/spf13/cobra"
)
func Getscmd() *cobra.Command {
serviceUpdateCmd := &cobra.Command{
Use: "scmd",
Run: runServiceUpdateCmd,
}
return serviceUpdateCmd
}
func runServiceUpdateCmd(cmd *cobra.Command, args []string) {
logger.MyCli.Info("start scmd")
// here what the command does ...
}
If I run it, I get what I am expecting: My subcommands (in this case scmd) logs at the level I set my flag log-level and the fields defined in my package logger are passed ("foo1": "bar1", "foo2": "bar2"). However, I feel it is not the right way and could become problematic when creating unit test as I am using the global variable var MyCli from my logger package. Moreover, I should import it and use it as logger.MyCli in every Info, error, warn, etc line I want to log.
My question is whether there is a better approach to pass fields in Logrus on all subcommands I create or the way I explained above is my only option.
Any help or idea to improve my code is really welcome.
Thanks!