https://github.com/sirupsen/logrus

    With log.SetFormatter(&log.JSONFormatter{}), for easy parsing by logstash or Splunk:

    1. {"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
    2. ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
    3. {"level":"warning","msg":"The group's number increased tremendously!",
    4. "number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
    5. {"animal":"walrus","level":"info","msg":"A giant walrus appears!",
    6. "size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
    7. {"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.",
    8. "size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
    9. {"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,
    10. "time":"2014-03-10 19:57:38.562543128 -0400 EDT"}

    With the default log.SetFormatter(&log.TextFormatter{}) when a TTY is not attached, the output is compatible with the logfmt format:

    1. time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8
    2. time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
    3. time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true
    4. time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
    5. time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
    6. time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true

    To ensure this behaviour even if a TTY is attached, set your formatter as follows:

    1. log.SetFormatter(&log.TextFormatter{
    2. DisableColors: true,
    3. FullTimestamp: true,
    4. })

    If you wish to add the calling method as a field, instruct the logger via:

    1. log.SetReportCaller(true)

    This adds the caller as ‘method’ like so:

    1. {"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by",
    2. "time":"2014-03-10 19:57:38.562543129 -0400 EDT"}

    The simplest way to use Logrus is simply the package-level exported logger:

    1. package main
    2. import (
    3. log "github.com/sirupsen/logrus"
    4. )
    5. func main() {
    6. log.WithFields(log.Fields{
    7. "animal": "walrus",
    8. }).Info("A walrus appears")
    9. }

    Often it’s helpful to have fields always attached to log statements in an application or parts of one. For example, you may want to always log the request_id and user_ip in the context of a request. Instead of writing log.WithFields(log.Fields{“request_id”: request_id, “user_ip”: user_ip}) on every line, you can create a logrus.Entry to pass around instead:

    1. requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})
    2. requestLogger.Info("something happened on that request") # will log request_id and user_ip
    3. requestLogger.Warn("something not great happened")

    Logrus has seven logging levels: Trace, Debug, Info, Warning, Error, Fatal and Panic.

    1. log.Trace("Something very low level.")
    2. log.Debug("Useful debugging information.")
    3. log.Info("Something noteworthy happened!")
    4. log.Warn("You should probably take a look at this.")
    5. log.Error("Something failed but I'm not quitting.")
    6. // Calls os.Exit(1) after logging
    7. log.Fatal("Bye.")
    8. // Calls panic() after logging
    9. log.Panic("I'm bailing.")

    You can set the logging level on a Logger, then it will only log entries with that severity or anything above it:

    1. // Will log anything that is info or above (warn, error, fatal, panic). Default.
    2. log.SetLevel(log.InfoLevel)

    Logrus can be transformed into an io.Writer. That writer is the end of an io.Pipe and it is your responsibility to close it.

    1. w := logger.Writer()
    2. defer w.Close()
    3. srv := http.Server{
    4. // create a stdlib log.Logger that writes to
    5. // logrus.Logger.
    6. ErrorLog: log.New(w, "", 0),
    7. }

    Each line written to that writer will be printed the usual way, using formatters and hooks. The level for those entries is info.
    This means that we can override the standard library logger easily:

    1. logger := logrus.New()
    2. logger.Formatter = &logrus.JSONFormatter{}
    3. // Use logrus for standard log output
    4. // Note that `log` here references stdlib's log
    5. // Not logrus imported under the name `log`.
    6. log.SetOutput(logger.Writer())