Skip to content
Snippets Groups Projects
Commit 53bf6b94 authored by John Harris's avatar John Harris
Browse files

Merge branch 'refactor' into main

parents 5d7a7776 4bb09063
No related branches found
No related tags found
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 ( ...@@ -6,36 +6,46 @@ import (
"strings" "strings"
) )
func InitLogger() *slog.Logger { func New(opts ...Option) *slog.Logger {
// Could set logger level via ENV vars in future. options := &Options{
programLevel := new(slog.LevelVar) Leveler: slog.LevelDebug,
programLevel.Set(slog.LevelDebug) Writer: os.Stdout,
}
for _, opt := range opts {
opt(options)
}
// Attributes modified for datadog schema via HandlerOptions.ReplaceAttr // Attributes modified for datadog schema via HandlerOptions.ReplaceAttr
// Per recommendation at https://pkg.go.dev/golang.org/x/exp/slog#JSONHandler // 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 // See datadog: https://docs.datadoghq.com/logs/log_configuration/attributes_naming_convention/#reserved-attributes
loggerReplace := func(groups []string, a slog.Attr) slog.Attr { replaceAttr := func(groups []string, attr slog.Attr) slog.Attr {
if a.Key == "msg" { if attr.Key == "msg" {
a.Key = "message" attr.Key = "message"
} }
if a.Key == "time" { if attr.Key == "time" {
a.Key = "date" attr.Key = "date"
} }
if a.Key == "level" { if attr.Key == "level" {
a.Key = "status" attr.Key = "status"
a.Value = slog.StringValue(strings.ToLower(a.Value.String())) 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})) handlerOptions := &slog.HandlerOptions{
hostname, hostnameErr := os.Hostname() Level: options.Leveler,
if hostnameErr == nil { AddSource: true,
logger = logger.With("host", hostname) 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 { } else {
logger.Error("Failed to get hostname.", slog.String("error", hostnameErr.Error())) logger = logger.With("host", hostname)
} }
logger.Info("Initialised.")
return logger 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