forked from tangled.org/core
Monorepo for Tangled — https://tangled.org
1package log 2 3import ( 4 "context" 5 "log/slog" 6 "os" 7 8 "github.com/charmbracelet/log" 9) 10 11func NewHandler(name string) slog.Handler { 12 return log.NewWithOptions(os.Stderr, log.Options{ 13 ReportTimestamp: true, 14 Prefix: name, 15 Level: log.DebugLevel, 16 }) 17} 18 19func New(name string) *slog.Logger { 20 return slog.New(NewHandler(name)) 21} 22 23func NewContext(ctx context.Context, name string) context.Context { 24 return IntoContext(ctx, New(name)) 25} 26 27type ctxKey struct{} 28 29// IntoContext adds a logger to a context. Use FromContext to 30// pull the logger out. 31func IntoContext(ctx context.Context, l *slog.Logger) context.Context { 32 return context.WithValue(ctx, ctxKey{}, l) 33} 34 35// FromContext returns a logger from a context.Context; 36// if the passed context is nil, we return the default slog 37// logger. 38func FromContext(ctx context.Context) *slog.Logger { 39 if ctx != nil { 40 v := ctx.Value(ctxKey{}) 41 if v == nil { 42 return slog.Default() 43 } 44 return v.(*slog.Logger) 45 } 46 47 return slog.Default() 48} 49 50// sublogger derives a new logger from an existing one by appending a suffix to its prefix. 51func SubLogger(base *slog.Logger, suffix string) *slog.Logger { 52 // try to get the underlying charmbracelet logger 53 if cl, ok := base.Handler().(*log.Logger); ok { 54 prefix := cl.GetPrefix() 55 if prefix != "" { 56 prefix = prefix + "/" + suffix 57 } else { 58 prefix = suffix 59 } 60 return slog.New(NewHandler(prefix)) 61 } 62 63 // Fallback: no known handler type 64 return slog.New(NewHandler(suffix)) 65}