Compare commits
5 Commits
7ace1f791c
...
64c1cac4d2
Author | SHA1 | Date | |
---|---|---|---|
64c1cac4d2 | |||
de83620d6b | |||
51964ac5e6 | |||
00ecef45b5 | |||
bcff73f576 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -25,3 +25,6 @@ go.work.sum
|
|||||||
# env file
|
# env file
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
|
||||||
|
.idea
|
||||||
|
|
||||||
|
13
go.mod
Normal file
13
go.mod
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module git.flexabyte.io/flexabyte/go-slogd
|
||||||
|
|
||||||
|
go 1.24.2
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/samber/slog-formatter v1.2.0
|
||||||
|
github.com/samber/slog-multi v1.4.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/samber/lo v1.49.1 // indirect
|
||||||
|
golang.org/x/text v0.24.0 // indirect
|
||||||
|
)
|
10
go.sum
Normal file
10
go.sum
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
|
||||||
|
github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
|
||||||
|
github.com/samber/slog-formatter v1.2.0 h1:gTSHm4CxyySyhcxRkzk21CSKbGCdZVipbRMhINkNtQU=
|
||||||
|
github.com/samber/slog-formatter v1.2.0/go.mod h1:hgjhSd5Vf69XCOnVp0UW0QHCxJ8iDEm/qASjji6FNoI=
|
||||||
|
github.com/samber/slog-multi v1.4.0 h1:pwlPMIE7PrbTHQyKWDU+RIoxP1+HKTNOujk3/kdkbdg=
|
||||||
|
github.com/samber/slog-multi v1.4.0/go.mod h1:FsQ4Uv2L+E/8TZt+/BVgYZ1LoDWCbfCU21wVIoMMrO8=
|
||||||
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
|
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||||
|
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
32
pkg/slogd/disabledHandler.go
Normal file
32
pkg/slogd/disabledHandler.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package slogd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log/slog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newDisabledHandler() slog.Handler {
|
||||||
|
return &disabledHandler{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerDisabledHandler(activate bool) {
|
||||||
|
RegisterSink(handlerDisabled, newDisabledHandler(), activate)
|
||||||
|
}
|
||||||
|
|
||||||
|
type disabledHandler struct{}
|
||||||
|
|
||||||
|
func (h *disabledHandler) Handle(ctx context.Context, r slog.Record) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *disabledHandler) Enabled(ctx context.Context, level slog.Level) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *disabledHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *disabledHandler) WithGroup(group string) slog.Handler {
|
||||||
|
return h
|
||||||
|
}
|
10
pkg/slogd/jsonHandler.go
Normal file
10
pkg/slogd/jsonHandler.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package slogd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"log/slog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterJSONHandler(w io.Writer, activate bool) {
|
||||||
|
RegisterSink(HandlerJSON, slog.NewJSONHandler(w, HandlerOptions()), activate)
|
||||||
|
}
|
56
pkg/slogd/level.go
Normal file
56
pkg/slogd/level.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package slogd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LevelTrace = slog.Level(-8)
|
||||||
|
LevelDebug = slog.LevelDebug
|
||||||
|
LevelInfo = slog.LevelInfo
|
||||||
|
LevelNotice = slog.Level(2)
|
||||||
|
LevelWarn = slog.LevelWarn
|
||||||
|
LevelError = slog.LevelError
|
||||||
|
LevelFatal = slog.Level(12)
|
||||||
|
LevelDefault = LevelInfo
|
||||||
|
)
|
||||||
|
|
||||||
|
var levelNames = map[slog.Leveler]string{
|
||||||
|
LevelTrace: "TRACE",
|
||||||
|
LevelDebug: "DEBUG",
|
||||||
|
LevelInfo: "INFO",
|
||||||
|
LevelNotice: "NOTICE",
|
||||||
|
LevelWarn: "WARN",
|
||||||
|
LevelError: "ERROR",
|
||||||
|
LevelFatal: "FATAL",
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReplaceAttrs(groups []string, a slog.Attr) slog.Attr {
|
||||||
|
if a.Key == slog.LevelKey {
|
||||||
|
a.Value = slog.StringValue(LevelName(a.Value.Any().(slog.Level)))
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func Level(l string) slog.Level {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
for k, v := range levelNames {
|
||||||
|
if strings.ToUpper(l) == v {
|
||||||
|
return k.Level()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LevelDefault
|
||||||
|
}
|
||||||
|
|
||||||
|
func LevelName(l slog.Level) string {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
for k, v := range levelNames {
|
||||||
|
if k == l {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return levelNames[LevelDefault]
|
||||||
|
}
|
140
pkg/slogd/slogd.go
Normal file
140
pkg/slogd/slogd.go
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
package slogd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log/slog"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
slogformatter "github.com/samber/slog-formatter"
|
||||||
|
slogmulti "github.com/samber/slog-multi"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
HandlerText string = "text"
|
||||||
|
HandlerJSON string = "json"
|
||||||
|
handlerDisabled string = "disabled"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
FlowFanOut Flow = iota
|
||||||
|
FlowPipeline
|
||||||
|
FlowRouting
|
||||||
|
FlowFailOver
|
||||||
|
FlowLoadBalancing
|
||||||
|
)
|
||||||
|
|
||||||
|
type Flow int
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctxKey = contextKey{}
|
||||||
|
)
|
||||||
|
var (
|
||||||
|
handlers = make(map[string]slog.Handler)
|
||||||
|
activeHandler string
|
||||||
|
level = new(slog.LevelVar)
|
||||||
|
formatters []slogformatter.Formatter
|
||||||
|
middlewares []slogmulti.Middleware
|
||||||
|
source bool
|
||||||
|
logger *slog.Logger
|
||||||
|
mux = &sync.Mutex{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func ActiveHandler() string {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
return activeHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func Key() contextKey {
|
||||||
|
return ctxKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func Disable() {
|
||||||
|
UseHandler(handlerDisabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromContext(ctx context.Context) *slog.Logger {
|
||||||
|
if l, ok := ctx.Value(Key()).(*slog.Logger); ok {
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
return Logger()
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandlerOptions() *slog.HandlerOptions {
|
||||||
|
return &slog.HandlerOptions{
|
||||||
|
AddSource: source,
|
||||||
|
Level: level,
|
||||||
|
ReplaceAttr: ReplaceAttrs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init(l slog.Level, addSource bool) {
|
||||||
|
level.Set(l)
|
||||||
|
source = addSource
|
||||||
|
}
|
||||||
|
|
||||||
|
func Logger() *slog.Logger {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
|
||||||
|
if logger == nil {
|
||||||
|
logger = slog.New(handlers[handlerDisabled])
|
||||||
|
}
|
||||||
|
return logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetLevel(l slog.Level) {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
level.Set(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterFormatter(f slogformatter.Formatter) {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
formatters = append(formatters, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterMiddleware(h slogmulti.Middleware) {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
middlewares = append(middlewares, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterSink(name string, h slog.Handler, activate bool) {
|
||||||
|
mux.Lock()
|
||||||
|
handlers[name] = h
|
||||||
|
mux.Unlock()
|
||||||
|
|
||||||
|
if activate {
|
||||||
|
UseHandler(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func UseHandler(name string) {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
if _, ok := handlers[name]; !ok {
|
||||||
|
Logger().LogAttrs(context.Background(), LevelError, "could not find handler", slog.String("name", name))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
formatterPipe := slogformatter.NewFormatterMiddleware(formatters...)
|
||||||
|
pipe := slogmulti.Pipe(middlewares...).Pipe(formatterPipe)
|
||||||
|
handler := slogmulti.Fanout(handlers[name])
|
||||||
|
|
||||||
|
logger = slog.New(pipe.Handler(handler))
|
||||||
|
activeHandler = name
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithContext(ctx context.Context) context.Context {
|
||||||
|
return context.WithValue(ctx, Key(), Logger())
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// RegisterFormatter(LevelFormatter())
|
||||||
|
// RegisterMiddleware(NewLevelMiddleware())
|
||||||
|
registerDisabledHandler(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
type contextKey struct{}
|
10
pkg/slogd/textHandler.go
Normal file
10
pkg/slogd/textHandler.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package slogd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"log/slog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterTextHandler(w io.Writer, activate bool) {
|
||||||
|
RegisterSink(HandlerText, slog.NewTextHandler(w, HandlerOptions()), activate)
|
||||||
|
}
|
Reference in New Issue
Block a user