Where to log error in go

10,277

This is an interesting topic, and really boils down to a lot of opinion, so this may get closed. There are a few guidelines I try to follow:

  1. Only "handle" an error once. Logging counts as handling. If you do not know what action needs to be taken, just pass it up. You definitely don't want errors to be logged multiple times per occurrence.

  2. If your caller is likely to change their behavior because of the error, you should return it. If you can still do your "job" despite the error, maybe you should log it and continue.

  3. Sometimes it helps to add context to where the error initially entered your system (so the log line can include where the error came from, not just where it finally got logged). Something like https://github.com/pkg/errors can be useful for this.

Share:
10,277

Related videos on Youtube

Alex Parker
Author by

Alex Parker

I love to learn.

Updated on October 21, 2022

Comments

  • Alex Parker
    Alex Parker over 1 year

    Perhaps this is an opinion or maybe it's actually a best practice, but I want to do it correctly.

    Consider the following code:

    func main() {
        if err := doSomething(); err != nil {
            // log here and exit?
        }
    }
    
    func doSomething() {
        f, err := os.Open("filename.ext")
        if err != nil {
            // log here and return the error/exit?
        }
    }
    

    I am interested to know where the error should be logged and where the program should be exited (assuming recovery is impossible). Some possibilities include: logging and exiting in the callee; logging in the callee, returning the error, and exiting in the caller; logging in the callee, returning the error, logging in the caller, and exiting. There seem to be benefits to all of these approaches. The second approach, for instance, allows a fine grained error message but still passes the error on to the caller. However, it will result in two log messages.

    Thanks!

  • Kaedys
    Kaedys over 7 years
    To further add to this, as a rule, don't use os.Exit() except in your main() function. Primary reason is, unlike panic(), os.Exit() cannot be caught, and main() really should have the authority on when the process terminates and how. As a corollary, os.Exit() and by extension, log.Fatal() (which calls os.Exit()) should absolutely never be used in libraries intended to be imported by others (I see this ALL the time, and it's terrible practice). If it's fatal (in an importable package), panic(), don't os.Exit() or log.Fatal().