Source File
log.go
Belonging Package
log
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package log implements a simple logging package. It defines a type, Logger,
// with methods for formatting output. It also has a predefined 'standard'
// Logger accessible through helper functions Print[f|ln], Fatal[f|ln], and
// Panic[f|ln], which are easier to use than creating a Logger manually.
// That logger writes to standard error and prints the date and time
// of each logged message.
// Every log message is output on a separate line: if the message being
// printed does not end in a newline, the logger will add one.
// The Fatal functions call os.Exit(1) after writing the log message.
// The Panic functions call panic after writing the log message.
package log
import (
)
// These flags define which text to prefix to each log entry generated by the Logger.
// Bits are or'ed together to control what's printed.
// With the exception of the Lmsgprefix flag, there is no
// control over the order they appear (the order listed here)
// or the format they present (as described in the comments).
// The prefix is followed by a colon only when Llongfile or Lshortfile
// is specified.
// For example, flags Ldate | Ltime (or LstdFlags) produce,
// 2009/01/23 01:23:23 message
// while flags Ldate | Ltime | Lmicroseconds | Llongfile produce,
// 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
const (
Ldate = 1 << iota // the date in the local time zone: 2009/01/23
Ltime // the time in the local time zone: 01:23:23
Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
Llongfile // full file name and line number: /a/b/c/d.go:23
Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone
Lmsgprefix // move the "prefix" from the beginning of the line to before the message
LstdFlags = Ldate | Ltime // initial values for the standard logger
)
// A Logger represents an active logging object that generates lines of
// output to an io.Writer. Each logging operation makes a single call to
// the Writer's Write method. A Logger can be used simultaneously from
// multiple goroutines; it guarantees to serialize access to the Writer.
type Logger struct {
mu sync.Mutex // ensures atomic writes; protects the following fields
prefix string // prefix on each line to identify the logger (but see Lmsgprefix)
flag int // properties
out io.Writer // destination for output
buf []byte // for accumulating text to write
isDiscard int32 // atomic boolean: whether out == io.Discard
}
// New creates a new Logger. The out variable sets the
// destination to which log data will be written.
// The prefix appears at the beginning of each generated log line, or
// after the log header if the Lmsgprefix flag is provided.
// The flag argument defines the logging properties.
func ( io.Writer, string, int) *Logger {
:= &Logger{out: , prefix: , flag: }
if == io.Discard {
.isDiscard = 1
}
return
}
// SetOutput sets the output destination for the logger.
func ( *Logger) ( io.Writer) {
.mu.Lock()
defer .mu.Unlock()
.out =
:= int32(0)
if == io.Discard {
= 1
}
atomic.StoreInt32(&.isDiscard, )
}
var std = New(os.Stderr, "", LstdFlags)
// Default returns the standard logger used by the package-level output functions.
func () *Logger { return std }
// Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
func ( *[]byte, int, int) {
// Assemble decimal in reverse order.
var [20]byte
:= len() - 1
for >= 10 || > 1 {
--
:= / 10
[] = byte('0' + - *10)
--
=
}
// i < 10
[] = byte('0' + )
* = append(*, [:]...)
}
// formatHeader writes log header to buf in following order:
// * l.prefix (if it's not blank and Lmsgprefix is unset),
// * date and/or time (if corresponding flags are provided),
// * file and line number (if corresponding flags are provided),
// * l.prefix (if it's not blank and Lmsgprefix is set).
func ( *Logger) ( *[]byte, time.Time, string, int) {
if .flag&Lmsgprefix == 0 {
* = append(*, .prefix...)
}
if .flag&(Ldate|Ltime|Lmicroseconds) != 0 {
if .flag&LUTC != 0 {
= .UTC()
}
if .flag&Ldate != 0 {
, , := .Date()
itoa(, , 4)
* = append(*, '/')
itoa(, int(), 2)
* = append(*, '/')
itoa(, , 2)
* = append(*, ' ')
}
if .flag&(Ltime|Lmicroseconds) != 0 {
, , := .Clock()
itoa(, , 2)
* = append(*, ':')
itoa(, , 2)
* = append(*, ':')
itoa(, , 2)
if .flag&Lmicroseconds != 0 {
* = append(*, '.')
itoa(, .Nanosecond()/1e3, 6)
}
* = append(*, ' ')
}
}
if .flag&(Lshortfile|Llongfile) != 0 {
if .flag&Lshortfile != 0 {
:=
for := len() - 1; > 0; -- {
if [] == '/' {
= [+1:]
break
}
}
=
}
* = append(*, ...)
* = append(*, ':')
itoa(, , -1)
* = append(*, ": "...)
}
if .flag&Lmsgprefix != 0 {
* = append(*, .prefix...)
}
}
// Output writes the output for a logging event. The string s contains
// the text to print after the prefix specified by the flags of the
// Logger. A newline is appended if the last character of s is not
// already a newline. Calldepth is used to recover the PC and is
// provided for generality, although at the moment on all pre-defined
// paths it will be 2.
func ( *Logger) ( int, string) error {
:= time.Now() // get this early.
var string
var int
.mu.Lock()
defer .mu.Unlock()
if .flag&(Lshortfile|Llongfile) != 0 {
// Release lock while getting caller info - it's expensive.
.mu.Unlock()
var bool
_, , , = runtime.Caller()
if ! {
= "???"
= 0
}
.mu.Lock()
}
.buf = .buf[:0]
.formatHeader(&.buf, , , )
.buf = append(.buf, ...)
if len() == 0 || [len()-1] != '\n' {
.buf = append(.buf, '\n')
}
, := .out.Write(.buf)
return
}
// Printf calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Printf.
func ( *Logger) ( string, ...any) {
if atomic.LoadInt32(&.isDiscard) != 0 {
return
}
.Output(2, fmt.Sprintf(, ...))
}
// Print calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Print.
func ( *Logger) ( ...any) {
if atomic.LoadInt32(&.isDiscard) != 0 {
return
}
.Output(2, fmt.Sprint(...))
}
// Println calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Println.
func ( *Logger) ( ...any) {
if atomic.LoadInt32(&.isDiscard) != 0 {
return
}
.Output(2, fmt.Sprintln(...))
}
// Fatal is equivalent to l.Print() followed by a call to os.Exit(1).
func ( *Logger) ( ...any) {
.Output(2, fmt.Sprint(...))
os.Exit(1)
}
// Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).
func ( *Logger) ( string, ...any) {
.Output(2, fmt.Sprintf(, ...))
os.Exit(1)
}
// Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).
func ( *Logger) ( ...any) {
.Output(2, fmt.Sprintln(...))
os.Exit(1)
}
// Panic is equivalent to l.Print() followed by a call to panic().
func ( *Logger) ( ...any) {
:= fmt.Sprint(...)
.Output(2, )
panic()
}
// Panicf is equivalent to l.Printf() followed by a call to panic().
func ( *Logger) ( string, ...any) {
:= fmt.Sprintf(, ...)
.Output(2, )
panic()
}
// Panicln is equivalent to l.Println() followed by a call to panic().
func ( *Logger) ( ...any) {
:= fmt.Sprintln(...)
.Output(2, )
panic()
}
// Flags returns the output flags for the logger.
// The flag bits are Ldate, Ltime, and so on.
func ( *Logger) () int {
.mu.Lock()
defer .mu.Unlock()
return .flag
}
// SetFlags sets the output flags for the logger.
// The flag bits are Ldate, Ltime, and so on.
func ( *Logger) ( int) {
.mu.Lock()
defer .mu.Unlock()
.flag =
}
// Prefix returns the output prefix for the logger.
func ( *Logger) () string {
.mu.Lock()
defer .mu.Unlock()
return .prefix
}
// SetPrefix sets the output prefix for the logger.
func ( *Logger) ( string) {
.mu.Lock()
defer .mu.Unlock()
.prefix =
}
// Writer returns the output destination for the logger.
func ( *Logger) () io.Writer {
.mu.Lock()
defer .mu.Unlock()
return .out
}
// SetOutput sets the output destination for the standard logger.
func ( io.Writer) {
std.SetOutput()
}
// Flags returns the output flags for the standard logger.
// The flag bits are Ldate, Ltime, and so on.
func () int {
return std.Flags()
}
// SetFlags sets the output flags for the standard logger.
// The flag bits are Ldate, Ltime, and so on.
func ( int) {
std.SetFlags()
}
// Prefix returns the output prefix for the standard logger.
func () string {
return std.Prefix()
}
// SetPrefix sets the output prefix for the standard logger.
func ( string) {
std.SetPrefix()
}
// Writer returns the output destination for the standard logger.
func () io.Writer {
return std.Writer()
}
// These functions write to the standard logger.
// Print calls Output to print to the standard logger.
// Arguments are handled in the manner of fmt.Print.
func ( ...any) {
if atomic.LoadInt32(&std.isDiscard) != 0 {
return
}
std.Output(2, fmt.Sprint(...))
}
// Printf calls Output to print to the standard logger.
// Arguments are handled in the manner of fmt.Printf.
func ( string, ...any) {
if atomic.LoadInt32(&std.isDiscard) != 0 {
return
}
std.Output(2, fmt.Sprintf(, ...))
}
// Println calls Output to print to the standard logger.
// Arguments are handled in the manner of fmt.Println.
func ( ...any) {
if atomic.LoadInt32(&std.isDiscard) != 0 {
return
}
std.Output(2, fmt.Sprintln(...))
}
// Fatal is equivalent to Print() followed by a call to os.Exit(1).
func ( ...any) {
std.Output(2, fmt.Sprint(...))
os.Exit(1)
}
// Fatalf is equivalent to Printf() followed by a call to os.Exit(1).
func ( string, ...any) {
std.Output(2, fmt.Sprintf(, ...))
os.Exit(1)
}
// Fatalln is equivalent to Println() followed by a call to os.Exit(1).
func ( ...any) {
std.Output(2, fmt.Sprintln(...))
os.Exit(1)
}
// Panic is equivalent to Print() followed by a call to panic().
func ( ...any) {
:= fmt.Sprint(...)
std.Output(2, )
panic()
}
// Panicf is equivalent to Printf() followed by a call to panic().
func ( string, ...any) {
:= fmt.Sprintf(, ...)
std.Output(2, )
panic()
}
// Panicln is equivalent to Println() followed by a call to panic().
func ( ...any) {
:= fmt.Sprintln(...)
std.Output(2, )
panic()
}
// Output writes the output for a logging event. The string s contains
// the text to print after the prefix specified by the flags of the
// Logger. A newline is appended if the last character of s is not
// already a newline. Calldepth is the count of the number of
// frames to skip when computing the file name and line number
// if Llongfile or Lshortfile is set; a value of 1 will print the details
// for the caller of Output.
func ( int, string) error {
return std.Output(+1, ) // +1 for this frame.
}
The pages are generated with Golds v0.4.9. (GOOS=linux GOARCH=amd64)