1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package log implements a simple logging package. It defines a type, [Logger],
6// with methods for formatting output. It also has a predefined 'standard'
7// Logger accessible through helper functions Print[f|ln], Fatal[f|ln], and
8// Panic[f|ln], which are easier to use than creating a Logger manually.
9// That logger writes to standard error and prints the date and time
10// of each logged message.
11// Every log message is output on a separate line: if the message being
12// printed does not end in a newline, the logger will add one.
13// The Fatal functions call [os.Exit](1) after writing the log message.
14// The Panic functions call panic after writing the log message.
15package log
16
17import (
18	"fmt"
19	"io"
20	"log/internal"
21	"os"
22	"runtime"
23	"sync"
24	"sync/atomic"
25	"time"
26)
27
28// These flags define which text to prefix to each log entry generated by the [Logger].
29// Bits are or'ed together to control what's printed.
30// With the exception of the Lmsgprefix flag, there is no
31// control over the order they appear (the order listed here)
32// or the format they present (as described in the comments).
33// The prefix is followed by a colon only when Llongfile or Lshortfile
34// is specified.
35// For example, flags Ldate | Ltime (or LstdFlags) produce,
36//
37//	2009/01/23 01:23:23 message
38//
39// while flags Ldate | Ltime | Lmicroseconds | Llongfile produce,
40//
41//	2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
42const (
43	Ldate         = 1 << iota     // the date in the local time zone: 2009/01/23
44	Ltime                         // the time in the local time zone: 01:23:23
45	Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  assumes Ltime.
46	Llongfile                     // full file name and line number: /a/b/c/d.go:23
47	Lshortfile                    // final file name element and line number: d.go:23. overrides Llongfile
48	LUTC                          // if Ldate or Ltime is set, use UTC rather than the local time zone
49	Lmsgprefix                    // move the "prefix" from the beginning of the line to before the message
50	LstdFlags     = Ldate | Ltime // initial values for the standard logger
51)
52
53// A Logger represents an active logging object that generates lines of
54// output to an [io.Writer]. Each logging operation makes a single call to
55// the Writer's Write method. A Logger can be used simultaneously from
56// multiple goroutines; it guarantees to serialize access to the Writer.
57type Logger struct {
58	outMu sync.Mutex
59	out   io.Writer // destination for output
60
61	prefix    atomic.Pointer[string] // prefix on each line to identify the logger (but see Lmsgprefix)
62	flag      atomic.Int32           // properties
63	isDiscard atomic.Bool
64}
65
66// New creates a new [Logger]. The out variable sets the
67// destination to which log data will be written.
68// The prefix appears at the beginning of each generated log line, or
69// after the log header if the [Lmsgprefix] flag is provided.
70// The flag argument defines the logging properties.
71func New(out io.Writer, prefix string, flag int) *Logger {
72	l := new(Logger)
73	l.SetOutput(out)
74	l.SetPrefix(prefix)
75	l.SetFlags(flag)
76	return l
77}
78
79// SetOutput sets the output destination for the logger.
80func (l *Logger) SetOutput(w io.Writer) {
81	l.outMu.Lock()
82	defer l.outMu.Unlock()
83	l.out = w
84	l.isDiscard.Store(w == io.Discard)
85}
86
87var std = New(os.Stderr, "", LstdFlags)
88
89// Default returns the standard logger used by the package-level output functions.
90func Default() *Logger { return std }
91
92// Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
93func itoa(buf *[]byte, i int, wid int) {
94	// Assemble decimal in reverse order.
95	var b [20]byte
96	bp := len(b) - 1
97	for i >= 10 || wid > 1 {
98		wid--
99		q := i / 10
100		b[bp] = byte('0' + i - q*10)
101		bp--
102		i = q
103	}
104	// i < 10
105	b[bp] = byte('0' + i)
106	*buf = append(*buf, b[bp:]...)
107}
108
109// formatHeader writes log header to buf in following order:
110//   - l.prefix (if it's not blank and Lmsgprefix is unset),
111//   - date and/or time (if corresponding flags are provided),
112//   - file and line number (if corresponding flags are provided),
113//   - l.prefix (if it's not blank and Lmsgprefix is set).
114func formatHeader(buf *[]byte, t time.Time, prefix string, flag int, file string, line int) {
115	if flag&Lmsgprefix == 0 {
116		*buf = append(*buf, prefix...)
117	}
118	if flag&(Ldate|Ltime|Lmicroseconds) != 0 {
119		if flag&LUTC != 0 {
120			t = t.UTC()
121		}
122		if flag&Ldate != 0 {
123			year, month, day := t.Date()
124			itoa(buf, year, 4)
125			*buf = append(*buf, '/')
126			itoa(buf, int(month), 2)
127			*buf = append(*buf, '/')
128			itoa(buf, day, 2)
129			*buf = append(*buf, ' ')
130		}
131		if flag&(Ltime|Lmicroseconds) != 0 {
132			hour, min, sec := t.Clock()
133			itoa(buf, hour, 2)
134			*buf = append(*buf, ':')
135			itoa(buf, min, 2)
136			*buf = append(*buf, ':')
137			itoa(buf, sec, 2)
138			if flag&Lmicroseconds != 0 {
139				*buf = append(*buf, '.')
140				itoa(buf, t.Nanosecond()/1e3, 6)
141			}
142			*buf = append(*buf, ' ')
143		}
144	}
145	if flag&(Lshortfile|Llongfile) != 0 {
146		if flag&Lshortfile != 0 {
147			short := file
148			for i := len(file) - 1; i > 0; i-- {
149				if file[i] == '/' {
150					short = file[i+1:]
151					break
152				}
153			}
154			file = short
155		}
156		*buf = append(*buf, file...)
157		*buf = append(*buf, ':')
158		itoa(buf, line, -1)
159		*buf = append(*buf, ": "...)
160	}
161	if flag&Lmsgprefix != 0 {
162		*buf = append(*buf, prefix...)
163	}
164}
165
166var bufferPool = sync.Pool{New: func() any { return new([]byte) }}
167
168func getBuffer() *[]byte {
169	p := bufferPool.Get().(*[]byte)
170	*p = (*p)[:0]
171	return p
172}
173
174func putBuffer(p *[]byte) {
175	// Proper usage of a sync.Pool requires each entry to have approximately
176	// the same memory cost. To obtain this property when the stored type
177	// contains a variably-sized buffer, we add a hard limit on the maximum buffer
178	// to place back in the pool.
179	//
180	// See https://go.dev/issue/23199
181	if cap(*p) > 64<<10 {
182		*p = nil
183	}
184	bufferPool.Put(p)
185}
186
187// Output writes the output for a logging event. The string s contains
188// the text to print after the prefix specified by the flags of the
189// Logger. A newline is appended if the last character of s is not
190// already a newline. Calldepth is used to recover the PC and is
191// provided for generality, although at the moment on all pre-defined
192// paths it will be 2.
193func (l *Logger) Output(calldepth int, s string) error {
194	calldepth++ // +1 for this frame.
195	return l.output(0, calldepth, func(b []byte) []byte {
196		return append(b, s...)
197	})
198}
199
200// output can take either a calldepth or a pc to get source line information.
201// It uses the pc if it is non-zero.
202func (l *Logger) output(pc uintptr, calldepth int, appendOutput func([]byte) []byte) error {
203	if l.isDiscard.Load() {
204		return nil
205	}
206
207	now := time.Now() // get this early.
208
209	// Load prefix and flag once so that their value is consistent within
210	// this call regardless of any concurrent changes to their value.
211	prefix := l.Prefix()
212	flag := l.Flags()
213
214	var file string
215	var line int
216	if flag&(Lshortfile|Llongfile) != 0 {
217		if pc == 0 {
218			var ok bool
219			_, file, line, ok = runtime.Caller(calldepth)
220			if !ok {
221				file = "???"
222				line = 0
223			}
224		} else {
225			fs := runtime.CallersFrames([]uintptr{pc})
226			f, _ := fs.Next()
227			file = f.File
228			if file == "" {
229				file = "???"
230			}
231			line = f.Line
232		}
233	}
234
235	buf := getBuffer()
236	defer putBuffer(buf)
237	formatHeader(buf, now, prefix, flag, file, line)
238	*buf = appendOutput(*buf)
239	if len(*buf) == 0 || (*buf)[len(*buf)-1] != '\n' {
240		*buf = append(*buf, '\n')
241	}
242
243	l.outMu.Lock()
244	defer l.outMu.Unlock()
245	_, err := l.out.Write(*buf)
246	return err
247}
248
249func init() {
250	internal.DefaultOutput = func(pc uintptr, data []byte) error {
251		return std.output(pc, 0, func(buf []byte) []byte {
252			return append(buf, data...)
253		})
254	}
255}
256
257// Print calls l.Output to print to the logger.
258// Arguments are handled in the manner of [fmt.Print].
259func (l *Logger) Print(v ...any) {
260	l.output(0, 2, func(b []byte) []byte {
261		return fmt.Append(b, v...)
262	})
263}
264
265// Printf calls l.Output to print to the logger.
266// Arguments are handled in the manner of [fmt.Printf].
267func (l *Logger) Printf(format string, v ...any) {
268	l.output(0, 2, func(b []byte) []byte {
269		return fmt.Appendf(b, format, v...)
270	})
271}
272
273// Println calls l.Output to print to the logger.
274// Arguments are handled in the manner of [fmt.Println].
275func (l *Logger) Println(v ...any) {
276	l.output(0, 2, func(b []byte) []byte {
277		return fmt.Appendln(b, v...)
278	})
279}
280
281// Fatal is equivalent to l.Print() followed by a call to [os.Exit](1).
282func (l *Logger) Fatal(v ...any) {
283	l.Output(2, fmt.Sprint(v...))
284	os.Exit(1)
285}
286
287// Fatalf is equivalent to l.Printf() followed by a call to [os.Exit](1).
288func (l *Logger) Fatalf(format string, v ...any) {
289	l.Output(2, fmt.Sprintf(format, v...))
290	os.Exit(1)
291}
292
293// Fatalln is equivalent to l.Println() followed by a call to [os.Exit](1).
294func (l *Logger) Fatalln(v ...any) {
295	l.Output(2, fmt.Sprintln(v...))
296	os.Exit(1)
297}
298
299// Panic is equivalent to l.Print() followed by a call to panic().
300func (l *Logger) Panic(v ...any) {
301	s := fmt.Sprint(v...)
302	l.Output(2, s)
303	panic(s)
304}
305
306// Panicf is equivalent to l.Printf() followed by a call to panic().
307func (l *Logger) Panicf(format string, v ...any) {
308	s := fmt.Sprintf(format, v...)
309	l.Output(2, s)
310	panic(s)
311}
312
313// Panicln is equivalent to l.Println() followed by a call to panic().
314func (l *Logger) Panicln(v ...any) {
315	s := fmt.Sprintln(v...)
316	l.Output(2, s)
317	panic(s)
318}
319
320// Flags returns the output flags for the logger.
321// The flag bits are [Ldate], [Ltime], and so on.
322func (l *Logger) Flags() int {
323	return int(l.flag.Load())
324}
325
326// SetFlags sets the output flags for the logger.
327// The flag bits are [Ldate], [Ltime], and so on.
328func (l *Logger) SetFlags(flag int) {
329	l.flag.Store(int32(flag))
330}
331
332// Prefix returns the output prefix for the logger.
333func (l *Logger) Prefix() string {
334	if p := l.prefix.Load(); p != nil {
335		return *p
336	}
337	return ""
338}
339
340// SetPrefix sets the output prefix for the logger.
341func (l *Logger) SetPrefix(prefix string) {
342	l.prefix.Store(&prefix)
343}
344
345// Writer returns the output destination for the logger.
346func (l *Logger) Writer() io.Writer {
347	l.outMu.Lock()
348	defer l.outMu.Unlock()
349	return l.out
350}
351
352// SetOutput sets the output destination for the standard logger.
353func SetOutput(w io.Writer) {
354	std.SetOutput(w)
355}
356
357// Flags returns the output flags for the standard logger.
358// The flag bits are [Ldate], [Ltime], and so on.
359func Flags() int {
360	return std.Flags()
361}
362
363// SetFlags sets the output flags for the standard logger.
364// The flag bits are [Ldate], [Ltime], and so on.
365func SetFlags(flag int) {
366	std.SetFlags(flag)
367}
368
369// Prefix returns the output prefix for the standard logger.
370func Prefix() string {
371	return std.Prefix()
372}
373
374// SetPrefix sets the output prefix for the standard logger.
375func SetPrefix(prefix string) {
376	std.SetPrefix(prefix)
377}
378
379// Writer returns the output destination for the standard logger.
380func Writer() io.Writer {
381	return std.Writer()
382}
383
384// These functions write to the standard logger.
385
386// Print calls Output to print to the standard logger.
387// Arguments are handled in the manner of [fmt.Print].
388func Print(v ...any) {
389	std.output(0, 2, func(b []byte) []byte {
390		return fmt.Append(b, v...)
391	})
392}
393
394// Printf calls Output to print to the standard logger.
395// Arguments are handled in the manner of [fmt.Printf].
396func Printf(format string, v ...any) {
397	std.output(0, 2, func(b []byte) []byte {
398		return fmt.Appendf(b, format, v...)
399	})
400}
401
402// Println calls Output to print to the standard logger.
403// Arguments are handled in the manner of [fmt.Println].
404func Println(v ...any) {
405	std.output(0, 2, func(b []byte) []byte {
406		return fmt.Appendln(b, v...)
407	})
408}
409
410// Fatal is equivalent to [Print] followed by a call to [os.Exit](1).
411func Fatal(v ...any) {
412	std.Output(2, fmt.Sprint(v...))
413	os.Exit(1)
414}
415
416// Fatalf is equivalent to [Printf] followed by a call to [os.Exit](1).
417func Fatalf(format string, v ...any) {
418	std.Output(2, fmt.Sprintf(format, v...))
419	os.Exit(1)
420}
421
422// Fatalln is equivalent to [Println] followed by a call to [os.Exit](1).
423func Fatalln(v ...any) {
424	std.Output(2, fmt.Sprintln(v...))
425	os.Exit(1)
426}
427
428// Panic is equivalent to [Print] followed by a call to panic().
429func Panic(v ...any) {
430	s := fmt.Sprint(v...)
431	std.Output(2, s)
432	panic(s)
433}
434
435// Panicf is equivalent to [Printf] followed by a call to panic().
436func Panicf(format string, v ...any) {
437	s := fmt.Sprintf(format, v...)
438	std.Output(2, s)
439	panic(s)
440}
441
442// Panicln is equivalent to [Println] followed by a call to panic().
443func Panicln(v ...any) {
444	s := fmt.Sprintln(v...)
445	std.Output(2, s)
446	panic(s)
447}
448
449// Output writes the output for a logging event. The string s contains
450// the text to print after the prefix specified by the flags of the
451// Logger. A newline is appended if the last character of s is not
452// already a newline. Calldepth is the count of the number of
453// frames to skip when computing the file name and line number
454// if [Llongfile] or [Lshortfile] is set; a value of 1 will print the details
455// for the caller of Output.
456func Output(calldepth int, s string) error {
457	return std.Output(calldepth+1, s) // +1 for this frame.
458}
459