simplelog/simplelog.go

135 lines
2.8 KiB
Go

package simplelog
import (
"context"
"log"
"runtime"
"log/slog"
"os"
"github.com/mattn/go-isatty"
)
var (
relpServerURL = os.Getenv("LOGGER_RELP_URL")
webhookURL = os.Getenv("LOGGER_WEBHOOK_URL")
)
var ourCustomLogger *slog.Logger
var ourCustomHandler slog.Handler
func init() {
ourCustomHandler = NewMultiplexHandler()
ourCustomLogger = slog.New(ourCustomHandler)
slog.SetDefault(ourCustomLogger)
}
type MultiplexHandler struct {
handlers []ExtendedHandler
}
func NewMultiplexHandler() slog.Handler {
cl := &MultiplexHandler{}
if isatty.IsTerminal(os.Stdout.Fd()) {
cl.handlers = append(cl.handlers, NewConsoleHandler())
} else {
cl.handlers = append(cl.handlers, NewJSONHandler())
}
if relpServerURL != "" {
handler, err := NewRELPHandler(relpServerURL)
if err != nil {
log.Fatalf("Failed to initialize RELP handler: %v", err)
}
cl.handlers = append(cl.handlers, handler)
}
if webhookURL != "" {
handler, err := NewWebhookHandler(webhookURL)
if err != nil {
log.Fatalf("Failed to initialize Webhook handler: %v", err)
}
cl.handlers = append(cl.handlers, handler)
}
return cl
}
func (cl *MultiplexHandler) Handle(ctx context.Context, record slog.Record) error {
for _, handler := range cl.handlers {
if err := handler.Handle(ctx, record); err != nil {
return err
}
}
return nil
}
func (cl *MultiplexHandler) Enabled(ctx context.Context, level slog.Level) bool {
// send us all events
return true
}
func (cl *MultiplexHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
newHandlers := make([]ExtendedHandler, len(cl.handlers))
for i, handler := range cl.handlers {
newHandlers[i] = handler.WithAttrs(attrs)
}
return &MultiplexHandler{handlers: newHandlers}
}
func (cl *MultiplexHandler) WithGroup(name string) slog.Handler {
newHandlers := make([]ExtendedHandler, len(cl.handlers))
for i, handler := range cl.handlers {
newHandlers[i] = handler.WithGroup(name)
}
return &MultiplexHandler{handlers: newHandlers}
}
type ExtendedEvent interface {
GetID() uuid.UUID
GetTimestamp() time.Time
GetLevel() string
GetMessage() string
GetData() json.RawMessage
GetFile() string
GetLine() int
}
type extendedEvent struct {
Event
File string `json:"file"`
Line int `json:"line"`
}
func (e extendedEvent) GetID() uuid.UUID {
return e.ID
}
func (e extendedEvent) GetTimestamp() time.Time {
return e.Timestamp
}
func (e extendedEvent) GetLevel() string {
return e.Level
}
func (e extendedEvent) GetMessage() string {
return e.Message
}
func (e extendedEvent) GetData() json.RawMessage {
return e.Data
}
func (e extendedEvent) GetFile() string {
return e.File
}
func (e extendedEvent) GetLine() int {
return e.Line
}
func NewExtendedEvent(baseEvent Event, file string, line int) ExtendedEvent {
return extendedEvent{
Event: baseEvent,
File: file,
Line: line,
}
}