log.go (2673B)
1 // MIT License 2 // 3 // Copyright (c) 2025 Anirudh Oppiliappan, Akshay Oppiliappan and 4 // contributors. 5 // 6 // Permission is hereby granted, free of charge, to any person obtaining a copy 7 // of this software and associated documentation files (the "Software"), to deal 8 // in the Software without restriction, including without limitation the rights 9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 // copies of the Software, and to permit persons to whom the Software is 11 // furnished to do so, subject to the following conditions: 12 // 13 // The above copyright notice and this permission notice shall be included in all 14 // copies or substantial portions of the Software. 15 // 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 // SOFTWARE. 23 24 package log 25 26 import ( 27 "context" 28 "log/slog" 29 "os" 30 31 "github.com/charmbracelet/log" 32 ) 33 34 func NewHandler(name string) slog.Handler { 35 return log.NewWithOptions(os.Stderr, log.Options{ 36 ReportTimestamp: true, 37 Prefix: name, 38 Level: log.DebugLevel, 39 }) 40 } 41 42 func New(name string) *slog.Logger { 43 return slog.New(NewHandler(name)) 44 } 45 46 func NewContext(ctx context.Context, name string) context.Context { 47 return IntoContext(ctx, New(name)) 48 } 49 50 type ctxKey struct{} 51 52 // IntoContext adds a logger to a context. Use FromContext to 53 // pull the logger out. 54 func IntoContext(ctx context.Context, l *slog.Logger) context.Context { 55 return context.WithValue(ctx, ctxKey{}, l) 56 } 57 58 // FromContext returns a logger from a context.Context; 59 // if the passed context is nil, we return the default slog 60 // logger. 61 func FromContext(ctx context.Context) *slog.Logger { 62 if ctx != nil { 63 v := ctx.Value(ctxKey{}) 64 if v == nil { 65 return slog.Default() 66 } 67 return v.(*slog.Logger) 68 } 69 70 return slog.Default() 71 } 72 73 // sublogger derives a new logger from an existing one by appending a suffix to its prefix. 74 func SubLogger(base *slog.Logger, suffix string) *slog.Logger { 75 // try to get the underlying charmbracelet logger 76 if cl, ok := base.Handler().(*log.Logger); ok { 77 prefix := cl.GetPrefix() 78 if prefix != "" { 79 prefix = prefix + "/" + suffix 80 } else { 81 prefix = suffix 82 } 83 return slog.New(NewHandler(prefix)) 84 } 85 86 // Fallback: no known handler type 87 return slog.New(NewHandler(suffix)) 88 }