How to do it...

These steps cover the writing and running of your application:

  1. From your Terminal/console application, create a new directory called ~/projects/go-programming-cookbook/chapter4/structured and navigate to this directory.
  2. Run the following command:
$ go mod init github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter4/structured

You should see a file called go.mod that contains the following:

module github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter4/structured    
  1. Copy tests from ~/projects/go-programming-cookbook-original/chapter4/structured, or use this as an exercise to write some of your own code!
  2. Create a file called logrus.go with the following content:
        package structured

import "github.com/sirupsen/logrus"

// Hook will implement the logrus
// hook interface
type Hook struct {
id string
}

// Fire will trigger whenever you log
func (hook *Hook) Fire(entry *logrus.Entry) error {
entry.Data["id"] = hook.id
return nil
}

// Levels is what levels this hook will fire on
func (hook *Hook) Levels() []logrus.Level {
return logrus.AllLevels
}

// Logrus demonstrates some basic logrus functionality
func Logrus() {
// we're emitting in json format
logrus.SetFormatter(&logrus.TextFormatter{})
logrus.SetLevel(logrus.InfoLevel)
logrus.AddHook(&Hook{"123"})

fields := logrus.Fields{}
fields["success"] = true
fields["complex_struct"] = struct {
Event string
When string
}{"Something happened", "Just now"}

x := logrus.WithFields(fields)
x.Warn("warning!")
x.Error("error!")
}
  1. Create a file called apex.go with the following content:
        package structured

import (
"errors"
"os"

"github.com/apex/log"
"github.com/apex/log/handlers/text"
)

// ThrowError throws an error that we'll trace
func ThrowError() error {
err := errors.New("a crazy failure")
log.WithField("id", "123").Trace("ThrowError").Stop(&err)
return err
}

// CustomHandler splits to two streams
type CustomHandler struct {
id string
handler log.Handler
}

// HandleLog adds a hook and does the emitting
func (h *CustomHandler) HandleLog(e *log.Entry) error {
e.WithField("id", h.id)
return h.handler.HandleLog(e)
}

// Apex has a number of useful tricks
func Apex() {
log.SetHandler(&CustomHandler{"123", text.New(os.Stdout)})
err := ThrowError()

//With error convenience function
log.WithError(err).Error("an error occurred")
}
  1. Create a new directory named example and navigate to it.
  2. Create a main.go file with the following content:
        package main

import (
"fmt"

"github.com/PacktPublishing/
Go-Programming-Cookbook-Second-Edition/
chapter4/structured"
)

func main() {
fmt.Println("Logrus:")
structured.Logrus()

fmt.Println()
fmt.Println("Apex:")
structured.Apex()
}
  1. Run go run main.go.
  2. You may also run the following commands:
$ go build
$ ./example

You should now see the following output:

$ go run main.go
Logrus:
WARN[0000] warning! complex_struct={Something happened Just now}
id=123 success=true

ERRO[0000] error! complex_struct={Something happened Just now}
id=123 success=true


Apex:
INFO[0000] ThrowError id=123
ERROR[0000] ThrowError duration=133ns error=a crazy failure
id=123
ERROR[0000] an error occurred error=a crazy failure
  1. The go.mod file should be updated and the go.sum file should now be present in the top-level recipe directory.
  2. If you copied or wrote your own tests, then go up one directory and run go test. Ensure that all the tests pass.