You can find a working example on my GitHub: https://github.com/seblegall/blog-scripts/tree/master/logrus-cobra
I recently had to refactor the way one of my app print logs. My idea was to use
logrus as it is a very well known lib to produce logs with Go.
Logrus let you print nicely color-coded and structured logs and is completely API compatible with the standard library logger.
My first question was about log level and how to setup it once across all sub-directory/package of my project.
Under the hood, logrus instantiate a new variable
log. Once done, calling the
logrus.SetLevel() function will store the level directly in this newly instantiated struct.
Thus, we have a global struct, available across all sub-package making the level automatically shared without having to use dependency injection.
If you need to set a different level in a sub-package (for example), you just need to instantiate a new logger :
More about logrus here : https://github.com/sirupsen/logrus
Then I thought about adding a flag to my binary, letting the user set its own log level.
My application is using
cobra, so I had to decided where to read the flag and where to init the logger by setting the level, depending on the flag value.
My first thought was to create a
SetLevel() func which could be called in each cobra sub-command run function. But I found a better approach by looking at the source code of Skaffold
Cobra has a cool feature called pre/post run. It’s basically a function that will be executed right before the command start, or right after.
The same way you can defined “persistent” flags in cobra commands (which is a way to create inheritance between commands and sub-commands), the framework also offers a
That was the perfect place to put my log init as it is :
- Defined once for all sub-commands (which is a behaviour you probably want when creating a
- A place where flags are already defined and read. So I could make a good use of the flag value set by the user.
Here is how it goes :
PersistentPreRun func defined, you call easily create a sub-command which will use the logger.
This will produce :
By default, logrus is configured on Info level and the default value for my flag is Warn. Son the result proves it works ;-)
You are done !