-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogger.go
More file actions
159 lines (135 loc) · 3.33 KB
/
Copy pathlogger.go
File metadata and controls
159 lines (135 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Package logger provides a thin wrapper around [zerolog].
package logger
import (
"context"
"io"
"os"
"sync"
"time"
"golang.org/x/term"
"github.com/rs/zerolog"
)
var (
DefaultLevel = zerolog.LevelInfoValue
DefaultTimeFormat = time.TimeOnly + ".000000"
)
type (
Context = zerolog.Context
Level = zerolog.Level
Logger = zerolog.Logger
Event = zerolog.Event
)
type Options struct {
Writer io.Writer
Level string
Timestamp bool
}
func init() {
// Serialize time fields as Unix timestamp integers in nanoseconds.
zerolog.TimeFieldFormat = zerolog.TimeFormatUnixNano
}
// New creates a new logger.
func New(options *Options) Logger {
if options == nil {
options = &Options{}
}
log := zerolog.New(options.writer())
level, err := zerolog.ParseLevel(options.level())
if err != nil {
log.Warn().Err(err).Msg("")
}
if level != zerolog.NoLevel {
log = log.Level(level)
}
if options.Timestamp {
log = log.With().Timestamp().Logger()
}
return log
}
func (o *Options) level() string {
if s := o.Level; s != "" {
return s
}
if s := os.Getenv("LOG_LEVEL"); s != "" {
return s
}
if s := os.Getenv("LL"); s != "" {
return s
}
return DefaultLevel
}
func (o *Options) writer() io.Writer {
if w := o.Writer; w != nil {
return w // caller supplied
}
return DefaultWriter()
}
// DefaultWriter returns the global default writer.
func DefaultWriter() io.Writer {
return defaultWriter()
}
var defaultWriter = sync.OnceValue(func() io.Writer {
if term.IsTerminal(int(os.Stdout.Fd())) {
return NewConsoleWriter() // pretty
}
return os.Stdout // raw JSON
})
var defaultConsoleWriterOptions = []func(w *zerolog.ConsoleWriter){
func(w *zerolog.ConsoleWriter) {
w.TimeFormat = DefaultTimeFormat
},
}
// NewConsoleWriter creates and initializes a new [zerolog.ConsoleWriter].
// Deprecated: Use [zerolog.NewConsoleWriter] instead.
func NewConsoleWriter(options ...func(w *zerolog.ConsoleWriter)) zerolog.ConsoleWriter {
options = append(defaultConsoleWriterOptions, options...)
return zerolog.NewConsoleWriter(options...)
}
// Ctx returns the Logger associated with the given context, or
// an appropriate (non-nil) default if the given context has no
// logger associated.
func Ctx(ctx context.Context) *Logger {
if ctx == nil {
panic("nil context")
}
return zerolog.Ctx(ctx)
}
// Contexter is the subset of [testing.T] et al used by TestCtx.
type Contexter interface {
Context() context.Context
}
// TestContext returns its receiver's context after associating a
// logger with it. It is intended for use with [testing.T] et al,
// for example:
//
// package pkg
//
// import (
// "testing"
// "gbenson.net/go/logger"
// )
//
// func TestSomething(t *testing.T) {
// ctx := logger.TestCtx(t)
// // ...
// logger.Ctx(ctx).Info().Msg("something happened")
// }
func TestContext(t Contexter) context.Context {
log := New(nil)
return log.WithContext(t.Context())
}
// TestCtx returns its receiver's context after associating a logger
// at debug level with it.
//
// Deprecated: Use [TestContext] instead.
func TestCtx(t Contexter) context.Context {
log := New(&Options{Level: "Debug"})
return log.WithContext(t.Context())
}
// LevelFor returns an appropriate level to log the given error at.
func LevelFor(err error) Level {
if IsRecoveredPanicError(err) {
return zerolog.PanicLevel
}
return zerolog.ErrorLevel
}