5

In Java, which is the language in which I normally work, a common feature of logging libraries is the ability to set a "global" logging level - eg emit to the log file if the level is WARNING or above, otherwise not, regardless of the module where the logging was done.

I want to do the same in Glog, in conjunction with also only logging to the standard error, not a file.

How?

UPDATE: By the time control passes to my code, the executable has already been started - I'm running as an AWS Lambda function - so I'm not sure I have the option to set the Glog state on the command line. Can I do it with function calls?


I'm both new to GoLang and I think I just don't understand the internal logic of Go. Because my mind can't penetrate the Glog docs. So this question may seem naive.

0xbe5077ed
  • 4,565
  • 6
  • 35
  • 77
  • The -v flag works for V-style logs, the others write unconditional IMHO (which is correct, Java got that wrong). – Volker Jun 15 '18 at 18:04
  • @Volker, I can't set flags on the command line because I'm already running by that point... (See the **UPDATE** section of the question.) – 0xbe5077ed Jun 15 '18 at 19:38
  • Flags can be set during runtime so I do not see your problem. – Volker Jun 16 '18 at 19:45

3 Answers3

7

Well, I skimmed the docs and glog is controlled by flags, so they have to be present in order for this to work. In your case, you will have to set them at runtime. You are going to want to set logtostderr=true to log to stderr and set the severity level to one of the possible options:
stderrthreshold=[WARNING|ERROR|INFO|FATAL]

Example:

package main

import (
    "flag"
    "fmt"
    "os"

    "github.com/golang/glog"
)

func usage() {
    flag.PrintDefaults()
    os.Exit(2)
}

func init() {
    flag.Usage = usage
    flag.Set("logtostderr", "true")
    flag.Set("stderrthreshold", "WARNING")
    flag.Set("v", "2")
    // This is wa
    flag.Parse()
}

func main() {
    number_of_lines := 10
    for i := 0; i < number_of_lines; i++ {
        glog.V(2).Infof("LINE: %d", i)
        message := fmt.Sprintf("TEST LINE: %d", i)
        glog.Warning(message)
    }
    glog.Flush()
}

Output:

$ ./stackoverflow.exe
I0615 11:03:47.589969   11776 main.go:30] LINE: 0
W0615 11:03:47.590469   11776 main.go:32] TEST LINE: 0
I0615 11:03:47.590969   11776 main.go:30] LINE: 1
W0615 11:03:47.590969   11776 main.go:32] TEST LINE: 1
I0615 11:03:47.590969   11776 main.go:30] LINE: 2
W0615 11:03:47.590969   11776 main.go:32] TEST LINE: 2
I0615 11:03:47.590969   11776 main.go:30] LINE: 3
W0615 11:03:47.590969   11776 main.go:32] TEST LINE: 3
I0615 11:03:47.590969   11776 main.go:30] LINE: 4
W0615 11:03:47.590969   11776 main.go:32] TEST LINE: 4
I0615 11:03:47.591469   11776 main.go:30] LINE: 5
W0615 11:03:47.591469   11776 main.go:32] TEST LINE: 5
I0615 11:03:47.591469   11776 main.go:30] LINE: 6
W0615 11:03:47.591469   11776 main.go:32] TEST LINE: 6
I0615 11:03:47.591469   11776 main.go:30] LINE: 7
W0615 11:03:47.591469   11776 main.go:32] TEST LINE: 7
I0615 11:03:47.591469   11776 main.go:30] LINE: 8
W0615 11:03:47.591469   11776 main.go:32] TEST LINE: 8
I0615 11:03:47.591469   11776 main.go:30] LINE: 9
W0615 11:03:47.591469   11776 main.go:32] TEST LINE: 9
will7200
  • 1,496
  • 1
  • 13
  • 23
  • How do I know my `init()` will be called before Glog's `init()`? (inits?) Or is that not important? – 0xbe5077ed Jun 15 '18 at 19:36
  • If I remember correctly it does by packages first and then whatever init is in your main or package. In this case it does not matter. Just know that init will be called before main. – will7200 Jun 15 '18 at 19:48
  • The `init` functions of all imported packages will be run before the `init` function of the package doing the importing. – Thomas Jun 15 '18 at 20:33
  • thank you, this was really helpful. The flagging method is a great way, i was struggling to do this in logrus. – Alok Kumar Singh Jun 19 '20 at 16:23
1

From what I can tell, they don't provide the functionality you're looking for. However, it seems like this is something you could very easily use the Adapter Pattern for.

I've created a barebones implementation for you here: https://play.golang.org/p/LJPWwF0gTgB

Although, I suggest you look into another logging library that provides something more like what you're wanting. I personally use https://github.com/uber-go/zap, as it also ties nicely into opentracing via Jaeger, which is something I generally need in addition to writing logs.

I think zap might feel more correct, but I also don't have context on your use case of have any issues with glog. Just a preference that might help.

syntaqx
  • 2,636
  • 23
  • 29
  • I think your Zap suggestion might be the right way to go here. It looks easier to use. – 0xbe5077ed Jun 15 '18 at 19:37
  • Going with a different logger is probably for the best if you don't mind switching. – will7200 Jun 15 '18 at 19:49
  • I believe it just matches your use case better, and gives you more flexibility overall. glog is useful for very specific implementations, but leans towards an opinionated implementation rather than flexibility. Zap is more configuration over convention, which generally lets people explore their options. – syntaqx Jun 15 '18 at 19:50
1

Kubernetes klog is a fork of glog which solves some annoying issues like global Flag setting

https://github.com/kubernetes/klog

package main

import (
    "flag"
    "fmt"
    "k8s.io/klog"
)

func main() {
    klog.InitFlags(nil)
    flag.Set("logtostderr", "true")
    flag.Set("stderrthreshold", "WARNING")
    flag.Set("v", "2")
    flag.Parse()

    number_of_lines := 10

    for i := 0; i < number_of_lines; i++ {
        klog.V(2).Infof("LINE: %d", i)
        message := fmt.Sprintf("TEST LINE: %d", i)
        klog.Warning(message)
    }
    klog.Flush()
}
Roman Shishkin
  • 2,097
  • 20
  • 21