1
2 package log
3
4 import (
5 "context"
6 "log"
7 stdlog "log"
8 "os"
9 "runtime/debug"
10 "testing"
11
12 "cdr.dev/slog"
13 "cdr.dev/slog/sloggers/sloghuman"
14 "cdr.dev/slog/sloggers/slogtest"
15
16 "oss.terrastruct.com/d2/lib/env"
17 )
18
19 var _default = slog.Make(sloghuman.Sink(os.Stderr)).Named("default")
20
21 func Init() {
22 stdlib := slog.Stdlib(context.Background(), _default, slog.LevelInfo)
23 log.SetOutput(stdlib.Writer())
24 }
25
26 type loggerKey struct{}
27
28 func from(ctx context.Context) slog.Logger {
29 l, ok := ctx.Value(loggerKey{}).(slog.Logger)
30 if !ok {
31 _default.Warn(ctx, "missing slog.Logger in context, see lib/log.With", slog.F("stack", string(debug.Stack())))
32 return _default
33 }
34 return l
35 }
36
37 func With(ctx context.Context, l slog.Logger) context.Context {
38 return context.WithValue(ctx, loggerKey{}, l)
39 }
40
41
42 func WithTB(ctx context.Context, t testing.TB, opts *slogtest.Options) context.Context {
43 l := slogtest.Make(t, opts)
44 if env.Debug() {
45 l = l.Leveled(slog.LevelDebug)
46 }
47 return With(ctx, l)
48 }
49
50 func Debug(ctx context.Context, msg string, fields ...slog.Field) {
51 slog.Helper()
52 from(ctx).Debug(ctx, msg, fields...)
53 }
54
55 func Info(ctx context.Context, msg string, fields ...slog.Field) {
56 slog.Helper()
57 from(ctx).Info(ctx, msg, fields...)
58 }
59
60 func Warn(ctx context.Context, msg string, fields ...slog.Field) {
61 slog.Helper()
62 from(ctx).Warn(ctx, msg, fields...)
63 }
64
65 func Error(ctx context.Context, msg string, fields ...slog.Field) {
66 slog.Helper()
67 from(ctx).Error(ctx, msg, fields...)
68 }
69
70 func Critical(ctx context.Context, msg string, fields ...slog.Field) {
71 slog.Helper()
72 from(ctx).Critical(ctx, msg, fields...)
73 }
74
75 func Fatal(ctx context.Context, msg string, fields ...slog.Field) {
76 slog.Helper()
77 from(ctx).Fatal(ctx, msg, fields...)
78 }
79
80 func Named(ctx context.Context, name string) context.Context {
81 return With(ctx, from(ctx).Named(name))
82 }
83
84 func Leveled(ctx context.Context, level slog.Level) context.Context {
85 return With(ctx, from(ctx).Leveled(level))
86 }
87
88 func AppendSinks(ctx context.Context, s ...slog.Sink) context.Context {
89 return With(ctx, from(ctx).AppendSinks(s...))
90 }
91
92 func Sync(ctx context.Context) {
93 from(ctx).Sync()
94 }
95
96 func Stdlib(ctx context.Context, level slog.Level) *log.Logger {
97 return slog.Stdlib(ctx, from(ctx), level)
98 }
99
100 func Fork(ctx, loggerCtx context.Context) context.Context {
101 return With(ctx, from(loggerCtx))
102 }
103
104 func Stderr(ctx context.Context) context.Context {
105 l := slog.Make(sloghuman.Sink(os.Stderr))
106 if os.Getenv("DEBUG") == "1" {
107 l = l.Leveled(slog.LevelDebug)
108 }
109
110 sl := slog.Stdlib(ctx, l, slog.LevelInfo)
111 stdlog.SetOutput(sl.Writer())
112
113 return With(ctx, l)
114 }
115
View as plain text