Skip to content
Snippets Groups Projects
Commit 4bb09063 authored by Jack Robertson's avatar Jack Robertson
Browse files

refactor: move slog package to root, add configuration options and tests

parent 5d7a7776
No related branches found
Tags v1.5.5
1 merge request!1Refactor library to idiomatic go
package slog
import (
"golang.org/x/exp/slog"
"io"
)
type Options struct {
Leveler slog.Leveler
Writer io.Writer
}
type Option func(*Options)
func WithLeveler(leveler slog.Leveler) Option {
return func(o *Options) {
o.Leveler = leveler
}
}
func WithWriter(writer io.Writer) Option {
return func(o *Options) {
o.Writer = writer
}
}
......@@ -6,36 +6,46 @@ import (
"strings"
)
func InitLogger() *slog.Logger {
// Could set logger level via ENV vars in future.
programLevel := new(slog.LevelVar)
programLevel.Set(slog.LevelDebug)
func New(opts ...Option) *slog.Logger {
options := &Options{
Leveler: slog.LevelDebug,
Writer: os.Stdout,
}
for _, opt := range opts {
opt(options)
}
// Attributes modified for datadog schema via HandlerOptions.ReplaceAttr
// Per recommendation at https://pkg.go.dev/golang.org/x/exp/slog#JSONHandler
// See datadog: https://docs.datadoghq.com/logs/log_configuration/attributes_naming_convention/#reserved-attributes
loggerReplace := func(groups []string, a slog.Attr) slog.Attr {
if a.Key == "msg" {
a.Key = "message"
replaceAttr := func(groups []string, attr slog.Attr) slog.Attr {
if attr.Key == "msg" {
attr.Key = "message"
}
if a.Key == "time" {
a.Key = "date"
if attr.Key == "time" {
attr.Key = "date"
}
if a.Key == "level" {
a.Key = "status"
a.Value = slog.StringValue(strings.ToLower(a.Value.String()))
if attr.Key == "level" {
attr.Key = "status"
attr.Value = slog.StringValue(strings.ToLower(attr.Value.String()))
}
return a
return attr
}
logger := slog.New(slog.NewJSONHandler(os.Stdout,
&slog.HandlerOptions{Level: programLevel, AddSource: true, ReplaceAttr: loggerReplace}))
hostname, hostnameErr := os.Hostname()
if hostnameErr == nil {
logger = logger.With("host", hostname)
handlerOptions := &slog.HandlerOptions{
Level: options.Leveler,
AddSource: true,
ReplaceAttr: replaceAttr,
}
logHandler := slog.NewJSONHandler(options.Writer, handlerOptions)
logger := slog.New(logHandler)
hostname, err := os.Hostname()
if err != nil {
logger.Error("Failed to get hostname.", slog.String("error", err.Error()))
} else {
logger.Error("Failed to get hostname.", slog.String("error", hostnameErr.Error()))
logger = logger.With("host", hostname)
}
logger.Info("Initialised.")
return logger
}
package slog
import (
"bufio"
"bytes"
"encoding/json"
"golang.org/x/exp/slog"
"testing"
)
func TestNew(t *testing.T) {
var buf bytes.Buffer
logger := New(WithWriter(&buf))
logger.Info("Foo", slog.String("bar", "baz"))
logger.Error("Bar", slog.String("baz", "qux"))
scanner := bufio.NewScanner(&buf)
// Scan the first log.
scanner.Scan()
infoLog := scanner.Bytes()
var infoLogMap map[string]any
if err := json.Unmarshal(infoLog, &infoLogMap); err != nil {
t.Errorf("Failed to unmarshal info log: %s", err.Error())
}
t.Log(infoLogMap)
if infoLogMap["status"] != "info" {
t.Errorf("Expected info log level, got %s", infoLogMap["level"])
}
if infoLogMap["bar"] != "baz" {
t.Errorf("Expected bar=baz, got %s", infoLogMap["bar"])
}
}
package main
import (
"gitlab.nexdev.uk/pub/go-slog/src/slog"
)
func main() {
logger := slog.InitLogger()
logger.Info("Logger test.")
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment