I have a project that needs to use cobra
and klog
to generate executable and print logs and keep.
Firstly, I tested that using the following klog
can output the log to the terminal and file
at the same time.
package main
import (
"flag"
"k8s.io/klog"
)
func init() {
var fs flag.FlagSet
klog.InitFlags(&fs)
fs.Set("logtostderr", "false")
fs.Set("log_file_max_size", "100")
fs.Set("log_file", "/home/test/workspace/klogfile/test.log")
fs.Set("alsologtostderr", "true")
}
func main() {
defer klog.Flush()
klog.Info("info")
klog.Warning("warning")
klog.Error("error")
}
The content of file /home/test/workspace/klogfile/test.log
is as follow
Log file created at: 2023/04/06 16:46:07
Running on machine: s52
Binary: Built with gc go1.16.12 for linux/amd64
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
I0406 16:46:07.751183 13512 main.go:20] info
W0406 16:46:07.751594 13512 main.go:21] warning
E0406 16:46:07.751629 13512 main.go:22] error
Then I try to add it to cobra
based on k8s style
package main
import (
"flag"
"github.com/spf13/cobra"
"k8s.io/klog"
)
var (
str = "hello world"
)
func NewCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "echo",
Short: "use klog with cobra",
Long: "Use klog together with cobra.",
Run: func(cmd *cobra.Command, args []string) {
Run()
},
}
klog.InitFlags(flag.CommandLine)
cmd.Flags().AddGoFlagSet(flag.CommandLine)
cmd.Flags().SortFlags = false
cmd.Flags().StringVar(&str, "str", str, "string to print")
return cmd
}
func Run() {
defer klog.Flush()
klog.Infof("Running, str:%s", str)
}
func main() {
if err := NewCommand().Execute(); err != nil {
klog.Fatalf("root cmd execute failed, err=%v", err)
}
}
I can print out the required log options
through --help
, but when I override them to achieve the save to file in the above example, only the output is output to the terminal and not to the file
# go run main2.go --logtostderr false --log_file_max_size "100" --alsologtostderr true --log_file "/home/test/workspace/klogfile/test2.log"
I0406 16:52:57.479455 15217 cobra_klog.go:34] Running, str:hello world
May I ask where I am missing the necessary code
, if so, please let me know how to modify it, thank you!
There is nothing wrong in your code. The only issue is that you must use the -flag=false
form to turn off a boolean flag (see Command line flag syntax).
Try this command (repalce --logtostderr false
with --logtostderr=false
):
go run main2.go --logtostderr=false --log_file_max_size "100" --alsologtostderr true --log_file "/home/test/workspace/klogfile/test2.log"
BTW, I think --log_file_max_size "100"
could be simplified to --log_file_max_size 100
.
Update:
To reduce the exposed flags of klog:
package main
import (
"flag"
"github.com/spf13/cobra"
"k8s.io/klog"
)
var (
str = "hello world"
+ logFile string
)
func NewCommand() *cobra.Command {
+ var fs flag.FlagSet
+ klog.InitFlags(&fs)
cmd := &cobra.Command{
Use: "echo",
Short: "use klog with cobra",
Long: "Use klog together with cobra.",
Run: func(cmd *cobra.Command, args []string) {
+ fs.Set("logtostderr", "false")
+ fs.Set("log_file", logFile)
Run()
},
}
- klog.InitFlags(flag.CommandLine)
- cmd.Flags().AddGoFlagSet(flag.CommandLine)
cmd.Flags().SortFlags = false
cmd.Flags().StringVar(&str, "str", str, "string to print")
+ cmd.Flags().StringVar(&logFile, "log_file", "", "If non-empty, use this log file")
return cmd
}
func Run() {
defer klog.Flush()
klog.Infof("Running, str:%s", str)
}
func main() {
if err := NewCommand().Execute(); err != nil {
klog.Fatalf("root cmd execute failed, err=%v", err)
}
}