goa.design custom zerolog logger with HTTP Info, Warn and Error codes

Sun, Apr 21, 2024 2-minute read

goa.design custom zerolog logger with HTTP Info, Warn and Error codes

By default the goa logger isn’t great IMO. I like zerolog and have created a custom logger.

You could also use slog or zap, basically anything as long as it has these methods to implement the Logger interface.

package logger

import (
	"fmt"
	"os"

	"github.com/rs/zerolog"
)

// Logger is an adapted zerologger
type Logger struct {
	*zerolog.Logger
}

func New(serviceName string, isDebug, isConsole bool) *Logger {
	logLevel := zerolog.InfoLevel
	if isDebug {
		logLevel = zerolog.DebugLevel
	}
	zerolog.SetGlobalLevel(logLevel)
	svclogger := zerolog.New(os.Stderr).With().Timestamp().Str("service", serviceName).Logger()
	if isConsole {
		svclogger = zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout}).
			With().
			Timestamp().
			Str("service", serviceName).
			Logger()
	}
	return &Logger{&svclogger}
}

// Log is called by the log middleware to log HTTP requests key values
func (logger *Logger) Log(keyvals ...interface{}) error {
	fields := FormatFields(keyvals)
  // If this isn't here, all HTTP requests get a zerolog.Info() block
  // which is super confusing when a request is a 5xx so I've overridden it
	if status, ok := fields["status"].(int); ok {
		s := status / 100
		switch s {
		case 4:
			logger.Warn().Fields(fields).Msgf("HTTP Request")
			return nil
		case 5:
			logger.Error().Fields(fields).Msgf("HTTP Request")
			return nil
		}
	}
	logger.Info().Fields(fields).Msgf("HTTP Request")
	return nil
}

// FormatFields formats input keyvals
// ref: https://github.com/goadesign/goa/blob/v1/logging/logrus/adapter.go#L64
func FormatFields(keyvals []interface{}) map[string]interface{} {
	n := (len(keyvals) + 1) / 2
	res := make(map[string]interface{}, n)
	for i := 0; i < len(keyvals); i += 2 {
		k := keyvals[i]
		var v interface{}
		if i+1 < len(keyvals) {
			v = keyvals[i+1]
		}
		res[fmt.Sprintf("%v", k)] = v
	}
	return res
}

Tags:

#zerolog #go #goa