Zap logger add UUID to all logs in golang

Issue

I have this method used in a lambda:

import (
    "os"

    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
)

func InitLogger() *zap.Logger {
    config := zap.NewProductionEncoderConfig()
    config.EncodeTime = zapcore.RFC3339TimeEncoder
    consoleEncoder := zapcore.NewJSONEncoder(config)
    core := zapcore.NewTee(zapcore.NewCore(consoleEncoder, zapcore.AddSync(os.Stdout), zapcore.InfoLevel))
    return zap.New(core).With()
}

And in my lambda Handler i have:

var (
    log *zap.Logger
)

func init() {
    log = u.InitLogger()
}

func handler(r events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) {

    out, err := exec.Command("uuidgen").Output()
    uuid := strings.ReplaceAll(string(out), "\n", "")
    if err != nil {
        log.Error(err.Error())
    }

    log.Info("PRINT_1", zap.Any("uuid", uuid), zap.Any("Request", r.Body))
}

I have a question, is possible add the UUID to all logs without adding one by one?, because in each log that I need print something, I need add zap.Any("uuid", uuid)

The problem is that I need pass as parameter to all methods the UUID to print it in the log info, or error.

Solution

You will have to slightly re-arrange your code since you’re only creating the UUID in the handler, which implies it’s request-specific whilst the logger is global…

But the gist, specific to the library, is that you’ve got to create a child logger (which you are, in fact, already doing: you just need to pass the fields there). Any subsequent log writes to the child logger will include those fields.

For example:

func main() {
    logger := InitLogger(zap.String("foo", "bar"))
    logger.Info("First message with our `foo` key")
    logger.Info("Second message with our `foo` key")
}

func InitLogger(fields ...zap.Field) *zap.Logger {
    config := zap.NewProductionEncoderConfig()
    config.EncodeTime = zapcore.RFC3339TimeEncoder
    consoleEncoder := zapcore.NewJSONEncoder(config)
    core := zapcore.NewTee(zapcore.NewCore(consoleEncoder, zapcore.AddSync(os.Stdout), zapcore.InfoLevel))
    return zap.New(core).With(fields...)
}

Output:

{"level":"info","ts":"2022-11-24T18:30:45+01:00","msg":"First message with our `foo` key","foo":"bar"}
{"level":"info","ts":"2022-11-24T18:30:45+01:00","msg":"Second message with our `foo` key","foo":"bar"}

Answered By – Emile Pels

Answer Checked By – Marie Seifert (GoLangFix Admin)

Leave a Reply

Your email address will not be published.