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 logimport ()// 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: messageconst (Ldate = 1 << iota // the date in the local time zone: 2009/01/23Ltime // the time in the local time zone: 01:23:23Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.Llongfile // full file name and line number: /a/b/c/d.go:23Lshortfile // final file name element and line number: d.go:23. overrides LlongfileLUTC // if Ldate or Ltime is set, use UTC rather than the local time zoneLmsgprefix // move the "prefix" from the beginning of the line to before the messageLstdFlags = 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 fieldsprefix string // prefix on each line to identify the logger (but see Lmsgprefix)flag int // propertiesout io.Writer // destination for outputbuf []byte // for accumulating text to write}// 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 {return &Logger{out: , prefix: , flag: }}// SetOutput sets the output destination for the logger.func ( *Logger) ( io.Writer) {.mu.Lock()defer .mu.Unlock().out =}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() - 1for >= 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 stringvar 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, ...interface{}) {.Output(2, fmt.Sprintf(, ...))}// Print calls l.Output to print to the logger.// Arguments are handled in the manner of fmt.Print.func ( *Logger) ( ...interface{}) { .Output(2, fmt.Sprint(...)) }// Println calls l.Output to print to the logger.// Arguments are handled in the manner of fmt.Println.func ( *Logger) ( ...interface{}) { .Output(2, fmt.Sprintln(...)) }// Fatal is equivalent to l.Print() followed by a call to os.Exit(1).func ( *Logger) ( ...interface{}) {.Output(2, fmt.Sprint(...))os.Exit(1)}// Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).func ( *Logger) ( string, ...interface{}) {.Output(2, fmt.Sprintf(, ...))os.Exit(1)}// Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).func ( *Logger) ( ...interface{}) {.Output(2, fmt.Sprintln(...))os.Exit(1)}// Panic is equivalent to l.Print() followed by a call to panic().func ( *Logger) ( ...interface{}) {:= fmt.Sprint(...).Output(2, )panic()}// Panicf is equivalent to l.Printf() followed by a call to panic().func ( *Logger) ( string, ...interface{}) {:= fmt.Sprintf(, ...).Output(2, )panic()}// Panicln is equivalent to l.Println() followed by a call to panic().func ( *Logger) ( ...interface{}) {:= 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.mu.Lock()defer std.mu.Unlock()std.out =}// 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 ( ...interface{}) {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, ...interface{}) {std.Output(2, fmt.Sprintf(, ...))}// Println calls Output to print to the standard logger.// Arguments are handled in the manner of fmt.Println.func ( ...interface{}) {std.Output(2, fmt.Sprintln(...))}// Fatal is equivalent to Print() followed by a call to os.Exit(1).func ( ...interface{}) {std.Output(2, fmt.Sprint(...))os.Exit(1)}// Fatalf is equivalent to Printf() followed by a call to os.Exit(1).func ( string, ...interface{}) {std.Output(2, fmt.Sprintf(, ...))os.Exit(1)}// Fatalln is equivalent to Println() followed by a call to os.Exit(1).func ( ...interface{}) {std.Output(2, fmt.Sprintln(...))os.Exit(1)}// Panic is equivalent to Print() followed by a call to panic().func ( ...interface{}) {:= fmt.Sprint(...)std.Output(2, )panic()}// Panicf is equivalent to Printf() followed by a call to panic().func ( string, ...interface{}) {:= fmt.Sprintf(, ...)std.Output(2, )panic()}// Panicln is equivalent to Println() followed by a call to panic().func ( ...interface{}) {:= 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.}